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