qtpropertybrowser.cpp
Go to the documentation of this file.
1/****************************************************************************
2**
3** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the Qt Solutions component.
7**
8** $QT_BEGIN_LICENSE:BSD$
9** You may use this file under the terms of the BSD license as follows:
10**
11** "Redistribution and use in source and binary forms, with or without
12** modification, are permitted provided that the following conditions are
13** met:
14** * Redistributions of source code must retain the above copyright
15** notice, this list of conditions and the following disclaimer.
16** * Redistributions in binary form must reproduce the above copyright
17** notice, this list of conditions and the following disclaimer in
18** the documentation and/or other materials provided with the
19** distribution.
20** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
21** of its contributors may be used to endorse or promote products derived
22** from this software without specific prior written permission.
23**
24**
25** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36**
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41
42#include "qtpropertybrowser.h"
43
44#include <QIcon>
45#include <QLineEdit>
46#include <QMap>
47#include <QSet>
48
49#if defined(Q_CC_MSVC)
50#pragma warning(disable : 4786) /* MS VS 6: truncating debug info after 255 characters */
51#endif
52
53QT_BEGIN_NAMESPACE
54
56{
57public:
59 m_enabled(true), m_modified(false), m_manager(manager)
60 {
61 }
62
64
65 QSet<QtProperty*> m_parentItems;
66 QList<QtProperty*> m_subItems;
67
68 QString m_toolTip;
69 QString m_statusTip;
70 QString m_whatsThis;
71 QString m_name;
74
76};
77
79{
81 Q_DECLARE_PUBLIC(QtAbstractPropertyManager)
82public:
83 void propertyDestroyed(QtProperty* property);
84 void propertyChanged(QtProperty* property) const;
85 void propertyRemoved(QtProperty* property, QtProperty* parentProperty) const;
86 void propertyInserted(QtProperty* property,
87 QtProperty* parentProperty,
88 QtProperty* afterProperty) const;
89
90 QSet<QtProperty*> m_properties;
91};
92
93/*!
94 \class QtProperty
95
96 \brief The QtProperty class encapsulates an instance of a property.
97
98 Properties are created by objects of QtAbstractPropertyManager
99 subclasses; a manager can create properties of a given type, and
100 is used in conjunction with the QtAbstractPropertyBrowser class. A
101 property is always owned by the manager that created it, which can
102 be retrieved using the propertyManager() function.
103
104 QtProperty contains the most common property attributes, and
105 provides functions for retrieving as well as setting their values:
106
107 \table
108 \header \o Getter \o Setter
109 \row
110 \o propertyName() \o setPropertyName()
111 \row
112 \o statusTip() \o setStatusTip()
113 \row
114 \o toolTip() \o setToolTip()
115 \row
116 \o whatsThis() \o setWhatsThis()
117 \row
118 \o isEnabled() \o setEnabled()
119 \row
120 \o isModified() \o setModified()
121 \row
122 \o valueText() \o Nop
123 \row
124 \o valueIcon() \o Nop
125 \endtable
126
127 It is also possible to nest properties: QtProperty provides the
128 addSubProperty(), insertSubProperty() and removeSubProperty() functions to
129 manipulate the set of subproperties. Use the subProperties()
130 function to retrieve a property's current set of subproperties.
131 Note that nested properties are not owned by the parent property,
132 i.e. each subproperty is owned by the manager that created it.
133
134 \sa QtAbstractPropertyManager, QtBrowserItem
135*/
136
137/*!
138 Creates a property with the given \a manager.
139
140 This constructor is only useful when creating a custom QtProperty
141 subclass (e.g. QtVariantProperty). To create a regular QtProperty
142 object, use the QtAbstractPropertyManager::addProperty()
143 function instead.
144
145 \sa QtAbstractPropertyManager::addProperty()
146*/
148{
149 d_ptr = new QtPropertyPrivate(manager);
150 d_ptr->q_ptr = this;
151}
152
153/*!
154 Destroys this property.
155
156 Note that subproperties are detached but not destroyed, i.e. they
157 can still be used in another context.
158
159 \sa QtAbstractPropertyManager::clear()
160
161*/
163{
164 QSetIterator<QtProperty*> itParent(d_ptr->m_parentItems);
165
166 while (itParent.hasNext())
167 {
168 QtProperty* property = itParent.next();
169 property->d_ptr->m_manager->d_ptr->propertyRemoved(this, property);
170 }
171
172 d_ptr->m_manager->d_ptr->propertyDestroyed(this);
173
174 QListIterator<QtProperty*> itChild(d_ptr->m_subItems);
175
176 while (itChild.hasNext())
177 {
178 QtProperty* property = itChild.next();
179 property->d_ptr->m_parentItems.remove(this);
180 }
181
182 itParent.toFront();
183
184 while (itParent.hasNext())
185 {
186 QtProperty* property = itParent.next();
187 property->d_ptr->m_subItems.removeAll(this);
188 }
189
190 delete d_ptr;
191}
192
193/*!
194 Returns the set of subproperties.
195
196 Note that subproperties are not owned by \e this property, but by
197 the manager that created them.
198
199 \sa insertSubProperty(), removeSubProperty()
200*/
201QList<QtProperty*>
203{
204 return d_ptr->m_subItems;
205}
206
207/*!
208 Returns a pointer to the manager that owns this property.
209*/
212{
213 return d_ptr->m_manager;
214}
215
216/*!
217 Returns the property's tool tip.
218
219 \sa setToolTip()
220*/
221QString
223{
224 return d_ptr->m_toolTip;
225}
226
227/*!
228 Returns the property's status tip.
229
230 \sa setStatusTip()
231*/
232QString
234{
235 return d_ptr->m_statusTip;
236}
237
238/*!
239 Returns the property's "What's This" help text.
240
241 \sa setWhatsThis()
242*/
243QString
245{
246 return d_ptr->m_whatsThis;
247}
248
249/*!
250 Returns the property's name.
251
252 \sa setPropertyName()
253*/
254QString
256{
257 return d_ptr->m_name;
258}
259
260/*!
261 Returns whether the property is enabled.
262
263 \sa setEnabled()
264*/
265bool
267{
268 return d_ptr->m_enabled;
269}
270
271/*!
272 Returns whether the property is modified.
273
274 \sa setModified()
275*/
276bool
278{
279 return d_ptr->m_modified;
280}
281
282/*!
283 Returns whether the property has a value.
284
285 \sa QtAbstractPropertyManager::hasValue()
286*/
287bool
289{
290 return d_ptr->m_manager->hasValue(this);
291}
292
293/*!
294 Returns an icon representing the current state of this property.
295
296 If the given property type can not generate such an icon, this
297 function returns an invalid icon.
298
299 \sa QtAbstractPropertyManager::valueIcon()
300*/
301QIcon
303{
304 return d_ptr->m_manager->valueIcon(this);
305}
306
307/*!
308 Returns a string representing the current state of this property.
309
310 If the given property type can not generate such a string, this
311 function returns an empty string.
312
313 \sa QtAbstractPropertyManager::valueText()
314*/
315QString
317{
318 return d_ptr->m_manager->valueText(this);
319}
320
321/*!
322 Returns the display text according to the echo-mode set on the editor.
323
324 When the editor is a QLineEdit, this will return a string equal to what
325 is displayed.
326
327 \sa QtAbstractPropertyManager::valueText()
328*/
329QString
331{
332 return d_ptr->m_manager->displayText(this);
333}
334
335/*!
336 Sets the property's tool tip to the given \a text.
337
338 \sa toolTip()
339*/
340void
341QtProperty::setToolTip(const QString& text)
342{
343 if (d_ptr->m_toolTip == text)
344 {
345 return;
346 }
347
348 d_ptr->m_toolTip = text;
350}
351
352/*!
353 Sets the property's status tip to the given \a text.
354
355 \sa statusTip()
356*/
357void
358QtProperty::setStatusTip(const QString& text)
359{
360 if (d_ptr->m_statusTip == text)
361 {
362 return;
363 }
364
365 d_ptr->m_statusTip = text;
367}
368
369/*!
370 Sets the property's "What's This" help text to the given \a text.
371
372 \sa whatsThis()
373*/
374void
375QtProperty::setWhatsThis(const QString& text)
376{
377 if (d_ptr->m_whatsThis == text)
378 {
379 return;
380 }
381
382 d_ptr->m_whatsThis = text;
384}
385
386/*!
387 \fn void QtProperty::setPropertyName(const QString &name)
388
389 Sets the property's name to the given \a name.
390
391 \sa propertyName()
392*/
393void
394QtProperty::setPropertyName(const QString& text)
395{
396 if (d_ptr->m_name == text)
397 {
398 return;
399 }
400
401 d_ptr->m_name = text;
403}
404
405/*!
406 Enables or disables the property according to the passed \a enable value.
407
408 \sa isEnabled()
409*/
410void
412{
413 if (d_ptr->m_enabled == enable)
414 {
415 return;
416 }
417
418 d_ptr->m_enabled = enable;
420}
421
422/*!
423 Sets the property's modified state according to the passed \a modified value.
424
425 \sa isModified()
426*/
427void
429{
430 if (d_ptr->m_modified == modified)
431 {
432 return;
433 }
434
435 d_ptr->m_modified = modified;
437}
438
439/*!
440 Appends the given \a property to this property's subproperties.
441
442 If the given \a property already is added, this function does
443 nothing.
444
445 \sa insertSubProperty(), removeSubProperty()
446*/
447void
449{
450 QtProperty* after = 0;
451
452 if (d_ptr->m_subItems.count() > 0)
453 {
454 after = d_ptr->m_subItems.last();
455 }
456
457 insertSubProperty(property, after);
458}
459
460/*!
461 \fn void QtProperty::insertSubProperty(QtProperty *property, QtProperty *precedingProperty)
462
463 Inserts the given \a property after the specified \a
464 precedingProperty into this property's list of subproperties. If
465 \a precedingProperty is 0, the specified \a property is inserted
466 at the beginning of the list.
467
468 If the given \a property already is inserted, this function does
469 nothing.
470
471 \sa addSubProperty(), removeSubProperty()
472*/
473void
475{
476 if (!property)
477 {
478 return;
479 }
480
481 if (property == this)
482 {
483 return;
484 }
485
486 // traverse all children of item. if this item is a child of item then cannot add.
487 QList<QtProperty*> pendingList = property->subProperties();
488 QMap<QtProperty*, bool> visited;
489
490 while (!pendingList.isEmpty())
491 {
492 QtProperty* i = pendingList.first();
493
494 if (i == this)
495 {
496 return;
497 }
498
499 pendingList.removeFirst();
500
501 if (visited.contains(i))
502 {
503 continue;
504 }
505
506 visited[i] = true;
507 pendingList += i->subProperties();
508 }
509
510 pendingList = subProperties();
511 int pos = 0;
512 int newPos = 0;
513 QtProperty* properAfterProperty = 0;
514
515 while (pos < pendingList.count())
516 {
517 QtProperty* i = pendingList.at(pos);
518
519 if (i == property)
520 {
521 return; // if item is already inserted in this item then cannot add.
522 }
523
524 if (i == afterProperty)
525 {
526 newPos = pos + 1;
527 properAfterProperty = afterProperty;
528 }
529
530 pos++;
531 }
532
533 d_ptr->m_subItems.insert(newPos, property);
534 property->d_ptr->m_parentItems.insert(this);
535
536 d_ptr->m_manager->d_ptr->propertyInserted(property, this, properAfterProperty);
537}
538
539/*!
540 Removes the given \a property from the list of subproperties
541 without deleting it.
542
543 \sa addSubProperty(), insertSubProperty()
544*/
545void
547{
548 if (!property)
549 {
550 return;
551 }
552
553 d_ptr->m_manager->d_ptr->propertyRemoved(property, this);
554
555 QList<QtProperty*> pendingList = subProperties();
556 int pos = 0;
557
558 while (pos < pendingList.count())
559 {
560 if (pendingList.at(pos) == property)
561 {
562 d_ptr->m_subItems.removeAt(pos);
563 property->d_ptr->m_parentItems.remove(this);
564
565 return;
566 }
567
568 pos++;
569 }
570}
571
572/*!
573 \internal
574*/
575void
577{
578 d_ptr->m_manager->d_ptr->propertyChanged(this);
579}
580
581////////////////////////////////
582
583void
585{
586 if (m_properties.contains(property))
587 {
588 emit q_ptr->propertyDestroyed(property);
589 q_ptr->uninitializeProperty(property);
590 m_properties.remove(property);
591 }
592}
593
594void
596{
597 emit q_ptr->propertyChanged(property);
598}
599
600void
602 QtProperty* parentProperty) const
603{
604 emit q_ptr->propertyRemoved(property, parentProperty);
605}
606
607void
609 QtProperty* parentProperty,
610 QtProperty* afterProperty) const
611{
612 emit q_ptr->propertyInserted(property, parentProperty, afterProperty);
613}
614
615/*!
616 \class QtAbstractPropertyManager
617
618 \brief The QtAbstractPropertyManager provides an interface for
619 property managers.
620
621 A manager can create and manage properties of a given type, and is
622 used in conjunction with the QtAbstractPropertyBrowser class.
623
624 When using a property browser widget, the properties are created
625 and managed by implementations of the QtAbstractPropertyManager
626 class. To ensure that the properties' values will be displayed
627 using suitable editing widgets, the managers are associated with
628 objects of QtAbstractEditorFactory subclasses. The property browser
629 will use these associations to determine which factories it should
630 use to create the preferred editing widgets.
631
632 The QtAbstractPropertyManager class provides common functionality
633 like creating a property using the addProperty() function, and
634 retrieving the properties created by the manager using the
635 properties() function. The class also provides signals that are
636 emitted when the manager's properties change: propertyInserted(),
637 propertyRemoved(), propertyChanged() and propertyDestroyed().
638
639 QtAbstractPropertyManager subclasses are supposed to provide their
640 own type specific API. Note that several ready-made
641 implementations are available:
642
643 \list
644 \o QtBoolPropertyManager
645 \o QtColorPropertyManager
646 \o QtDatePropertyManager
647 \o QtDateTimePropertyManager
648 \o QtDoublePropertyManager
649 \o QtEnumPropertyManager
650 \o QtFlagPropertyManager
651 \o QtFontPropertyManager
652 \o QtGroupPropertyManager
653 \o QtIntPropertyManager
654 \o QtPointPropertyManager
655 \o QtRectPropertyManager
656 \o QtSizePropertyManager
657 \o QtSizePolicyPropertyManager
658 \o QtStringPropertyManager
659 \o QtTimePropertyManager
660 \o QtVariantPropertyManager
661 \endlist
662
663 \sa QtAbstractEditorFactoryBase, QtAbstractPropertyBrowser, QtProperty
664*/
665
666/*!
667 \fn void QtAbstractPropertyManager::propertyInserted(QtProperty *newProperty,
668 QtProperty *parentProperty, QtProperty *precedingProperty)
669
670 This signal is emitted when a new subproperty is inserted into an
671 existing property, passing pointers to the \a newProperty, \a
672 parentProperty and \a precedingProperty as parameters.
673
674 If \a precedingProperty is 0, the \a newProperty was inserted at
675 the beginning of the \a parentProperty's subproperties list.
676
677 Note that signal is emitted only if the \a parentProperty is created
678 by this manager.
679
680 \sa QtAbstractPropertyBrowser::itemInserted()
681*/
682
683/*!
684 \fn void QtAbstractPropertyManager::propertyChanged(QtProperty *property)
685
686 This signal is emitted whenever a property's data changes, passing
687 a pointer to the \a property as parameter.
688
689 Note that signal is only emitted for properties that are created by
690 this manager.
691
692 \sa QtAbstractPropertyBrowser::itemChanged()
693*/
694
695/*!
696 \fn void QtAbstractPropertyManager::propertyRemoved(QtProperty *property, QtProperty *parent)
697
698 This signal is emitted when a subproperty is removed, passing
699 pointers to the removed \a property and the \a parent property as
700 parameters.
701
702 Note that signal is emitted only when the \a parent property is
703 created by this manager.
704
705 \sa QtAbstractPropertyBrowser::itemRemoved()
706*/
707
708/*!
709 \fn void QtAbstractPropertyManager::propertyDestroyed(QtProperty *property)
710
711 This signal is emitted when the specified \a property is about to
712 be destroyed.
713
714 Note that signal is only emitted for properties that are created
715 by this manager.
716
717 \sa clear(), uninitializeProperty()
718*/
719
720/*!
721 \fn void QtAbstractPropertyBrowser::currentItemChanged(QtBrowserItem *current)
722
723 This signal is emitted when the current item changes. The current item is specified by \a current.
724
725 \sa QtAbstractPropertyBrowser::setCurrentItem()
726*/
727
728/*!
729 Creates an abstract property manager with the given \a parent.
730*/
732{
734 d_ptr->q_ptr = this;
735}
736
737/*!
738 Destroys the manager. All properties created by the manager are
739 destroyed.
740*/
746
747/*!
748 Destroys all the properties that this manager has created.
749
750 \sa propertyDestroyed(), uninitializeProperty()
751*/
752void
754{
755 while (!properties().isEmpty())
756 {
757 QSetIterator<QtProperty*> itProperty(properties());
758 QtProperty* prop = itProperty.next();
759 delete prop;
760 }
761}
762
763/*!
764 Returns the set of properties created by this manager.
765
766 \sa addProperty()
767*/
768QSet<QtProperty*>
770{
771 return d_ptr->m_properties;
772}
773
774/*!
775 Returns whether the given \a property has a value.
776
777 The default implementation of this function returns true.
778
779 \sa QtProperty::hasValue()
780*/
781bool
783{
784 Q_UNUSED(property)
785 return true;
786}
787
788/*!
789 Returns an icon representing the current state of the given \a
790 property.
791
792 The default implementation of this function returns an invalid
793 icon.
794
795 \sa QtProperty::valueIcon()
796*/
797QIcon
799{
800 Q_UNUSED(property)
801 return QIcon();
802}
803
804/*!
805 Returns a string representing the current state of the given \a
806 property.
807
808 The default implementation of this function returns an empty
809 string.
810
811 \sa QtProperty::valueText()
812*/
813QString
815{
816 Q_UNUSED(property)
817 return QString();
818}
819
820/*!
821 Returns a string representing the current state of the given \a
822 property.
823
824 The default implementation of this function returns an empty
825 string.
826
827 \sa QtProperty::valueText()
828*/
829QString
831{
832 Q_UNUSED(property)
833 return QString();
834}
835
836/*!
837 Returns the echo mode representing the current state of the given \a
838 property.
839
840 The default implementation of this function returns QLineEdit::Normal.
841
842 \sa QtProperty::valueText()
843*/
846{
847 Q_UNUSED(property)
848 return QLineEdit::Normal;
849}
850
851/*!
852 Creates a property with the given \a name which then is owned by this manager.
853
854 Internally, this function calls the createProperty() and
855 initializeProperty() functions.
856
857 \sa initializeProperty(), properties()
858*/
861{
862 QtProperty* property = createProperty();
863
864 if (property)
865 {
866 property->setPropertyName(name);
867 d_ptr->m_properties.insert(property);
868 initializeProperty(property);
869 }
870
871 return property;
872}
873
874/*!
875 Creates a property.
876
877 The base implementation produce QtProperty instances; Reimplement
878 this function to make this manager produce objects of a QtProperty
879 subclass.
880
881 \sa addProperty(), initializeProperty()
882*/
888
889/*!
890 \fn void QtAbstractPropertyManager::initializeProperty(QtProperty *property) = 0
891
892 This function is called whenever a new valid property pointer has
893 been created, passing the pointer as parameter.
894
895 The purpose is to let the manager know that the \a property has
896 been created so that it can provide additional attributes for the
897 new property, e.g. QtIntPropertyManager adds \l
898 {QtIntPropertyManager::value()}{value}, \l
899 {QtIntPropertyManager::minimum()}{minimum} and \l
900 {QtIntPropertyManager::maximum()}{maximum} attributes. Since each manager
901 subclass adds type specific attributes, this function is pure
902 virtual and must be reimplemented when deriving from the
903 QtAbstractPropertyManager class.
904
905 \sa addProperty(), createProperty()
906*/
907
908/*!
909 This function is called just before the specified \a property is destroyed.
910
911 The purpose is to let the property manager know that the \a
912 property is being destroyed so that it can remove the property's
913 additional attributes.
914
915 \sa clear(), propertyDestroyed()
916*/
917void
919{
920 Q_UNUSED(property)
921}
922
923////////////////////////////////////
924
925/*!
926 \class QtAbstractEditorFactoryBase
927
928 \brief The QtAbstractEditorFactoryBase provides an interface for
929 editor factories.
930
931 An editor factory is a class that is able to create an editing
932 widget of a specified type (e.g. line edits or comboboxes) for a
933 given QtProperty object, and it is used in conjunction with the
934 QtAbstractPropertyManager and QtAbstractPropertyBrowser classes.
935
936 When using a property browser widget, the properties are created
937 and managed by implementations of the QtAbstractPropertyManager
938 class. To ensure that the properties' values will be displayed
939 using suitable editing widgets, the managers are associated with
940 objects of QtAbstractEditorFactory subclasses. The property browser
941 will use these associations to determine which factories it should
942 use to create the preferred editing widgets.
943
944 Typically, an editor factory is created by subclassing the
945 QtAbstractEditorFactory template class which inherits
946 QtAbstractEditorFactoryBase. But note that several ready-made
947 implementations are available:
948
949 \list
950 \o QtCheckBoxFactory
951 \o QtDateEditFactory
952 \o QtDateTimeEditFactory
953 \o QtDoubleSpinBoxFactory
954 \o QtEnumEditorFactory
955 \o QtLineEditFactory
956 \o QtScrollBarFactory
957 \o QtSliderFactory
958 \o QtSpinBoxFactory
959 \o QtTimeEditFactory
960 \o QtVariantEditorFactory
961 \endlist
962
963 \sa QtAbstractPropertyManager, QtAbstractPropertyBrowser
964*/
965
966/*!
967 \fn virtual QWidget *QtAbstractEditorFactoryBase::createEditor(QtProperty *property,
968 QWidget *parent) = 0
969
970 Creates an editing widget (with the given \a parent) for the given
971 \a property.
972
973 This function is reimplemented in QtAbstractEditorFactory template class
974 which also provides a pure virtual convenience overload of this
975 function enabling access to the property's manager.
976
977 \sa QtAbstractEditorFactory::createEditor()
978*/
979
980/*!
981 \fn QtAbstractEditorFactoryBase::QtAbstractEditorFactoryBase(QObject *parent = 0)
982
983 Creates an abstract editor factory with the given \a parent.
984*/
985
986/*!
987 \fn virtual void QtAbstractEditorFactoryBase::breakConnection(QtAbstractPropertyManager *manager) = 0
988
989 \internal
990
991 Detaches property manager from factory.
992 This method is reimplemented in QtAbstractEditorFactory template subclass.
993 You don't need to reimplement it in your subclasses. Instead implement more convenient
994 QtAbstractEditorFactory::disconnectPropertyManager() which gives you access to particular manager subclass.
995*/
996
997/*!
998 \fn virtual void QtAbstractEditorFactoryBase::managerDestroyed(QObject *manager) = 0
999
1000 \internal
1001
1002 This method is called when property manager is being destroyed.
1003 Basically it notifies factory not to produce editors for properties owned by \a manager.
1004 You don't need to reimplement it in your subclass. This method is implemented in
1005 QtAbstractEditorFactory template subclass.
1006*/
1007
1008/*!
1009 \class QtAbstractEditorFactory
1010
1011 \brief The QtAbstractEditorFactory is the base template class for editor
1012 factories.
1013
1014 An editor factory is a class that is able to create an editing
1015 widget of a specified type (e.g. line edits or comboboxes) for a
1016 given QtProperty object, and it is used in conjunction with the
1017 QtAbstractPropertyManager and QtAbstractPropertyBrowser classes.
1018
1019 Note that the QtAbstractEditorFactory functions are using the
1020 PropertyManager template argument class which can be any
1021 QtAbstractPropertyManager subclass. For example:
1022
1023 \code
1024 QtSpinBoxFactory *factory;
1025 QSet<QtIntPropertyManager *> managers = factory->propertyManagers();
1026 \endcode
1027
1028 Note that QtSpinBoxFactory by definition creates editing widgets
1029 \e only for properties created by QtIntPropertyManager.
1030
1031 When using a property browser widget, the properties are created
1032 and managed by implementations of the QtAbstractPropertyManager
1033 class. To ensure that the properties' values will be displayed
1034 using suitable editing widgets, the managers are associated with
1035 objects of QtAbstractEditorFactory subclasses. The property browser will
1036 use these associations to determine which factories it should use
1037 to create the preferred editing widgets.
1038
1039 A QtAbstractEditorFactory object is capable of producing editors for
1040 several property managers at the same time. To create an
1041 association between this factory and a given manager, use the
1042 addPropertyManager() function. Use the removePropertyManager() function to make
1043 this factory stop producing editors for a given property
1044 manager. Use the propertyManagers() function to retrieve the set of
1045 managers currently associated with this factory.
1046
1047 Several ready-made implementations of the QtAbstractEditorFactory class
1048 are available:
1049
1050 \list
1051 \o QtCheckBoxFactory
1052 \o QtDateEditFactory
1053 \o QtDateTimeEditFactory
1054 \o QtDoubleSpinBoxFactory
1055 \o QtEnumEditorFactory
1056 \o QtLineEditFactory
1057 \o QtScrollBarFactory
1058 \o QtSliderFactory
1059 \o QtSpinBoxFactory
1060 \o QtTimeEditFactory
1061 \o QtVariantEditorFactory
1062 \endlist
1063
1064 When deriving from the QtAbstractEditorFactory class, several pure virtual
1065 functions must be implemented: the connectPropertyManager() function is
1066 used by the factory to connect to the given manager's signals, the
1067 createEditor() function is supposed to create an editor for the
1068 given property controlled by the given manager, and finally the
1069 disconnectPropertyManager() function is used by the factory to disconnect
1070 from the specified manager's signals.
1071
1072 \sa QtAbstractEditorFactoryBase, QtAbstractPropertyManager
1073*/
1074
1075/*!
1076 \fn QtAbstractEditorFactory::QtAbstractEditorFactory(QObject *parent = 0)
1077
1078 Creates an editor factory with the given \a parent.
1079
1080 \sa addPropertyManager()
1081*/
1082
1083/*!
1084 \fn QWidget *QtAbstractEditorFactory::createEditor(QtProperty *property, QWidget *parent)
1085
1086 Creates an editing widget (with the given \a parent) for the given
1087 \a property.
1088*/
1089
1090/*!
1091 \fn void QtAbstractEditorFactory::addPropertyManager(PropertyManager *manager)
1092
1093 Adds the given \a manager to this factory's set of managers,
1094 making this factory produce editing widgets for properties created
1095 by the given manager.
1096
1097 The PropertyManager type is a template argument class, and represents the chosen
1098 QtAbstractPropertyManager subclass.
1099
1100 \sa propertyManagers(), removePropertyManager()
1101*/
1102
1103/*!
1104 \fn void QtAbstractEditorFactory::removePropertyManager(PropertyManager *manager)
1105
1106 Removes the given \a manager from this factory's set of
1107 managers. The PropertyManager type is a template argument class, and may be
1108 any QtAbstractPropertyManager subclass.
1109
1110 \sa propertyManagers(), addPropertyManager()
1111*/
1112
1113/*!
1114 \fn virtual void QtAbstractEditorFactory::connectPropertyManager(PropertyManager *manager) = 0
1115
1116 Connects this factory to the given \a manager's signals. The
1117 PropertyManager type is a template argument class, and represents
1118 the chosen QtAbstractPropertyManager subclass.
1119
1120 This function is used internally by the addPropertyManager() function, and
1121 makes it possible to update an editing widget when the associated
1122 property's data changes. This is typically done in custom slots
1123 responding to the signals emitted by the property's manager,
1124 e.g. QtIntPropertyManager::valueChanged() and
1125 QtIntPropertyManager::rangeChanged().
1126
1127 \sa propertyManagers(), disconnectPropertyManager()
1128*/
1129
1130/*!
1131 \fn virtual QWidget *QtAbstractEditorFactory::createEditor(PropertyManager *manager, QtProperty *property,
1132 QWidget *parent) = 0
1133
1134 Creates an editing widget with the given \a parent for the
1135 specified \a property created by the given \a manager. The
1136 PropertyManager type is a template argument class, and represents
1137 the chosen QtAbstractPropertyManager subclass.
1138
1139 This function must be implemented in derived classes: It is
1140 recommended to store a pointer to the widget and map it to the
1141 given \a property, since the widget must be updated whenever the
1142 associated property's data changes. This is typically done in
1143 custom slots responding to the signals emitted by the property's
1144 manager, e.g. QtIntPropertyManager::valueChanged() and
1145 QtIntPropertyManager::rangeChanged().
1146
1147 \sa connectPropertyManager()
1148*/
1149
1150/*!
1151 \fn virtual void QtAbstractEditorFactory::disconnectPropertyManager(PropertyManager *manager) = 0
1152
1153 Disconnects this factory from the given \a manager's signals. The
1154 PropertyManager type is a template argument class, and represents
1155 the chosen QtAbstractPropertyManager subclass.
1156
1157 This function is used internally by the removePropertyManager() function.
1158
1159 \sa propertyManagers(), connectPropertyManager()
1160*/
1161
1162/*!
1163 \fn QSet<PropertyManager *> QtAbstractEditorFactory::propertyManagers() const
1164
1165 Returns the factory's set of associated managers. The
1166 PropertyManager type is a template argument class, and represents
1167 the chosen QtAbstractPropertyManager subclass.
1168
1169 \sa addPropertyManager(), removePropertyManager()
1170*/
1171
1172/*!
1173 \fn PropertyManager *QtAbstractEditorFactory::propertyManager(QtProperty *property) const
1174
1175 Returns the property manager for the given \a property, or 0 if
1176 the given \a property doesn't belong to any of this factory's
1177 registered managers.
1178
1179 The PropertyManager type is a template argument class, and represents the chosen
1180 QtAbstractPropertyManager subclass.
1181
1182 \sa propertyManagers()
1183*/
1184
1185/*!
1186 \fn virtual void QtAbstractEditorFactory::managerDestroyed(QObject *manager)
1187
1188 \internal
1189 \reimp
1190*/
1191
1192////////////////////////////////////
1194{
1195public:
1197 QtProperty* property,
1198 QtBrowserItem* parent) :
1199 m_browser(browser), m_property(property), m_parent(parent), q_ptr(0)
1200 {
1201 }
1202
1205
1209
1211
1212 QList<QtBrowserItem*> m_children;
1213};
1214
1215void
1217{
1218 if (m_children.contains(index))
1219 {
1220 return;
1221 }
1222
1223 int idx = m_children.indexOf(after) +
1224 1; // we insert after returned idx, if it was -1 then we set idx to 0;
1225 m_children.insert(idx, index);
1226}
1227
1228void
1233
1234/*!
1235 \class QtBrowserItem
1236
1237 \brief The QtBrowserItem class represents a property in
1238 a property browser instance.
1239
1240 Browser items are created whenever a QtProperty is inserted to the
1241 property browser. A QtBrowserItem uniquely identifies a
1242 browser's item. Thus, if the same QtProperty is inserted multiple
1243 times, each occurrence gets its own unique QtBrowserItem. The
1244 items are owned by QtAbstractPropertyBrowser and automatically
1245 deleted when they are removed from the browser.
1246
1247 You can traverse a browser's properties by calling parent() and
1248 children(). The property and the browser associated with an item
1249 are available as property() and browser().
1250
1251 \sa QtAbstractPropertyBrowser, QtProperty
1252*/
1253
1254/*!
1255 Returns the property which is accosiated with this item. Note that
1256 several items can be associated with the same property instance in
1257 the same property browser.
1258
1259 \sa QtAbstractPropertyBrowser::items()
1260*/
1261
1264{
1265 return d_ptr->m_property;
1266}
1267
1268/*!
1269 Returns the parent item of \e this item. Returns 0 if \e this item
1270 is associated with top-level property in item's property browser.
1271
1272 \sa children()
1273*/
1274
1277{
1278 return d_ptr->m_parent;
1279}
1280
1281/*!
1282 Returns the children items of \e this item. The properties
1283 reproduced from children items are always the same as
1284 reproduced from associated property' children, for example:
1285
1286 \code
1287 QtBrowserItem *item;
1288 QList<QtBrowserItem *> childrenItems = item->children();
1289
1290 QList<QtProperty *> childrenProperties = item->property()->subProperties();
1291 \endcode
1292
1293 The \e childrenItems list represents the same list as \e childrenProperties.
1294*/
1295
1296QList<QtBrowserItem*>
1298{
1299 return d_ptr->m_children;
1300}
1301
1302/*!
1303 Returns the property browser which owns \e this item.
1304*/
1305
1308{
1309 return d_ptr->m_browser;
1310}
1311
1312QtBrowserItem::QtBrowserItem(QtAbstractPropertyBrowser* browser,
1313 QtProperty* property,
1314 QtBrowserItem* parent)
1315{
1317 d_ptr->q_ptr = this;
1318}
1319
1320QtBrowserItem::~QtBrowserItem()
1321{
1322 delete d_ptr;
1323}
1324
1325////////////////////////////////////
1326
1327typedef QMap<QtAbstractPropertyBrowser*,
1328 QMap<QtAbstractPropertyManager*, QtAbstractEditorFactoryBase*>>
1330typedef QMap<QtAbstractPropertyManager*,
1331 QMap<QtAbstractEditorFactoryBase*, QList<QtAbstractPropertyBrowser*>>>
1333Q_GLOBAL_STATIC(Map1, m_viewToManagerToFactory)
1334Q_GLOBAL_STATIC(Map2, m_managerToFactoryToViews)
1335
1337{
1339 Q_DECLARE_PUBLIC(QtAbstractPropertyBrowser)
1340public:
1342
1343 void insertSubTree(QtProperty* property, QtProperty* parentProperty);
1344 void removeSubTree(QtProperty* property, QtProperty* parentProperty);
1345 void createBrowserIndexes(QtProperty* property,
1346 QtProperty* parentProperty,
1347 QtProperty* afterProperty);
1348 void removeBrowserIndexes(QtProperty* property, QtProperty* parentProperty);
1350 createBrowserIndex(QtProperty* property, QtBrowserItem* parentIndex, QtBrowserItem* afterIndex);
1353
1354 void slotPropertyInserted(QtProperty* property,
1355 QtProperty* parentProperty,
1356 QtProperty* afterProperty);
1357 void slotPropertyRemoved(QtProperty* property, QtProperty* parentProperty);
1358 void slotPropertyDestroyed(QtProperty* property);
1359 void slotPropertyDataChanged(QtProperty* property);
1360
1361 QList<QtProperty*> m_subItems;
1362 QMap<QtAbstractPropertyManager*, QList<QtProperty*>> m_managerToProperties;
1363 QMap<QtProperty*, QList<QtProperty*>> m_propertyToParents;
1364
1365 QMap<QtProperty*, QtBrowserItem*> m_topLevelPropertyToIndex;
1366 QList<QtBrowserItem*> m_topLevelIndexes;
1367 QMap<QtProperty*, QList<QtBrowserItem*>> m_propertyToIndexes;
1368
1370};
1371
1375
1376void
1378{
1379 if (m_propertyToParents.contains(property))
1380 {
1381 // property was already inserted, so its manager is connected
1382 // and all its children are inserted and theirs managers are connected
1383 // we just register new parent (parent has to be new).
1384 m_propertyToParents[property].append(parentProperty);
1385 // don't need to update m_managerToProperties map since
1386 // m_managerToProperties[manager] already contains property.
1387 return;
1388 }
1389
1390 QtAbstractPropertyManager* manager = property->propertyManager();
1391
1392 if (m_managerToProperties[manager].isEmpty())
1393 {
1394 // connect manager's signals
1395 q_ptr->connect(manager,
1396 SIGNAL(propertyInserted(QtProperty*, QtProperty*, QtProperty*)),
1397 q_ptr,
1399 q_ptr->connect(manager,
1400 SIGNAL(propertyRemoved(QtProperty*, QtProperty*)),
1401 q_ptr,
1403 q_ptr->connect(manager,
1404 SIGNAL(propertyDestroyed(QtProperty*)),
1405 q_ptr,
1407 q_ptr->connect(manager,
1408 SIGNAL(propertyChanged(QtProperty*)),
1409 q_ptr,
1411 }
1412
1413 m_managerToProperties[manager].append(property);
1414 m_propertyToParents[property].append(parentProperty);
1415
1416 QList<QtProperty*> subList = property->subProperties();
1417 QListIterator<QtProperty*> itSub(subList);
1418
1419 while (itSub.hasNext())
1420 {
1421 QtProperty* subProperty = itSub.next();
1422 insertSubTree(subProperty, property);
1423 }
1424}
1425
1426void
1428{
1429 if (!m_propertyToParents.contains(property))
1430 {
1431 // ASSERT
1432 return;
1433 }
1434
1435 m_propertyToParents[property].removeAll(parentProperty);
1436
1437 if (!m_propertyToParents[property].isEmpty())
1438 {
1439 return;
1440 }
1441
1442 m_propertyToParents.remove(property);
1443 QtAbstractPropertyManager* manager = property->propertyManager();
1444 m_managerToProperties[manager].removeAll(property);
1445
1446 if (m_managerToProperties[manager].isEmpty())
1447 {
1448 // disconnect manager's signals
1449 q_ptr->disconnect(manager,
1450 SIGNAL(propertyInserted(QtProperty*, QtProperty*, QtProperty*)),
1451 q_ptr,
1453 q_ptr->disconnect(manager,
1454 SIGNAL(propertyRemoved(QtProperty*, QtProperty*)),
1455 q_ptr,
1457 q_ptr->disconnect(manager,
1458 SIGNAL(propertyDestroyed(QtProperty*)),
1459 q_ptr,
1461 q_ptr->disconnect(manager,
1462 SIGNAL(propertyChanged(QtProperty*)),
1463 q_ptr,
1465
1466 m_managerToProperties.remove(manager);
1467 }
1468
1469 QList<QtProperty*> subList = property->subProperties();
1470 QListIterator<QtProperty*> itSub(subList);
1471
1472 while (itSub.hasNext())
1473 {
1474 QtProperty* subProperty = itSub.next();
1475 removeSubTree(subProperty, property);
1476 }
1477}
1478
1479void
1481 QtProperty* parentProperty,
1482 QtProperty* afterProperty)
1483{
1484 QMap<QtBrowserItem*, QtBrowserItem*> parentToAfter;
1485
1486 if (afterProperty)
1487 {
1488 QMap<QtProperty*, QList<QtBrowserItem*>>::ConstIterator it =
1489 m_propertyToIndexes.find(afterProperty);
1490
1491 if (it == m_propertyToIndexes.constEnd())
1492 {
1493 return;
1494 }
1495
1496 QList<QtBrowserItem*> indexes = it.value();
1497 QListIterator<QtBrowserItem*> itIndex(indexes);
1498
1499 while (itIndex.hasNext())
1500 {
1501 QtBrowserItem* idx = itIndex.next();
1502 QtBrowserItem* parentIdx = idx->parent();
1503
1504 if ((parentProperty && parentIdx && parentIdx->property() == parentProperty) ||
1505 (!parentProperty && !parentIdx))
1506 {
1507 parentToAfter[idx->parent()] = idx;
1508 }
1509 }
1510 }
1511 else if (parentProperty)
1512 {
1513 QMap<QtProperty*, QList<QtBrowserItem*>>::ConstIterator it =
1514 m_propertyToIndexes.find(parentProperty);
1515
1516 if (it == m_propertyToIndexes.constEnd())
1517 {
1518 return;
1519 }
1520
1521 QList<QtBrowserItem*> indexes = it.value();
1522 QListIterator<QtBrowserItem*> itIndex(indexes);
1523
1524 while (itIndex.hasNext())
1525 {
1526 QtBrowserItem* idx = itIndex.next();
1527 parentToAfter[idx] = 0;
1528 }
1529 }
1530 else
1531 {
1532 parentToAfter[0] = 0;
1533 }
1534
1535 const QMap<QtBrowserItem*, QtBrowserItem*>::ConstIterator pcend = parentToAfter.constEnd();
1536
1537 for (QMap<QtBrowserItem*, QtBrowserItem*>::ConstIterator it = parentToAfter.constBegin();
1538 it != pcend;
1539 ++it)
1540 {
1541 createBrowserIndex(property, it.key(), it.value());
1542 }
1543}
1544
1547 QtBrowserItem* parentIndex,
1548 QtBrowserItem* afterIndex)
1549{
1550 QtBrowserItem* newIndex = new QtBrowserItem(q_ptr, property, parentIndex);
1551
1552 if (parentIndex)
1553 {
1554 parentIndex->d_ptr->addChild(newIndex, afterIndex);
1555 }
1556 else
1557 {
1558 m_topLevelPropertyToIndex[property] = newIndex;
1559 m_topLevelIndexes.insert(m_topLevelIndexes.indexOf(afterIndex) + 1, newIndex);
1560 }
1561
1562 m_propertyToIndexes[property].append(newIndex);
1563
1564 q_ptr->itemInserted(newIndex, afterIndex);
1565
1566 QList<QtProperty*> subItems = property->subProperties();
1567 QListIterator<QtProperty*> itChild(subItems);
1568 QtBrowserItem* afterChild = 0;
1569
1570 while (itChild.hasNext())
1571 {
1572 QtProperty* child = itChild.next();
1573 afterChild = createBrowserIndex(child, newIndex, afterChild);
1574 }
1575
1576 return newIndex;
1577}
1578
1579void
1581 QtProperty* parentProperty)
1582{
1583 QList<QtBrowserItem*> toRemove;
1584 QMap<QtProperty*, QList<QtBrowserItem*>>::ConstIterator it = m_propertyToIndexes.find(property);
1585
1586 if (it == m_propertyToIndexes.constEnd())
1587 {
1588 return;
1589 }
1590
1591 QList<QtBrowserItem*> indexes = it.value();
1592 QListIterator<QtBrowserItem*> itIndex(indexes);
1593
1594 while (itIndex.hasNext())
1595 {
1596 QtBrowserItem* idx = itIndex.next();
1597 QtBrowserItem* parentIdx = idx->parent();
1598
1599 if ((parentProperty && parentIdx && parentIdx->property() == parentProperty) ||
1600 (!parentProperty && !parentIdx))
1601 {
1602 toRemove.append(idx);
1603 }
1604 }
1605
1606 QListIterator<QtBrowserItem*> itRemove(toRemove);
1607
1608 while (itRemove.hasNext())
1609 {
1610 QtBrowserItem* index = itRemove.next();
1612 }
1613}
1614
1615void
1617{
1618 QList<QtBrowserItem*> children = index->children();
1619
1620 for (int i = children.count(); i > 0; i--)
1621 {
1622 removeBrowserIndex(children.at(i - 1));
1623 }
1624
1625 q_ptr->itemRemoved(index);
1626
1627 if (index->parent())
1628 {
1629 index->parent()->d_ptr->removeChild(index);
1630 }
1631 else
1632 {
1633 m_topLevelPropertyToIndex.remove(index->property());
1634 m_topLevelIndexes.removeAll(index);
1635 }
1636
1637 QtProperty* property = index->property();
1638
1639 m_propertyToIndexes[property].removeAll(index);
1640
1641 if (m_propertyToIndexes[property].isEmpty())
1642 {
1643 m_propertyToIndexes.remove(property);
1644 }
1645
1646 delete index;
1647}
1648
1649void
1651{
1652 QList<QtBrowserItem*> children = index->children();
1653 QListIterator<QtBrowserItem*> itChild(children);
1654
1655 while (itChild.hasNext())
1656 {
1657 clearIndex(itChild.next());
1658 }
1659
1660 delete index;
1661}
1662
1663void
1665 QtProperty* parentProperty,
1666 QtProperty* afterProperty)
1667{
1668 if (!m_propertyToParents.contains(parentProperty))
1669 {
1670 return;
1671 }
1672
1673 createBrowserIndexes(property, parentProperty, afterProperty);
1674 insertSubTree(property, parentProperty);
1675 //q_ptr->propertyInserted(property, parentProperty, afterProperty);
1676}
1677
1678void
1680 QtProperty* parentProperty)
1681{
1682 if (!m_propertyToParents.contains(parentProperty))
1683 {
1684 return;
1685 }
1686
1688 property,
1689 parentProperty); // this line should be probably moved down after propertyRemoved call
1690 //q_ptr->propertyRemoved(property, parentProperty);
1691 removeBrowserIndexes(property, parentProperty);
1692}
1693
1694void
1696{
1697 if (!m_subItems.contains(property))
1698 {
1699 return;
1700 }
1701
1702 q_ptr->removeProperty(property);
1703}
1704
1705void
1707{
1708 if (!m_propertyToParents.contains(property))
1709 {
1710 return;
1711 }
1712
1713 QMap<QtProperty*, QList<QtBrowserItem*>>::ConstIterator it = m_propertyToIndexes.find(property);
1714
1715 if (it == m_propertyToIndexes.constEnd())
1716 {
1717 return;
1718 }
1719
1720 QList<QtBrowserItem*> indexes = it.value();
1721 QListIterator<QtBrowserItem*> itIndex(indexes);
1722
1723 while (itIndex.hasNext())
1724 {
1725 QtBrowserItem* idx = itIndex.next();
1726 q_ptr->itemChanged(idx);
1727 }
1728
1729 //q_ptr->propertyChanged(property);
1730}
1731
1732/*!
1733 \class QtAbstractPropertyBrowser
1734
1735 \brief QtAbstractPropertyBrowser provides a base class for
1736 implementing property browsers.
1737
1738 A property browser is a widget that enables the user to edit a
1739 given set of properties. Each property is represented by a label
1740 specifying the property's name, and an editing widget (e.g. a line
1741 edit or a combobox) holding its value. A property can have zero or
1742 more subproperties.
1743
1744 \image qtpropertybrowser.png
1745
1746 The top level properties can be retrieved using the
1747 properties() function. To traverse each property's
1748 subproperties, use the QtProperty::subProperties() function. In
1749 addition, the set of top level properties can be manipulated using
1750 the addProperty(), insertProperty() and removeProperty()
1751 functions. Note that the QtProperty class provides a corresponding
1752 set of functions making it possible to manipulate the set of
1753 subproperties as well.
1754
1755 To remove all the properties from the property browser widget, use
1756 the clear() function. This function will clear the editor, but it
1757 will not delete the properties since they can still be used in
1758 other editors.
1759
1760 The properties themselves are created and managed by
1761 implementations of the QtAbstractPropertyManager class. A manager
1762 can handle (i.e. create and manage) properties of a given type. In
1763 the property browser the managers are associated with
1764 implementations of the QtAbstractEditorFactory: A factory is a
1765 class able to create an editing widget of a specified type.
1766
1767 When using a property browser widget, managers must be created for
1768 each of the required property types before the properties
1769 themselves can be created. To ensure that the properties' values
1770 will be displayed using suitable editing widgets, the managers
1771 must be associated with objects of the preferred factory
1772 implementations using the setFactoryForManager() function. The
1773 property browser will use these associations to determine which
1774 factory it should use to create the preferred editing widget.
1775
1776 Note that a factory can be associated with many managers, but a
1777 manager can only be associated with one single factory within the
1778 context of a single property browser. The associations between
1779 managers and factories can at any time be removed using the
1780 unsetFactoryForManager() function.
1781
1782 Whenever the property data changes or a property is inserted or
1783 removed, the itemChanged(), itemInserted() or
1784 itemRemoved() functions are called, respectively. These
1785 functions must be reimplemented in derived classes in order to
1786 update the property browser widget. Be aware that some property
1787 instances can appear several times in an abstract tree
1788 structure. For example:
1789
1790 \table 100%
1791 \row
1792 \o
1793 \code
1794 QtProperty *property1, *property2, *property3;
1795
1796 property2->addSubProperty(property1);
1797 property3->addSubProperty(property2);
1798
1799 QtAbstractPropertyBrowser *editor;
1800
1801 editor->addProperty(property1);
1802 editor->addProperty(property2);
1803 editor->addProperty(property3);
1804 \endcode
1805 \o \image qtpropertybrowser-duplicate.png
1806 \endtable
1807
1808 The addProperty() function returns a QtBrowserItem that uniquely
1809 identifies the created item.
1810
1811 To make a property editable in the property browser, the
1812 createEditor() function must be called to provide the
1813 property with a suitable editing widget.
1814
1815 Note that there are two ready-made property browser
1816 implementations:
1817
1818 \list
1819 \o QtGroupBoxPropertyBrowser
1820 \o QtTreePropertyBrowser
1821 \endlist
1822
1823 \sa QtAbstractPropertyManager, QtAbstractEditorFactoryBase
1824*/
1825
1826/*!
1827 \fn void QtAbstractPropertyBrowser::setFactoryForManager(PropertyManager *manager,
1828 QtAbstractEditorFactory<PropertyManager> *factory)
1829
1830 Connects the given \a manager to the given \a factory, ensuring
1831 that properties of the \a manager's type will be displayed with an
1832 editing widget suitable for their value.
1833
1834 For example:
1835
1836 \code
1837 QtIntPropertyManager *intManager;
1838 QtDoublePropertyManager *doubleManager;
1839
1840 QtProperty *myInteger = intManager->addProperty();
1841 QtProperty *myDouble = doubleManager->addProperty();
1842
1843 QtSpinBoxFactory *spinBoxFactory;
1844 QtDoubleSpinBoxFactory *doubleSpinBoxFactory;
1845
1846 QtAbstractPropertyBrowser *editor;
1847 editor->setFactoryForManager(intManager, spinBoxFactory);
1848 editor->setFactoryForManager(doubleManager, doubleSpinBoxFactory);
1849
1850 editor->addProperty(myInteger);
1851 editor->addProperty(myDouble);
1852 \endcode
1853
1854 In this example the \c myInteger property's value is displayed
1855 with a QSpinBox widget, while the \c myDouble property's value is
1856 displayed with a QDoubleSpinBox widget.
1857
1858 Note that a factory can be associated with many managers, but a
1859 manager can only be associated with one single factory. If the
1860 given \a manager already is associated with another factory, the
1861 old association is broken before the new one established.
1862
1863 This function ensures that the given \a manager and the given \a
1864 factory are compatible, and it automatically calls the
1865 QtAbstractEditorFactory::addPropertyManager() function if necessary.
1866
1867 \sa unsetFactoryForManager()
1868*/
1869
1870/*!
1871 \fn virtual void QtAbstractPropertyBrowser::itemInserted(QtBrowserItem *insertedItem,
1872 QtBrowserItem *precedingItem) = 0
1873
1874 This function is called to update the widget whenever a property
1875 is inserted or added to the property browser, passing pointers to
1876 the \a insertedItem of property and the specified
1877 \a precedingItem as parameters.
1878
1879 If \a precedingItem is 0, the \a insertedItem was put at
1880 the beginning of its parent item's list of subproperties. If
1881 the parent of \a insertedItem is 0, the \a insertedItem was added as a top
1882 level property of \e this property browser.
1883
1884 This function must be reimplemented in derived classes. Note that
1885 if the \a insertedItem's property has subproperties, this
1886 method will be called for those properties as soon as the current call is finished.
1887
1888 \sa insertProperty(), addProperty()
1889*/
1890
1891/*!
1892 \fn virtual void QtAbstractPropertyBrowser::itemRemoved(QtBrowserItem *item) = 0
1893
1894 This function is called to update the widget whenever a property
1895 is removed from the property browser, passing the pointer to the
1896 \a item of the property as parameters. The passed \a item is
1897 deleted just after this call is finished.
1898
1899 If the the parent of \a item is 0, the removed \a item was a
1900 top level property in this editor.
1901
1902 This function must be reimplemented in derived classes. Note that
1903 if the removed \a item's property has subproperties, this
1904 method will be called for those properties just before the current call is started.
1905
1906 \sa removeProperty()
1907*/
1908
1909/*!
1910 \fn virtual void QtAbstractPropertyBrowser::itemChanged(QtBrowserItem *item) = 0
1911
1912 This function is called whenever a property's data changes,
1913 passing a pointer to the \a item of property as parameter.
1914
1915 This function must be reimplemented in derived classes in order to
1916 update the property browser widget whenever a property's name,
1917 tool tip, status tip, "what's this" text, value text or value icon
1918 changes.
1919
1920 Note that if the property browser contains several occurrences of
1921 the same property, this method will be called once for each
1922 occurrence (with a different item each time).
1923
1924 \sa QtProperty, items()
1925*/
1926
1927/*!
1928 Creates an abstract property browser with the given \a parent.
1929*/
1931{
1933 d_ptr->q_ptr = this;
1934}
1935
1936/*!
1937 Destroys the property browser, and destroys all the items that were
1938 created by this property browser.
1939
1940 Note that the properties that were displayed in the editor are not
1941 deleted since they still can be used in other editors. Neither
1942 does the destructor delete the property managers and editor
1943 factories that were used by this property browser widget unless
1944 this widget was their parent.
1945
1946 \sa QtAbstractPropertyManager::~QtAbstractPropertyManager()
1947*/
1949{
1950 QList<QtBrowserItem*> indexes = topLevelItems();
1951 QListIterator<QtBrowserItem*> itItem(indexes);
1952
1953 while (itItem.hasNext())
1954 {
1955 d_ptr->clearIndex(itItem.next());
1956 }
1957
1958 delete d_ptr;
1959}
1960
1961/*!
1962 Returns the property browser's list of top level properties.
1963
1964 To traverse the subproperties, use the QtProperty::subProperties()
1965 function.
1966
1967 \sa addProperty(), insertProperty(), removeProperty()
1968*/
1969QList<QtProperty*>
1971{
1972 return d_ptr->m_subItems;
1973}
1974
1975/*!
1976 Returns the property browser's list of all items associated
1977 with the given \a property.
1978
1979 There is one item per instance of the property in the browser.
1980
1981 \sa topLevelItem()
1982*/
1983
1984QList<QtBrowserItem*>
1986{
1987 return d_ptr->m_propertyToIndexes.value(property);
1988}
1989
1990/*!
1991 Returns the top-level items associated with the given \a property.
1992
1993 Returns 0 if \a property wasn't inserted into this property
1994 browser or isn't a top-level one.
1995
1996 \sa topLevelItems(), items()
1997*/
1998
2001{
2002 return d_ptr->m_topLevelPropertyToIndex.value(property);
2003}
2004
2005/*!
2006 Returns the list of top-level items.
2007
2008 \sa topLevelItem()
2009*/
2010
2011QList<QtBrowserItem*>
2013{
2014 return d_ptr->m_topLevelIndexes;
2015}
2016
2017/*!
2018 Removes all the properties from the editor, but does not delete
2019 them since they can still be used in other editors.
2020
2021 \sa removeProperty(), QtAbstractPropertyManager::clear()
2022*/
2023void
2025{
2026 QList<QtProperty*> subList = properties();
2027 QListIterator<QtProperty*> itSub(subList);
2028 itSub.toBack();
2029
2030 while (itSub.hasPrevious())
2031 {
2032 QtProperty* property = itSub.previous();
2033 removeProperty(property);
2034 }
2035}
2036
2037/*!
2038 Appends the given \a property (and its subproperties) to the
2039 property browser's list of top level properties. Returns the item
2040 created by property browser which is associated with the \a property.
2041 In order to get all children items created by the property
2042 browser in this call, the returned item should be traversed.
2043
2044 If the specified \a property is already added, this function does
2045 nothing and returns 0.
2046
2047 \sa insertProperty(), QtProperty::addSubProperty(), properties()
2048*/
2051{
2052 QtProperty* afterProperty = 0;
2053
2054 if (d_ptr->m_subItems.count() > 0)
2055 {
2056 afterProperty = d_ptr->m_subItems.last();
2057 }
2058
2059 return insertProperty(property, afterProperty);
2060}
2061
2062/*!
2063 \fn QtBrowserItem *QtAbstractPropertyBrowser::insertProperty(QtProperty *property,
2064 QtProperty *afterProperty)
2065
2066 Inserts the given \a property (and its subproperties) after
2067 the specified \a afterProperty in the browser's list of top
2068 level properties. Returns item created by property browser which
2069 is associated with the \a property. In order to get all children items
2070 created by the property browser in this call returned item should be traversed.
2071
2072 If the specified \a afterProperty is 0, the given \a property is
2073 inserted at the beginning of the list. If \a property is
2074 already inserted, this function does nothing and returns 0.
2075
2076 \sa addProperty(), QtProperty::insertSubProperty(), properties()
2077*/
2080{
2081 if (!property)
2082 {
2083 return 0;
2084 }
2085
2086 // if item is already inserted in this item then cannot add.
2087 QList<QtProperty*> pendingList = properties();
2088 int pos = 0;
2089 int newPos = 0;
2090
2091 while (pos < pendingList.count())
2092 {
2093 QtProperty* prop = pendingList.at(pos);
2094
2095 if (prop == property)
2096 {
2097 return 0;
2098 }
2099
2100 if (prop == afterProperty)
2101 {
2102 newPos = pos + 1;
2103 }
2104
2105 pos++;
2106 }
2107
2108 d_ptr->createBrowserIndexes(property, 0, afterProperty);
2109
2110 // traverse inserted subtree and connect to manager's signals
2111 d_ptr->insertSubTree(property, 0);
2112
2113 d_ptr->m_subItems.insert(newPos, property);
2114 //propertyInserted(property, 0, properAfterProperty);
2115 return topLevelItem(property);
2116}
2117
2118/*!
2119 Removes the specified \a property (and its subproperties) from the
2120 property browser's list of top level properties. All items
2121 that were associated with the given \a property and its children
2122 are deleted.
2123
2124 Note that the properties are \e not deleted since they can still
2125 be used in other editors.
2126
2127 \sa clear(), QtProperty::removeSubProperty(), properties()
2128*/
2129void
2131{
2132 if (!property)
2133 {
2134 return;
2135 }
2136
2137 QList<QtProperty*> pendingList = properties();
2138 int pos = 0;
2139
2140 while (pos < pendingList.count())
2141 {
2142 if (pendingList.at(pos) == property)
2143 {
2144 d_ptr->m_subItems.removeAt(pos); //perhaps this two lines
2145 d_ptr->removeSubTree(property, 0); //should be moved down after propertyRemoved call.
2146 //propertyRemoved(property, 0);
2147
2148 d_ptr->removeBrowserIndexes(property, 0);
2149
2150 // when item is deleted, item will call removeItem for top level items,
2151 // and itemRemoved for nested items.
2152
2153 return;
2154 }
2155
2156 pos++;
2157 }
2158}
2159
2160/*!
2161 Creates an editing widget (with the given \a parent) for the given
2162 \a property according to the previously established associations
2163 between property managers and editor factories.
2164
2165 If the property is created by a property manager which was not
2166 associated with any of the existing factories in \e this property
2167 editor, the function returns 0.
2168
2169 To make a property editable in the property browser, the
2170 createEditor() function must be called to provide the
2171 property with a suitable editing widget.
2172
2173 Reimplement this function to provide additional decoration for the
2174 editing widgets created by the installed factories.
2175
2176 \sa setFactoryForManager()
2177*/
2178QWidget*
2180{
2181 QtAbstractEditorFactoryBase* factory = 0;
2182 QtAbstractPropertyManager* manager = property->propertyManager();
2183
2184 if (m_viewToManagerToFactory()->contains(this) &&
2185 (*m_viewToManagerToFactory())[this].contains(manager))
2186 {
2187 factory = (*m_viewToManagerToFactory())[this][manager];
2188 }
2189
2190 if (!factory)
2191 {
2192 return 0;
2193 }
2194
2195 return factory->createEditor(property, parent);
2196}
2197
2198bool
2199QtAbstractPropertyBrowser::addFactory(QtAbstractPropertyManager* abstractManager,
2200 QtAbstractEditorFactoryBase* abstractFactory)
2201{
2202 bool connectNeeded = false;
2203
2204 if (!m_managerToFactoryToViews()->contains(abstractManager) ||
2205 !(*m_managerToFactoryToViews())[abstractManager].contains(abstractFactory))
2206 {
2207 connectNeeded = true;
2208 }
2209 else if ((*m_managerToFactoryToViews())[abstractManager][abstractFactory].contains(this))
2210 {
2211 return connectNeeded;
2212 }
2213
2214 if (m_viewToManagerToFactory()->contains(this) &&
2215 (*m_viewToManagerToFactory())[this].contains(abstractManager))
2216 {
2217 unsetFactoryForManager(abstractManager);
2218 }
2219
2220 (*m_managerToFactoryToViews())[abstractManager][abstractFactory].append(this);
2221 (*m_viewToManagerToFactory())[this][abstractManager] = abstractFactory;
2222
2223 return connectNeeded;
2224}
2225
2226/*!
2227 Removes the association between the given \a manager and the
2228 factory bound to it, automatically calling the
2229 QtAbstractEditorFactory::removePropertyManager() function if necessary.
2230
2231 \sa setFactoryForManager()
2232*/
2233void
2235{
2236 if (!m_viewToManagerToFactory()->contains(this) ||
2237 !(*m_viewToManagerToFactory())[this].contains(manager))
2238 {
2239 return;
2240 }
2241
2242 QtAbstractEditorFactoryBase* abstractFactory = (*m_viewToManagerToFactory())[this][manager];
2243 (*m_viewToManagerToFactory())[this].remove(manager);
2244
2245 if ((*m_viewToManagerToFactory())[this].isEmpty())
2246 {
2247 (*m_viewToManagerToFactory()).remove(this);
2248 }
2249
2250 (*m_managerToFactoryToViews())[manager][abstractFactory].removeAll(this);
2251
2252 if ((*m_managerToFactoryToViews())[manager][abstractFactory].isEmpty())
2253 {
2254 (*m_managerToFactoryToViews())[manager].remove(abstractFactory);
2255 abstractFactory->breakConnection(manager);
2256
2257 if ((*m_managerToFactoryToViews())[manager].isEmpty())
2258 {
2259 (*m_managerToFactoryToViews()).remove(manager);
2260 }
2261 }
2262}
2263
2264/*!
2265 Returns the current item in the property browser.
2266
2267 \sa setCurrentItem()
2268*/
2271{
2272 return d_ptr->m_currentItem;
2273}
2274
2275/*!
2276 Sets the current item in the property browser to \a item.
2277
2278 \sa currentItem(), currentItemChanged()
2279*/
2280void
2282{
2283 QtBrowserItem* oldItem = d_ptr->m_currentItem;
2284 d_ptr->m_currentItem = item;
2285
2286 if (oldItem != item)
2287 {
2288 emit currentItemChanged(item);
2289 }
2290}
2291
2292QT_END_NAMESPACE
2293
2294#include "moc_qtpropertybrowser.cpp"
uint8_t index
The QtAbstractEditorFactoryBase provides an interface for editor factories.
virtual void breakConnection(QtAbstractPropertyManager *manager)=0
virtual QWidget * createEditor(QtProperty *property, QWidget *parent)=0
void slotPropertyInserted(QtProperty *property, QtProperty *parentProperty, QtProperty *afterProperty)
void slotPropertyDataChanged(QtProperty *property)
void insertSubTree(QtProperty *property, QtProperty *parentProperty)
void clearIndex(QtBrowserItem *index)
void slotPropertyDestroyed(QtProperty *property)
QMap< QtProperty *, QList< QtProperty * > > m_propertyToParents
void createBrowserIndexes(QtProperty *property, QtProperty *parentProperty, QtProperty *afterProperty)
QMap< QtProperty *, QList< QtBrowserItem * > > m_propertyToIndexes
QMap< QtAbstractPropertyManager *, QList< QtProperty * > > m_managerToProperties
QtBrowserItem * createBrowserIndex(QtProperty *property, QtBrowserItem *parentIndex, QtBrowserItem *afterIndex)
void removeSubTree(QtProperty *property, QtProperty *parentProperty)
void removeBrowserIndexes(QtProperty *property, QtProperty *parentProperty)
QList< QtBrowserItem * > m_topLevelIndexes
QMap< QtProperty *, QtBrowserItem * > m_topLevelPropertyToIndex
void removeBrowserIndex(QtBrowserItem *index)
void slotPropertyRemoved(QtProperty *property, QtProperty *parentProperty)
QtAbstractPropertyBrowser provides a base class for implementing property browsers.
QtBrowserItem * currentItem() const
QtAbstractPropertyBrowser(QWidget *parent=0)
void currentItemChanged(QtBrowserItem *)
QtBrowserItem * insertProperty(QtProperty *property, QtProperty *afterProperty)
virtual QWidget * createEditor(QtProperty *property, QWidget *parent)
void unsetFactoryForManager(QtAbstractPropertyManager *manager)
void removeProperty(QtProperty *property)
QList< QtProperty * > properties() const
QList< QtBrowserItem * > topLevelItems() const
QtBrowserItem * addProperty(QtProperty *property)
void setCurrentItem(QtBrowserItem *)
QtBrowserItem * topLevelItem(QtProperty *property) const
QList< QtBrowserItem * > items(QtProperty *property) const
void propertyDestroyed(QtProperty *property)
void propertyRemoved(QtProperty *property, QtProperty *parentProperty) const
void propertyChanged(QtProperty *property) const
void propertyInserted(QtProperty *property, QtProperty *parentProperty, QtProperty *afterProperty) const
The QtAbstractPropertyManager provides an interface for property managers.
QSet< QtProperty * > properties() const
virtual QString valueText(const QtProperty *property) const
virtual QIcon valueIcon(const QtProperty *property) const
virtual void uninitializeProperty(QtProperty *property)
virtual QString displayText(const QtProperty *property) const
virtual EchoMode echoMode(const QtProperty *) const
QtAbstractPropertyManager(QObject *parent=0)
virtual void initializeProperty(QtProperty *property)=0
virtual QtProperty * createProperty()
QtProperty * addProperty(const QString &name=QString())
virtual bool hasValue(const QtProperty *property) const
QtAbstractPropertyBrowser *const m_browser
QtBrowserItemPrivate(QtAbstractPropertyBrowser *browser, QtProperty *property, QtBrowserItem *parent)
void removeChild(QtBrowserItem *index)
void addChild(QtBrowserItem *index, QtBrowserItem *after)
QList< QtBrowserItem * > m_children
The QtBrowserItem class represents a property in a property browser instance.
QList< QtBrowserItem * > children() const
QtBrowserItem * parent() const
QtAbstractPropertyBrowser * browser() const
QtProperty * property() const
QSet< QtProperty * > m_parentItems
QList< QtProperty * > m_subItems
QtPropertyPrivate(QtAbstractPropertyManager *manager)
QtAbstractPropertyManager *const m_manager
The QtProperty class encapsulates an instance of a property.
QString propertyName() const
QIcon valueIcon() const
QString toolTip() const
QString valueText() const
void insertSubProperty(QtProperty *property, QtProperty *afterProperty)
void removeSubProperty(QtProperty *property)
QList< QtProperty * > subProperties() const
QString statusTip() const
QtAbstractPropertyManager * propertyManager() const
bool isModified() const
void setToolTip(const QString &text)
void setModified(bool modified)
bool isEnabled() const
QString whatsThis() const
void setEnabled(bool enable)
void setWhatsThis(const QString &text)
virtual ~QtProperty()
friend class QtAbstractPropertyManager
void setPropertyName(const QString &text)
void setStatusTip(const QString &text)
QString displayText() const
QtProperty(QtAbstractPropertyManager *manager)
bool hasValue() const
void addSubProperty(QtProperty *property)
bool contains(const MemoryID &general, const MemoryID &specific)
Indicates whether general is "less specific" than, or equal to, specific, i.e.
Definition MemoryID.cpp:563
QMap< QtAbstractPropertyManager *, QMap< QtAbstractEditorFactoryBase *, QList< QtAbstractPropertyBrowser * > > > Map2
QMap< QtAbstractPropertyBrowser *, QMap< QtAbstractPropertyManager *, QtAbstractEditorFactoryBase * > > Map1
QLineEdit::EchoMode EchoMode