tools/shared/qtpropertybrowser/qtpropertybrowser.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/shared/qtpropertybrowser/qtpropertybrowser.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,1955 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtpropertybrowser.h"
+#include <QtCore/QSet>
+#include <QtCore/QMap>
+#include <QtGui/QIcon>
+
+#if defined(Q_CC_MSVC)
+#    pragma warning(disable: 4786) /* MS VS 6: truncating debug info after 255 characters */
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QtPropertyPrivate
+{
+public:
+    QtPropertyPrivate(QtAbstractPropertyManager *manager) : m_enabled(true), m_modified(false), m_manager(manager) {}
+    QtProperty *q_ptr;
+
+    QSet<QtProperty *> m_parentItems;
+    QList<QtProperty *> m_subItems;
+
+    QString m_toolTip;
+    QString m_statusTip;
+    QString m_whatsThis;
+    QString m_name;
+    bool m_enabled;
+    bool m_modified;
+
+    QtAbstractPropertyManager * const m_manager;
+};
+
+class QtAbstractPropertyManagerPrivate
+{
+    QtAbstractPropertyManager *q_ptr;
+    Q_DECLARE_PUBLIC(QtAbstractPropertyManager)
+public:
+    void propertyDestroyed(QtProperty *property);
+    void propertyChanged(QtProperty *property) const;
+    void propertyRemoved(QtProperty *property,
+                QtProperty *parentProperty) const;
+    void propertyInserted(QtProperty *property, QtProperty *parentProperty,
+                QtProperty *afterProperty) const;
+
+    QSet<QtProperty *> m_properties;
+};
+
+/*!
+    \class QtProperty
+    \internal
+    \inmodule QtDesigner
+    \since 4.4
+
+    \brief The QtProperty class encapsulates an instance of a property.
+
+    Properties are created by objects of QtAbstractPropertyManager
+    subclasses; a manager can create properties of a given type, and
+    is used in conjunction with the QtAbstractPropertyBrowser class. A
+    property is always owned by the manager that created it, which can
+    be retrieved using the propertyManager() function.
+
+    QtProperty contains the most common property attributes, and
+    provides functions for retrieving as well as setting their values:
+
+    \table
+    \header \o Getter \o Setter
+    \row
+    \o propertyName() \o setPropertyName()
+    \row
+    \o statusTip() \o setStatusTip()
+    \row
+    \o toolTip() \o setToolTip()
+    \row
+    \o whatsThis() \o setWhatsThis()
+    \row
+    \o isEnabled() \o setEnabled()
+    \row
+    \o isModified() \o setModified()
+    \row
+    \o valueText() \o Nop
+    \row
+    \o valueIcon() \o Nop
+    \endtable
+
+    It is also possible to nest properties: QtProperty provides the
+    addSubProperty(), insertSubProperty() and removeSubProperty() functions to
+    manipulate the set of subproperties. Use the subProperties()
+    function to retrieve a property's current set of subproperties.
+    Note that nested properties are not owned by the parent property,
+    i.e. each subproperty is owned by the manager that created it.
+
+    \sa QtAbstractPropertyManager, QtBrowserItem
+*/
+
+/*!
+    Creates a property with the given \a manager.
+
+    This constructor is only useful when creating a custom QtProperty
+    subclass (e.g. QtVariantProperty). To create a regular QtProperty
+    object, use the QtAbstractPropertyManager::addProperty()
+    function instead.
+
+    \sa QtAbstractPropertyManager::addProperty()
+*/
+QtProperty::QtProperty(QtAbstractPropertyManager *manager)
+    : d_ptr(new QtPropertyPrivate(manager))
+{
+    d_ptr->q_ptr = this;
+}
+
+/*!
+    Destroys this property.
+
+    Note that subproperties are detached but not destroyed, i.e. they
+    can still be used in another context.
+
+    \sa QtAbstractPropertyManager::clear()
+
+*/
+QtProperty::~QtProperty()
+{
+    QSetIterator<QtProperty *> itParent(d_ptr->m_parentItems);
+    while (itParent.hasNext()) {
+        QtProperty *property = itParent.next();
+        property->d_ptr->m_manager->d_ptr->propertyRemoved(this, property);
+    }
+
+    d_ptr->m_manager->d_ptr->propertyDestroyed(this);
+
+    QListIterator<QtProperty *> itChild(d_ptr->m_subItems);
+    while (itChild.hasNext()) {
+        QtProperty *property = itChild.next();
+        property->d_ptr->m_parentItems.remove(this);
+    }
+
+    itParent.toFront();
+    while (itParent.hasNext()) {
+        QtProperty *property = itParent.next();
+        property->d_ptr->m_subItems.removeAll(this);
+    }
+}
+
+/*!
+    Returns the set of subproperties.
+
+    Note that subproperties are not owned by \e this property, but by
+    the manager that created them.
+
+    \sa insertSubProperty(), removeSubProperty()
+*/
+QList<QtProperty *> QtProperty::subProperties() const
+{
+    return d_ptr->m_subItems;
+}
+
+/*!
+    Returns a pointer to the manager that owns this property.
+*/
+QtAbstractPropertyManager *QtProperty::propertyManager() const
+{
+    return d_ptr->m_manager;
+}
+
+/*!
+    Returns the property's  tool tip.
+
+    \sa setToolTip()
+*/
+QString QtProperty::toolTip() const
+{
+    return d_ptr->m_toolTip;
+}
+
+/*!
+    Returns the property's status tip.
+
+    \sa setStatusTip()
+*/
+QString QtProperty::statusTip() const
+{
+    return d_ptr->m_statusTip;
+}
+
+/*!
+    Returns the property's "What's This" help text.
+
+    \sa setWhatsThis()
+*/
+QString QtProperty::whatsThis() const
+{
+    return d_ptr->m_whatsThis;
+}
+
+/*!
+    Returns the property's name.
+
+    \sa setPropertyName()
+*/
+QString QtProperty::propertyName() const
+{
+    return d_ptr->m_name;
+}
+
+/*!
+    Returns whether the property is enabled.
+
+    \sa setEnabled()
+*/
+bool QtProperty::isEnabled() const
+{
+    return d_ptr->m_enabled;
+}
+
+/*!
+    Returns whether the property is modified.
+
+    \sa setModified()
+*/
+bool QtProperty::isModified() const
+{
+    return d_ptr->m_modified;
+}
+
+/*!
+    Returns whether the property has a value.
+
+    \sa QtAbstractPropertyManager::hasValue()
+*/
+bool QtProperty::hasValue() const
+{
+    return d_ptr->m_manager->hasValue(this);
+}
+
+/*!
+    Returns an icon representing the current state of this property.
+
+    If the given property type can not generate such an icon, this
+    function returns an invalid icon.
+
+    \sa QtAbstractPropertyManager::valueIcon()
+*/
+QIcon QtProperty::valueIcon() const
+{
+    return d_ptr->m_manager->valueIcon(this);
+}
+
+/*!
+    Returns a string representing the current state of this property.
+
+    If the given property type can not generate such a string, this
+    function returns an empty string.
+
+    \sa QtAbstractPropertyManager::valueText()
+*/
+QString QtProperty::valueText() const
+{
+    return d_ptr->m_manager->valueText(this);
+}
+
+/*!
+    Sets the property's tool tip to the given \a text.
+
+    \sa toolTip()
+*/
+void QtProperty::setToolTip(const QString &text)
+{
+    if (d_ptr->m_toolTip == text)
+        return;
+
+    d_ptr->m_toolTip = text;
+    propertyChanged();
+}
+
+/*!
+    Sets the property's status tip to the given \a text.
+
+    \sa statusTip()
+*/
+void QtProperty::setStatusTip(const QString &text)
+{
+    if (d_ptr->m_statusTip == text)
+        return;
+
+    d_ptr->m_statusTip = text;
+    propertyChanged();
+}
+
+/*!
+    Sets the property's "What's This" help text to the given \a text.
+
+    \sa whatsThis()
+*/
+void QtProperty::setWhatsThis(const QString &text)
+{
+    if (d_ptr->m_whatsThis == text)
+        return;
+
+    d_ptr->m_whatsThis = text;
+    propertyChanged();
+}
+
+/*!
+    \fn void QtProperty::setPropertyName(const QString &name)
+
+    Sets the property's  name to the given \a name.
+
+    \sa propertyName()
+*/
+void QtProperty::setPropertyName(const QString &text)
+{
+    if (d_ptr->m_name == text)
+        return;
+
+    d_ptr->m_name = text;
+    propertyChanged();
+}
+
+/*!
+    Enables or disables the property according to the passed \a enable value.
+
+    \sa isEnabled()
+*/
+void QtProperty::setEnabled(bool enable)
+{
+    if (d_ptr->m_enabled == enable)
+        return;
+
+    d_ptr->m_enabled = enable;
+    propertyChanged();
+}
+
+/*!
+    Sets the property's modified state according to the passed \a modified value.
+
+    \sa isModified()
+*/
+void QtProperty::setModified(bool modified)
+{
+    if (d_ptr->m_modified == modified)
+        return;
+
+    d_ptr->m_modified = modified;
+    propertyChanged();
+}
+
+/*!
+    Appends the given \a property to this property's subproperties.
+
+    If the given \a property already is added, this function does
+    nothing.
+
+    \sa insertSubProperty(), removeSubProperty()
+*/
+void QtProperty::addSubProperty(QtProperty *property)
+{
+    QtProperty *after = 0;
+    if (d_ptr->m_subItems.count() > 0)
+        after = d_ptr->m_subItems.last();
+    insertSubProperty(property, after);
+}
+
+/*!
+    \fn void QtProperty::insertSubProperty(QtProperty *property, QtProperty *precedingProperty)
+
+    Inserts the given \a property after the specified \a
+    precedingProperty into this property's list of subproperties.  If
+    \a precedingProperty is 0, the specified \a property is inserted
+    at the beginning of the list.
+
+    If the given \a property already is inserted, this function does
+    nothing.
+
+    \sa addSubProperty(), removeSubProperty()
+*/
+void QtProperty::insertSubProperty(QtProperty *property,
+            QtProperty *afterProperty)
+{
+    if (!property)
+        return;
+
+    if (property == this)
+        return;
+
+    // traverse all children of item. if this item is a child of item then cannot add.
+    QList<QtProperty *> pendingList = property->subProperties();
+    QMap<QtProperty *, bool> visited;
+    while (!pendingList.isEmpty()) {
+        QtProperty *i = pendingList.first();
+        if (i == this)
+            return;
+        pendingList.removeFirst();
+        if (visited.contains(i))
+            continue;
+        visited[i] = true;
+        pendingList += i->subProperties();
+    }
+
+    pendingList = subProperties();
+    int pos = 0;
+    int newPos = 0;
+    QtProperty *properAfterProperty = 0;
+    while (pos < pendingList.count()) {
+        QtProperty *i = pendingList.at(pos);
+        if (i == property)
+            return; // if item is already inserted in this item then cannot add.
+        if (i == afterProperty) {
+            newPos = pos + 1;
+            properAfterProperty = afterProperty;
+        }
+        pos++;
+    }
+
+    d_ptr->m_subItems.insert(newPos, property);
+    property->d_ptr->m_parentItems.insert(this);
+
+    d_ptr->m_manager->d_ptr->propertyInserted(property, this, properAfterProperty);
+}
+
+/*!
+    Removes the given \a property from the list of subproperties
+    without deleting it.
+
+    \sa addSubProperty(), insertSubProperty()
+*/
+void QtProperty::removeSubProperty(QtProperty *property)
+{
+    if (!property)
+        return;
+
+    d_ptr->m_manager->d_ptr->propertyRemoved(property, this);
+
+    QList<QtProperty *> pendingList = subProperties();
+    int pos = 0;
+    while (pos < pendingList.count()) {
+        if (pendingList.at(pos) == property) {
+            d_ptr->m_subItems.removeAt(pos);
+            property->d_ptr->m_parentItems.remove(this);
+
+            return;
+        }
+        pos++;
+    }
+}
+
+/*!
+    \internal
+*/
+void QtProperty::propertyChanged()
+{
+    d_ptr->m_manager->d_ptr->propertyChanged(this);
+}
+
+////////////////////////////////
+
+void QtAbstractPropertyManagerPrivate::propertyDestroyed(QtProperty *property)
+{
+    if (m_properties.contains(property)) {
+        emit q_ptr->propertyDestroyed(property);
+        q_ptr->uninitializeProperty(property);
+        m_properties.remove(property);
+    }
+}
+
+void QtAbstractPropertyManagerPrivate::propertyChanged(QtProperty *property) const
+{
+    emit q_ptr->propertyChanged(property);
+}
+
+void QtAbstractPropertyManagerPrivate::propertyRemoved(QtProperty *property,
+            QtProperty *parentProperty) const
+{
+    emit q_ptr->propertyRemoved(property, parentProperty);
+}
+
+void QtAbstractPropertyManagerPrivate::propertyInserted(QtProperty *property,
+            QtProperty *parentProperty, QtProperty *afterProperty) const
+{
+    emit q_ptr->propertyInserted(property, parentProperty, afterProperty);
+}
+
+/*!
+    \class QtAbstractPropertyManager
+    \internal
+    \inmodule QtDesigner
+    \since 4.4
+
+    \brief The QtAbstractPropertyManager provides an interface for
+    property managers.
+
+    A manager can create and manage properties of a given type, and is
+    used in conjunction with the QtAbstractPropertyBrowser class.
+
+    When using a property browser widget, the properties are created
+    and managed by implementations of the QtAbstractPropertyManager
+    class. To ensure that the properties' values will be displayed
+    using suitable editing widgets, the managers are associated with
+    objects of QtAbstractEditorFactory subclasses. The property browser
+    will use these associations to determine which factories it should
+    use to create the preferred editing widgets.
+
+    The QtAbstractPropertyManager class provides common functionality
+    like creating a property using the addProperty() function, and
+    retrieving the properties created by the manager using the
+    properties() function. The class also provides signals that are
+    emitted when the manager's properties change: propertyInserted(),
+    propertyRemoved(), propertyChanged() and propertyDestroyed().
+
+    QtAbstractPropertyManager subclasses are supposed to provide their
+    own type specific API. Note that several ready-made
+    implementations are available:
+
+    \list
+    \o QtBoolPropertyManager
+    \o QtColorPropertyManager
+    \o QtDatePropertyManager
+    \o QtDateTimePropertyManager
+    \o QtDoublePropertyManager
+    \o QtEnumPropertyManager
+    \o QtFlagPropertyManager
+    \o QtFontPropertyManager
+    \o QtGroupPropertyManager
+    \o QtIntPropertyManager
+    \o QtPointPropertyManager
+    \o QtRectPropertyManager
+    \o QtSizePropertyManager
+    \o QtSizePolicyPropertyManager
+    \o QtStringPropertyManager
+    \o QtTimePropertyManager
+    \o QtVariantPropertyManager
+    \endlist
+
+    \sa QtAbstractEditorFactoryBase, QtAbstractPropertyBrowser, QtProperty
+*/
+
+/*!
+    \fn void QtAbstractPropertyManager::propertyInserted(QtProperty *newProperty,
+                QtProperty *parentProperty, QtProperty *precedingProperty)
+
+    This signal is emitted when a new subproperty is inserted into an
+    existing property, passing pointers to the \a newProperty, \a
+    parentProperty and \a precedingProperty as parameters.
+
+    If \a precedingProperty is 0, the \a newProperty was inserted at
+    the beginning of the \a parentProperty's subproperties list.
+
+    Note that signal is emitted only if the \a parentProperty is created
+    by this manager.
+
+    \sa QtAbstractPropertyBrowser::itemInserted()
+*/
+
+/*!
+    \fn void QtAbstractPropertyManager::propertyChanged(QtProperty *property)
+
+    This signal is emitted whenever a property's data changes, passing
+    a pointer to the \a property as parameter.
+
+    Note that signal is only emitted for properties that are created by
+    this manager.
+
+    \sa QtAbstractPropertyBrowser::itemChanged()
+*/
+
+/*!
+    \fn void QtAbstractPropertyManager::propertyRemoved(QtProperty *property, QtProperty *parent)
+
+    This signal is emitted when a subproperty is removed, passing
+    pointers to the removed \a property and the \a parent property as
+    parameters.
+
+    Note that signal is emitted only when the \a parent property is
+    created by this manager.
+
+    \sa QtAbstractPropertyBrowser::itemRemoved()
+*/
+
+/*!
+    \fn void QtAbstractPropertyManager::propertyDestroyed(QtProperty *property)
+
+    This signal is emitted when the specified \a property is about to
+    be destroyed.
+
+    Note that signal is only emitted for properties that are created
+    by this manager.
+
+    \sa clear(), uninitializeProperty()
+*/
+
+/*!
+    \fn void QtAbstractPropertyBrowser::currentItemChanged(QtBrowserItem *current)
+
+    This signal is emitted when the current item changes. The current item is specified by \a current.
+
+    \sa QtAbstractPropertyBrowser::setCurrentItem()
+*/
+
+/*!
+    Creates an abstract property manager with the given \a parent.
+*/
+QtAbstractPropertyManager::QtAbstractPropertyManager(QObject *parent)
+    : QObject(parent), d_ptr(new QtAbstractPropertyManagerPrivate)
+{
+    d_ptr->q_ptr = this;
+
+}
+
+/*!
+    Destroys the manager. All properties created by the manager are
+    destroyed.
+*/
+QtAbstractPropertyManager::~QtAbstractPropertyManager()
+{
+    clear();
+}
+
+/*!
+    Destroys all the properties that this manager has created.
+
+    \sa propertyDestroyed(), uninitializeProperty()
+*/
+void QtAbstractPropertyManager::clear() const
+{
+    while (!properties().isEmpty()) {
+        QSetIterator<QtProperty *> itProperty(properties());
+        QtProperty *prop = itProperty.next();
+        delete prop;
+    }
+}
+
+/*!
+    Returns the set of properties created by this manager.
+
+    \sa addProperty()
+*/
+QSet<QtProperty *> QtAbstractPropertyManager::properties() const
+{
+    return d_ptr->m_properties;
+}
+
+/*!
+    Returns whether the given \a property has a value.
+
+    The default implementation of this function returns true.
+
+    \sa QtProperty::hasValue()
+*/
+bool QtAbstractPropertyManager::hasValue(const QtProperty *property) const
+{
+    Q_UNUSED(property)
+    return true;
+}
+
+/*!
+    Returns an icon representing the current state of the given \a
+    property.
+
+    The default implementation of this function returns an invalid
+    icon.
+
+    \sa QtProperty::valueIcon()
+*/
+QIcon QtAbstractPropertyManager::valueIcon(const QtProperty *property) const
+{
+    Q_UNUSED(property)
+    return QIcon();
+}
+
+/*!
+    Returns a string representing the current state of the given \a
+    property.
+
+    The default implementation of this function returns an empty
+    string.
+
+    \sa QtProperty::valueText()
+*/
+QString QtAbstractPropertyManager::valueText(const QtProperty *property) const
+{
+    Q_UNUSED(property)
+    return QString();
+}
+
+/*!
+    Creates a property with the given \a name which then is owned by this manager.
+
+    Internally, this function calls the createProperty() and
+    initializeProperty() functions.
+
+    \sa initializeProperty(), properties()
+*/
+QtProperty *QtAbstractPropertyManager::addProperty(const QString &name)
+{
+    QtProperty *property = createProperty();
+    if (property) {
+        property->setPropertyName(name);
+        d_ptr->m_properties.insert(property);
+        initializeProperty(property);
+    }
+    return property;
+}
+
+/*!
+    Creates a property.
+
+    The base implementation produce QtProperty instances; Reimplement
+    this function to make this manager produce objects of a QtProperty
+    subclass.
+
+    \sa addProperty(), initializeProperty()
+*/
+QtProperty *QtAbstractPropertyManager::createProperty()
+{
+    return new QtProperty(this);
+}
+
+/*!
+    \fn void QtAbstractPropertyManager::initializeProperty(QtProperty *property) = 0
+
+    This function is called whenever a new valid property pointer has
+    been created, passing the pointer as parameter.
+
+    The purpose is to let the manager know that the \a property has
+    been created so that it can provide additional attributes for the
+    new property, e.g. QtIntPropertyManager adds \l
+    {QtIntPropertyManager::value()}{value}, \l
+    {QtIntPropertyManager::minimum()}{minimum} and \l
+    {QtIntPropertyManager::maximum()}{maximum} attributes. Since each manager
+    subclass adds type specific attributes, this function is pure
+    virtual and must be reimplemented when deriving from the
+    QtAbstractPropertyManager class.
+
+    \sa addProperty(), createProperty()
+*/
+
+/*!
+    This function is called just before the specified \a property is destroyed.
+
+    The purpose is to let the property manager know that the \a
+    property is being destroyed so that it can remove the property's
+    additional attributes.
+
+    \sa clear(),  propertyDestroyed()
+*/
+void QtAbstractPropertyManager::uninitializeProperty(QtProperty *property)
+{
+    Q_UNUSED(property)
+}
+
+////////////////////////////////////
+
+/*!
+    \class QtAbstractEditorFactoryBase
+    \internal
+    \inmodule QtDesigner
+    \since 4.4
+
+    \brief The QtAbstractEditorFactoryBase provides an interface for
+    editor factories.
+
+    An editor factory is a class that is able to create an editing
+    widget of a specified type (e.g. line edits or comboboxes) for a
+    given QtProperty object, and it is used in conjunction with the
+    QtAbstractPropertyManager and QtAbstractPropertyBrowser classes.
+
+    When using a property browser widget, the properties are created
+    and managed by implementations of the QtAbstractPropertyManager
+    class. To ensure that the properties' values will be displayed
+    using suitable editing widgets, the managers are associated with
+    objects of QtAbstractEditorFactory subclasses. The property browser
+    will use these associations to determine which factories it should
+    use to create the preferred editing widgets.
+
+    Typically, an editor factory is created by subclassing the
+    QtAbstractEditorFactory template class which inherits
+    QtAbstractEditorFactoryBase. But note that several ready-made
+    implementations are available:
+
+    \list
+    \o QtCheckBoxFactory
+    \o QtDateEditFactory
+    \o QtDateTimeEditFactory
+    \o QtDoubleSpinBoxFactory
+    \o QtEnumEditorFactory
+    \o QtLineEditFactory
+    \o QtScrollBarFactory
+    \o QtSliderFactory
+    \o QtSpinBoxFactory
+    \o QtTimeEditFactory
+    \o QtVariantEditorFactory
+    \endlist
+
+    \sa QtAbstractPropertyManager, QtAbstractPropertyBrowser
+*/
+
+/*!
+    \fn virtual QWidget *QtAbstractEditorFactoryBase::createEditor(QtProperty *property,
+        QWidget *parent) = 0
+
+    Creates an editing widget (with the given \a parent) for the given
+    \a property.
+
+    This function is reimplemented in QtAbstractEditorFactory template class
+    which also provides a pure virtual convenience overload of this
+    function enabling access to the property's manager.
+
+    \sa  QtAbstractEditorFactory::createEditor()
+*/
+
+/*!
+    \fn QtAbstractEditorFactoryBase::QtAbstractEditorFactoryBase(QObject *parent = 0)
+
+    Creates an abstract editor factory with the given \a parent.
+*/
+
+/*!
+    \fn virtual void QtAbstractEditorFactoryBase::breakConnection(QtAbstractPropertyManager *manager) = 0
+
+    \internal
+
+    Detaches property manager from factory.
+    This method is reimplemented in QtAbstractEditorFactory template subclass.
+    You don't need to reimplement it in your subclasses. Instead implement more convenient
+    QtAbstractEditorFactory::disconnectPropertyManager() which gives you access to particular manager subclass.
+*/
+
+/*!
+    \fn virtual void QtAbstractEditorFactoryBase::managerDestroyed(QObject *manager) = 0
+
+    \internal
+
+    This method is called when property manager is being destroyed.
+    Basically it notifies factory not to produce editors for properties owned by \a manager.
+    You don't need to reimplement it in your subclass. This method is implemented in
+    QtAbstractEditorFactory template subclass.
+*/
+
+/*!
+    \class QtAbstractEditorFactory
+    \internal
+    \inmodule QtDesigner
+    \since 4.4
+
+    \brief The QtAbstractEditorFactory is the base template class for editor
+    factories.
+
+    An editor factory is a class that is able to create an editing
+    widget of a specified type (e.g. line edits or comboboxes) for a
+    given QtProperty object, and it is used in conjunction with the
+    QtAbstractPropertyManager and QtAbstractPropertyBrowser classes.
+
+    Note that the QtAbstractEditorFactory functions are using the
+    PropertyManager template argument class which can be any
+    QtAbstractPropertyManager subclass. For example:
+
+    \snippet doc/src/snippets/code/tools_shared_qtpropertybrowser_qtpropertybrowser.cpp 0
+
+    Note that QtSpinBoxFactory by definition creates editing widgets
+    \e only for properties created by QtIntPropertyManager.
+
+    When using a property browser widget, the properties are created
+    and managed by implementations of the QtAbstractPropertyManager
+    class. To ensure that the properties' values will be displayed
+    using suitable editing widgets, the managers are associated with
+    objects of QtAbstractEditorFactory subclasses. The property browser will
+    use these associations to determine which factories it should use
+    to create the preferred editing widgets.
+
+    A QtAbstractEditorFactory object is capable of producing editors for
+    several property managers at the same time. To create an
+    association between this factory and a given manager, use the
+    addPropertyManager() function. Use the removePropertyManager() function to make
+    this factory stop producing editors for a given property
+    manager. Use the propertyManagers() function to retrieve the set of
+    managers currently associated with this factory.
+
+    Several ready-made implementations of the QtAbstractEditorFactory class
+    are available:
+
+    \list
+    \o QtCheckBoxFactory
+    \o QtDateEditFactory
+    \o QtDateTimeEditFactory
+    \o QtDoubleSpinBoxFactory
+    \o QtEnumEditorFactory
+    \o QtLineEditFactory
+    \o QtScrollBarFactory
+    \o QtSliderFactory
+    \o QtSpinBoxFactory
+    \o QtTimeEditFactory
+    \o QtVariantEditorFactory
+    \endlist
+
+    When deriving from the QtAbstractEditorFactory class, several pure virtual
+    functions must be implemented: the connectPropertyManager() function is
+    used by the factory to connect to the given manager's signals, the
+    createEditor() function is supposed to create an editor for the
+    given property controlled by the given manager, and finally the
+    disconnectPropertyManager() function is used by the factory to disconnect
+    from the specified manager's signals.
+
+    \sa QtAbstractEditorFactoryBase, QtAbstractPropertyManager
+*/
+
+/*!
+    \fn QtAbstractEditorFactory::QtAbstractEditorFactory(QObject *parent = 0)
+
+    Creates an editor factory with the given \a parent.
+
+    \sa addPropertyManager()
+*/
+
+/*!
+    \fn QWidget *QtAbstractEditorFactory::createEditor(QtProperty *property, QWidget *parent)
+
+    Creates an editing widget (with the given \a parent) for the given
+    \a property.
+*/
+
+/*!
+    \fn void QtAbstractEditorFactory::addPropertyManager(PropertyManager *manager)
+
+    Adds the given \a manager to this factory's set of managers,
+    making this factory produce editing widgets for properties created
+    by the given manager.
+
+    The PropertyManager type is a template argument class, and represents the chosen
+    QtAbstractPropertyManager subclass.
+
+    \sa propertyManagers(), removePropertyManager()
+*/
+
+/*!
+    \fn void QtAbstractEditorFactory::removePropertyManager(PropertyManager *manager)
+
+    Removes the given \a manager from this factory's set of
+    managers. The PropertyManager type is a template argument class, and may be
+    any QtAbstractPropertyManager subclass.
+
+    \sa propertyManagers(), addPropertyManager()
+*/
+
+/*!
+    \fn virtual void QtAbstractEditorFactory::connectPropertyManager(PropertyManager *manager) = 0
+
+    Connects this factory to the given \a manager's signals.  The
+    PropertyManager type is a template argument class, and represents
+    the chosen QtAbstractPropertyManager subclass.
+
+    This function is used internally by the addPropertyManager() function, and
+    makes it possible to update an editing widget when the associated
+    property's data changes. This is typically done in custom slots
+    responding to the signals emitted by the property's manager,
+    e.g. QtIntPropertyManager::valueChanged() and
+    QtIntPropertyManager::rangeChanged().
+
+    \sa propertyManagers(), disconnectPropertyManager()
+*/
+
+/*!
+    \fn virtual QWidget *QtAbstractEditorFactory::createEditor(PropertyManager *manager, QtProperty *property,
+                QWidget *parent) = 0
+
+    Creates an editing widget with the given \a parent for the
+    specified \a property created by the given \a manager. The
+    PropertyManager type is a template argument class, and represents
+    the chosen QtAbstractPropertyManager subclass.
+
+    This function must be implemented in derived classes: It is
+    recommended to store a pointer to the widget and map it to the
+    given \a property, since the widget must be updated whenever the
+    associated property's data changes. This is typically done in
+    custom slots responding to the signals emitted by the property's
+    manager, e.g. QtIntPropertyManager::valueChanged() and
+    QtIntPropertyManager::rangeChanged().
+
+    \sa connectPropertyManager()
+*/
+
+/*!
+    \fn virtual void QtAbstractEditorFactory::disconnectPropertyManager(PropertyManager *manager) = 0
+
+    Disconnects this factory from the given \a manager's signals. The
+    PropertyManager type is a template argument class, and represents
+    the chosen QtAbstractPropertyManager subclass.
+
+    This function is used internally by the removePropertyManager() function.
+
+    \sa propertyManagers(), connectPropertyManager()
+*/
+
+/*!
+    \fn QSet<PropertyManager *> QtAbstractEditorFactory::propertyManagers() const
+
+    Returns the factory's set of associated managers.  The
+    PropertyManager type is a template argument class, and represents
+    the chosen QtAbstractPropertyManager subclass.
+
+    \sa addPropertyManager(), removePropertyManager()
+*/
+
+/*!
+    \fn PropertyManager *QtAbstractEditorFactory::propertyManager(QtProperty *property) const
+
+    Returns the property manager for the given \a property, or 0 if
+    the given \a property doesn't belong to any of this factory's
+    registered managers.
+
+    The PropertyManager type is a template argument class, and represents the chosen
+    QtAbstractPropertyManager subclass.
+
+    \sa propertyManagers()
+*/
+
+/*!
+    \fn virtual void QtAbstractEditorFactory::managerDestroyed(QObject *manager)
+
+    \internal
+    \reimp
+*/
+
+////////////////////////////////////
+class QtBrowserItemPrivate
+{
+public:
+    QtBrowserItemPrivate(QtAbstractPropertyBrowser *browser, QtProperty *property, QtBrowserItem *parent)
+        : m_browser(browser), m_property(property), m_parent(parent), q_ptr(0) {}
+
+    void addChild(QtBrowserItem *index, QtBrowserItem *after);
+    void removeChild(QtBrowserItem *index);
+
+    QtAbstractPropertyBrowser * const m_browser;
+    QtProperty *m_property;
+    QtBrowserItem *m_parent;
+
+    QtBrowserItem *q_ptr;
+
+    QList<QtBrowserItem *> m_children;
+
+};
+
+void QtBrowserItemPrivate::addChild(QtBrowserItem *index, QtBrowserItem *after)
+{
+    if (m_children.contains(index))
+        return;
+    int idx = m_children.indexOf(after) + 1; // we insert after returned idx, if it was -1 then we set idx to 0;
+    m_children.insert(idx, index);
+}
+
+void QtBrowserItemPrivate::removeChild(QtBrowserItem *index)
+{
+    m_children.removeAll(index);
+}
+
+
+/*!
+    \class QtBrowserItem
+    \internal
+    \inmodule QtDesigner
+    \since 4.4
+
+    \brief The QtBrowserItem class represents a property in
+    a property browser instance.
+
+    Browser items are created whenever a QtProperty is inserted to the
+    property browser. A QtBrowserItem uniquely identifies a
+    browser's item. Thus, if the same QtProperty is inserted multiple
+    times, each occurrence gets its own unique QtBrowserItem. The
+    items are owned by QtAbstractPropertyBrowser and automatically
+    deleted when they are removed from the browser.
+
+    You can traverse a browser's properties by calling parent() and
+    children(). The property and the browser associated with an item
+    are available as property() and browser().
+
+    \sa QtAbstractPropertyBrowser, QtProperty
+*/
+
+/*!
+    Returns the property which is accosiated with this item. Note that
+    several items can be associated with the same property instance in
+    the same property browser.
+
+    \sa QtAbstractPropertyBrowser::items()
+*/
+
+QtProperty *QtBrowserItem::property() const
+{
+    return d_ptr->m_property;
+}
+
+/*!
+    Returns the parent item of \e this item. Returns 0 if \e this item
+    is associated with top-level property in item's property browser.
+
+    \sa children()
+*/
+
+QtBrowserItem *QtBrowserItem::parent() const
+{
+    return d_ptr->m_parent;
+}
+
+/*!
+    Returns the children items of \e this item. The properties
+    reproduced from children items are always the same as
+    reproduced from associated property' children, for example:
+
+    \snippet doc/src/snippets/code/tools_shared_qtpropertybrowser_qtpropertybrowser.cpp 1
+
+    The \e childrenItems list represents the same list as \e childrenProperties.
+*/
+
+QList<QtBrowserItem *> QtBrowserItem::children() const
+{
+    return d_ptr->m_children;
+}
+
+/*!
+    Returns the property browser which owns \e this item.
+*/
+
+QtAbstractPropertyBrowser *QtBrowserItem::browser() const
+{
+    return d_ptr->m_browser;
+}
+
+QtBrowserItem::QtBrowserItem(QtAbstractPropertyBrowser *browser, QtProperty *property, QtBrowserItem *parent)
+    : d_ptr(new QtBrowserItemPrivate(browser, property, parent))
+{
+    d_ptr->q_ptr = this;
+}
+
+QtBrowserItem::~QtBrowserItem()
+{
+}
+
+
+////////////////////////////////////
+
+typedef QMap<QtAbstractPropertyBrowser *, QMap<QtAbstractPropertyManager *,
+                            QtAbstractEditorFactoryBase *> > Map1;
+typedef QMap<QtAbstractPropertyManager *, QMap<QtAbstractEditorFactoryBase *,
+                            QList<QtAbstractPropertyBrowser *> > > Map2;
+Q_GLOBAL_STATIC(Map1, m_viewToManagerToFactory)
+Q_GLOBAL_STATIC(Map2, m_managerToFactoryToViews)
+
+class QtAbstractPropertyBrowserPrivate
+{
+    QtAbstractPropertyBrowser *q_ptr;
+    Q_DECLARE_PUBLIC(QtAbstractPropertyBrowser)
+public:
+    QtAbstractPropertyBrowserPrivate();
+
+    void insertSubTree(QtProperty *property,
+            QtProperty *parentProperty);
+    void removeSubTree(QtProperty *property,
+            QtProperty *parentProperty);
+    void createBrowserIndexes(QtProperty *property, QtProperty *parentProperty, QtProperty *afterProperty);
+    void removeBrowserIndexes(QtProperty *property, QtProperty *parentProperty);
+    QtBrowserItem *createBrowserIndex(QtProperty *property, QtBrowserItem *parentIndex, QtBrowserItem *afterIndex);
+    void removeBrowserIndex(QtBrowserItem *index);
+    void clearIndex(QtBrowserItem *index);
+
+    void slotPropertyInserted(QtProperty *property,
+            QtProperty *parentProperty, QtProperty *afterProperty);
+    void slotPropertyRemoved(QtProperty *property, QtProperty *parentProperty);
+    void slotPropertyDestroyed(QtProperty *property);
+    void slotPropertyDataChanged(QtProperty *property);
+
+    QList<QtProperty *> m_subItems;
+    QMap<QtAbstractPropertyManager *, QList<QtProperty *> > m_managerToProperties;
+    QMap<QtProperty *, QList<QtProperty *> > m_propertyToParents;
+
+    QMap<QtProperty *, QtBrowserItem *> m_topLevelPropertyToIndex;
+    QList<QtBrowserItem *> m_topLevelIndexes;
+    QMap<QtProperty *, QList<QtBrowserItem *> > m_propertyToIndexes;
+
+    QtBrowserItem *m_currentItem;
+};
+
+QtAbstractPropertyBrowserPrivate::QtAbstractPropertyBrowserPrivate() :
+   m_currentItem(0)
+{
+}
+
+void QtAbstractPropertyBrowserPrivate::insertSubTree(QtProperty *property,
+            QtProperty *parentProperty)
+{
+    if (m_propertyToParents.contains(property)) {
+        // property was already inserted, so its manager is connected
+        // and all its children are inserted and theirs managers are connected
+        // we just register new parent (parent has to be new).
+        m_propertyToParents[property].append(parentProperty);
+        // don't need to update m_managerToProperties map since
+        // m_managerToProperties[manager] already contains property.
+        return;
+    }
+    QtAbstractPropertyManager *manager = property->propertyManager();
+    if (m_managerToProperties[manager].isEmpty()) {
+        // connect manager's signals
+        q_ptr->connect(manager, SIGNAL(propertyInserted(QtProperty *,
+                            QtProperty *, QtProperty *)),
+                q_ptr, SLOT(slotPropertyInserted(QtProperty *,
+                            QtProperty *, QtProperty *)));
+        q_ptr->connect(manager, SIGNAL(propertyRemoved(QtProperty *,
+                            QtProperty *)),
+                q_ptr, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *)));
+        q_ptr->connect(manager, SIGNAL(propertyDestroyed(QtProperty *)),
+                q_ptr, SLOT(slotPropertyDestroyed(QtProperty *)));
+        q_ptr->connect(manager, SIGNAL(propertyChanged(QtProperty *)),
+                q_ptr, SLOT(slotPropertyDataChanged(QtProperty *)));
+    }
+    m_managerToProperties[manager].append(property);
+    m_propertyToParents[property].append(parentProperty);
+
+    QList<QtProperty *> subList = property->subProperties();
+    QListIterator<QtProperty *> itSub(subList);
+    while (itSub.hasNext()) {
+        QtProperty *subProperty = itSub.next();
+        insertSubTree(subProperty, property);
+    }
+}
+
+void QtAbstractPropertyBrowserPrivate::removeSubTree(QtProperty *property,
+            QtProperty *parentProperty)
+{
+    if (!m_propertyToParents.contains(property)) {
+        // ASSERT
+        return;
+    }
+
+    m_propertyToParents[property].removeAll(parentProperty);
+    if (!m_propertyToParents[property].isEmpty())
+        return;
+
+    m_propertyToParents.remove(property);
+    QtAbstractPropertyManager *manager = property->propertyManager();
+    m_managerToProperties[manager].removeAll(property);
+    if (m_managerToProperties[manager].isEmpty()) {
+        // disconnect manager's signals
+        q_ptr->disconnect(manager, SIGNAL(propertyInserted(QtProperty *,
+                            QtProperty *, QtProperty *)),
+                q_ptr, SLOT(slotPropertyInserted(QtProperty *,
+                            QtProperty *, QtProperty *)));
+        q_ptr->disconnect(manager, SIGNAL(propertyRemoved(QtProperty *,
+                            QtProperty *)),
+                q_ptr, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *)));
+        q_ptr->disconnect(manager, SIGNAL(propertyDestroyed(QtProperty *)),
+                q_ptr, SLOT(slotPropertyDestroyed(QtProperty *)));
+        q_ptr->disconnect(manager, SIGNAL(propertyChanged(QtProperty *)),
+                q_ptr, SLOT(slotPropertyDataChanged(QtProperty *)));
+
+        m_managerToProperties.remove(manager);
+    }
+
+    QList<QtProperty *> subList = property->subProperties();
+    QListIterator<QtProperty *> itSub(subList);
+    while (itSub.hasNext()) {
+        QtProperty *subProperty = itSub.next();
+        removeSubTree(subProperty, property);
+    }
+}
+
+void QtAbstractPropertyBrowserPrivate::createBrowserIndexes(QtProperty *property, QtProperty *parentProperty, QtProperty *afterProperty)
+{
+    QMap<QtBrowserItem *, QtBrowserItem *> parentToAfter;
+    if (afterProperty) {
+        QMap<QtProperty *, QList<QtBrowserItem *> >::ConstIterator it =
+            m_propertyToIndexes.find(afterProperty);
+        if (it == m_propertyToIndexes.constEnd())
+            return;
+
+        QList<QtBrowserItem *> indexes = it.value();
+        QListIterator<QtBrowserItem *> itIndex(indexes);
+        while (itIndex.hasNext()) {
+            QtBrowserItem *idx = itIndex.next();
+            QtBrowserItem *parentIdx = idx->parent();
+            if ((parentProperty && parentIdx && parentIdx->property() == parentProperty) || (!parentProperty && !parentIdx))
+                parentToAfter[idx->parent()] = idx;
+        }
+    } else if (parentProperty) {
+        QMap<QtProperty *, QList<QtBrowserItem *> >::ConstIterator it =
+                m_propertyToIndexes.find(parentProperty);
+        if (it == m_propertyToIndexes.constEnd())
+            return;
+
+        QList<QtBrowserItem *> indexes = it.value();
+        QListIterator<QtBrowserItem *> itIndex(indexes);
+        while (itIndex.hasNext()) {
+            QtBrowserItem *idx = itIndex.next();
+            parentToAfter[idx] = 0;
+        }
+    } else {
+        parentToAfter[0] = 0;
+    }
+
+    const QMap<QtBrowserItem *, QtBrowserItem *>::ConstIterator pcend = parentToAfter.constEnd();
+    for (QMap<QtBrowserItem *, QtBrowserItem *>::ConstIterator it = parentToAfter.constBegin(); it != pcend; ++it)
+        createBrowserIndex(property, it.key(), it.value());
+}
+
+QtBrowserItem *QtAbstractPropertyBrowserPrivate::createBrowserIndex(QtProperty *property,
+        QtBrowserItem *parentIndex, QtBrowserItem *afterIndex)
+{
+    QtBrowserItem *newIndex = new QtBrowserItem(q_ptr, property, parentIndex);
+    if (parentIndex) {
+        parentIndex->d_ptr->addChild(newIndex, afterIndex);
+    } else {
+        m_topLevelPropertyToIndex[property] = newIndex;
+        m_topLevelIndexes.insert(m_topLevelIndexes.indexOf(afterIndex) + 1, newIndex);
+    }
+    m_propertyToIndexes[property].append(newIndex);
+
+    q_ptr->itemInserted(newIndex, afterIndex);
+
+    QList<QtProperty *> subItems = property->subProperties();
+    QListIterator<QtProperty *> itChild(subItems);
+    QtBrowserItem *afterChild = 0;
+    while (itChild.hasNext()) {
+        QtProperty *child = itChild.next();
+        afterChild = createBrowserIndex(child, newIndex, afterChild);
+    }
+    return newIndex;
+}
+
+void QtAbstractPropertyBrowserPrivate::removeBrowserIndexes(QtProperty *property, QtProperty *parentProperty)
+{
+    QList<QtBrowserItem *> toRemove;
+    QMap<QtProperty *, QList<QtBrowserItem *> >::ConstIterator it =
+        m_propertyToIndexes.find(property);
+    if (it == m_propertyToIndexes.constEnd())
+        return;
+
+    QList<QtBrowserItem *> indexes = it.value();
+    QListIterator<QtBrowserItem *> itIndex(indexes);
+    while (itIndex.hasNext()) {
+        QtBrowserItem *idx = itIndex.next();
+        QtBrowserItem *parentIdx = idx->parent();
+        if ((parentProperty && parentIdx && parentIdx->property() == parentProperty) || (!parentProperty && !parentIdx))
+            toRemove.append(idx);
+    }
+
+    QListIterator<QtBrowserItem *> itRemove(toRemove);
+    while (itRemove.hasNext()) {
+        QtBrowserItem *index = itRemove.next();
+        removeBrowserIndex(index);
+    }
+}
+
+void QtAbstractPropertyBrowserPrivate::removeBrowserIndex(QtBrowserItem *index)
+{
+    QList<QtBrowserItem *> children = index->children();
+    for (int i = children.count(); i > 0; i--) {
+        removeBrowserIndex(children.at(i - 1));
+    }
+
+    q_ptr->itemRemoved(index);
+
+    if (index->parent()) {
+        index->parent()->d_ptr->removeChild(index);
+    } else {
+        m_topLevelPropertyToIndex.remove(index->property());
+        m_topLevelIndexes.removeAll(index);
+    }
+
+    QtProperty *property = index->property();
+
+    m_propertyToIndexes[property].removeAll(index);
+    if (m_propertyToIndexes[property].isEmpty())
+        m_propertyToIndexes.remove(property);
+
+    delete index;
+}
+
+void QtAbstractPropertyBrowserPrivate::clearIndex(QtBrowserItem *index)
+{
+    QList<QtBrowserItem *> children = index->children();
+    QListIterator<QtBrowserItem *> itChild(children);
+    while (itChild.hasNext()) {
+        clearIndex(itChild.next());
+    }
+    delete index;
+}
+
+void QtAbstractPropertyBrowserPrivate::slotPropertyInserted(QtProperty *property,
+        QtProperty *parentProperty, QtProperty *afterProperty)
+{
+    if (!m_propertyToParents.contains(parentProperty))
+        return;
+    createBrowserIndexes(property, parentProperty, afterProperty);
+    insertSubTree(property, parentProperty);
+    //q_ptr->propertyInserted(property, parentProperty, afterProperty);
+}
+
+void QtAbstractPropertyBrowserPrivate::slotPropertyRemoved(QtProperty *property,
+        QtProperty *parentProperty)
+{
+    if (!m_propertyToParents.contains(parentProperty))
+        return;
+    removeSubTree(property, parentProperty); // this line should be probably moved down after propertyRemoved call
+    //q_ptr->propertyRemoved(property, parentProperty);
+    removeBrowserIndexes(property, parentProperty);
+}
+
+void QtAbstractPropertyBrowserPrivate::slotPropertyDestroyed(QtProperty *property)
+{
+    if (!m_subItems.contains(property))
+        return;
+    q_ptr->removeProperty(property);
+}
+
+void QtAbstractPropertyBrowserPrivate::slotPropertyDataChanged(QtProperty *property)
+{
+    if (!m_propertyToParents.contains(property))
+        return;
+
+    QMap<QtProperty *, QList<QtBrowserItem *> >::ConstIterator it =
+            m_propertyToIndexes.find(property);
+    if (it == m_propertyToIndexes.constEnd())
+        return;
+
+    QList<QtBrowserItem *> indexes = it.value();
+    QListIterator<QtBrowserItem *> itIndex(indexes);
+    while (itIndex.hasNext()) {
+        QtBrowserItem *idx = itIndex.next();
+        q_ptr->itemChanged(idx);
+    }
+    //q_ptr->propertyChanged(property);
+}
+
+/*!
+    \class QtAbstractPropertyBrowser
+    \internal
+    \inmodule QtDesigner
+    \since 4.4
+
+    \brief QtAbstractPropertyBrowser provides a base class for
+    implementing property browsers.
+
+    A property browser is a widget that enables the user to edit a
+    given set of properties.  Each property is represented by a label
+    specifying the property's name, and an editing widget (e.g. a line
+    edit or a combobox) holding its value. A property can have zero or
+    more subproperties.
+
+    \image qtpropertybrowser.png
+
+    The top level properties can be retrieved using the
+    properties() function. To traverse each property's
+    subproperties, use the QtProperty::subProperties() function. In
+    addition, the set of top level properties can be manipulated using
+    the addProperty(), insertProperty() and removeProperty()
+    functions. Note that the QtProperty class provides a corresponding
+    set of functions making it possible to manipulate the set of
+    subproperties as well.
+
+    To remove all the properties from the property browser widget, use
+    the clear() function. This function will clear the editor, but it
+    will not delete the properties since they can still be used in
+    other editors.
+
+    The properties themselves are created and managed by
+    implementations of the QtAbstractPropertyManager class. A manager
+    can handle (i.e. create and manage) properties of a given type. In
+    the property browser the managers are associated with
+    implementations of the QtAbstractEditorFactory: A factory is a
+    class able to create an editing widget of a specified type.
+
+    When using a property browser widget, managers must be created for
+    each of the required property types before the properties
+    themselves can be created. To ensure that the properties' values
+    will be displayed using suitable editing widgets, the managers
+    must be associated with objects of the preferred factory
+    implementations using the setFactoryForManager() function. The
+    property browser will use these associations to determine which
+    factory it should use to create the preferred editing widget.
+
+    Note that a factory can be associated with many managers, but a
+    manager can only be associated with one single factory within the
+    context of a single property browser.  The associations between
+    managers and factories can at any time be removed using the
+    unsetFactoryForManager() function.
+
+    Whenever the property data changes or a property is inserted or
+    removed, the itemChanged(), itemInserted() or
+    itemRemoved() functions are called, respectively. These
+    functions must be reimplemented in derived classes in order to
+    update the property browser widget. Be aware that some property
+    instances can appear several times in an abstract tree
+    structure. For example:
+
+    \table 100%
+    \row
+    \o
+    \snippet doc/src/snippets/code/tools_shared_qtpropertybrowser_qtpropertybrowser.cpp 2
+    \o  \image qtpropertybrowser-duplicate.png
+    \endtable
+
+    The addProperty() function returns a QtBrowserItem that uniquely
+    identifies the created item.
+
+    To make a property editable in the property browser, the
+    createEditor() function must be called to provide the
+    property with a suitable editing widget.
+
+    Note that there are two ready-made property browser
+    implementations:
+
+    \list
+        \o QtGroupBoxPropertyBrowser
+        \o QtTreePropertyBrowser
+    \endlist
+
+    \sa QtAbstractPropertyManager, QtAbstractEditorFactoryBase
+*/
+
+/*!
+    \fn void QtAbstractPropertyBrowser::setFactoryForManager(PropertyManager *manager,
+                    QtAbstractEditorFactory<PropertyManager> *factory)
+
+    Connects the given \a manager to the given \a factory, ensuring
+    that properties of the \a manager's type will be displayed with an
+    editing widget suitable for their value.
+
+    For example:
+
+    \snippet doc/src/snippets/code/tools_shared_qtpropertybrowser_qtpropertybrowser.cpp 3
+
+    In this example the \c myInteger property's value is displayed
+    with a QSpinBox widget, while the \c myDouble property's value is
+    displayed with a QDoubleSpinBox widget.
+
+    Note that a factory can be associated with many managers, but a
+    manager can only be associated with one single factory.  If the
+    given \a manager already is associated with another factory, the
+    old association is broken before the new one established.
+
+    This function ensures that the given \a manager and the given \a
+    factory are compatible, and it automatically calls the
+    QtAbstractEditorFactory::addPropertyManager() function if necessary.
+
+    \sa unsetFactoryForManager()
+*/
+
+/*!
+    \fn virtual void QtAbstractPropertyBrowser::itemInserted(QtBrowserItem *insertedItem,
+        QtBrowserItem *precedingItem) = 0
+
+    This function is called to update the widget whenever a property
+    is inserted or added to the property browser, passing pointers to
+    the \a insertedItem of property and the specified
+    \a precedingItem as parameters.
+
+    If \a precedingItem is 0, the \a insertedItem was put at
+    the beginning of its parent item's list of subproperties. If
+    the parent of \a insertedItem is 0, the \a insertedItem was added as a top
+    level property of \e this property browser.
+
+    This function must be reimplemented in derived classes. Note that
+    if the \a insertedItem's property has subproperties, this
+    method will be called for those properties as soon as the current call is finished.
+
+    \sa insertProperty(), addProperty()
+*/
+
+/*!
+    \fn virtual void QtAbstractPropertyBrowser::itemRemoved(QtBrowserItem *item) = 0
+
+    This function is called to update the widget whenever a property
+    is removed from the property browser, passing the pointer to the
+    \a item of the property as parameters. The passed \a item is
+    deleted just after this call is finished.
+
+    If the the parent of \a item is 0, the removed \a item was a
+    top level property in this editor.
+
+    This function must be reimplemented in derived classes. Note that
+    if the removed \a item's property has subproperties, this
+    method will be called for those properties just before the current call is started.
+
+    \sa removeProperty()
+*/
+
+/*!
+    \fn virtual void QtAbstractPropertyBrowser::itemChanged(QtBrowserItem *item) = 0
+
+    This function is called whenever a property's data changes,
+    passing a pointer to the \a item of property as parameter.
+
+    This function must be reimplemented in derived classes in order to
+    update the property browser widget whenever a property's name,
+    tool tip, status tip, "what's this" text, value text or value icon
+    changes.
+
+    Note that if the property browser contains several occurrences of
+    the same property, this method will be called once for each
+    occurrence (with a different item each time).
+
+    \sa QtProperty, items()
+*/
+
+/*!
+    Creates an abstract property browser with the given \a parent.
+*/
+QtAbstractPropertyBrowser::QtAbstractPropertyBrowser(QWidget *parent)
+    : QWidget(parent), d_ptr(new QtAbstractPropertyBrowserPrivate)
+{
+    d_ptr->q_ptr = this;
+
+}
+
+/*!
+    Destroys the property browser, and destroys all the items that were
+    created by this property browser.
+
+    Note that the properties that were displayed in the editor are not
+    deleted since they still can be used in other editors. Neither
+    does the destructor delete the property managers and editor
+    factories that were used by this property browser widget unless
+    this widget was their parent.
+
+    \sa QtAbstractPropertyManager::~QtAbstractPropertyManager()
+*/
+QtAbstractPropertyBrowser::~QtAbstractPropertyBrowser()
+{
+    QList<QtBrowserItem *> indexes = topLevelItems();
+    QListIterator<QtBrowserItem *> itItem(indexes);
+    while (itItem.hasNext())
+        d_ptr->clearIndex(itItem.next());
+}
+
+/*!
+    Returns the property browser's list of top level properties.
+
+    To traverse the subproperties, use the QtProperty::subProperties()
+    function.
+
+    \sa addProperty(), insertProperty(), removeProperty()
+*/
+QList<QtProperty *> QtAbstractPropertyBrowser::properties() const
+{
+    return d_ptr->m_subItems;
+}
+
+/*!
+    Returns the property browser's list of all items associated
+    with the given \a property.
+
+    There is one item per instance of the property in the browser.
+
+    \sa topLevelItem()
+*/
+
+QList<QtBrowserItem *> QtAbstractPropertyBrowser::items(QtProperty *property) const
+{
+    return d_ptr->m_propertyToIndexes.value(property);
+}
+
+/*!
+    Returns the top-level items associated with the given \a property.
+
+    Returns 0 if \a property wasn't inserted into this property
+    browser or isn't a top-level one.
+
+    \sa topLevelItems(), items()
+*/
+
+QtBrowserItem *QtAbstractPropertyBrowser::topLevelItem(QtProperty *property) const
+{
+    return d_ptr->m_topLevelPropertyToIndex.value(property);
+}
+
+/*!
+    Returns the list of top-level items.
+
+    \sa topLevelItem()
+*/
+
+QList<QtBrowserItem *> QtAbstractPropertyBrowser::topLevelItems() const
+{
+    return d_ptr->m_topLevelIndexes;
+}
+
+/*!
+    Removes all the properties from the editor, but does not delete
+    them since they can still be used in other editors.
+
+    \sa removeProperty(), QtAbstractPropertyManager::clear()
+*/
+void QtAbstractPropertyBrowser::clear()
+{
+    QList<QtProperty *> subList = properties();
+    QListIterator<QtProperty *> itSub(subList);
+    itSub.toBack();
+    while (itSub.hasPrevious()) {
+        QtProperty *property = itSub.previous();
+        removeProperty(property);
+    }
+}
+
+/*!
+    Appends the given \a property (and its subproperties) to the
+    property browser's list of top level properties. Returns the item
+    created by property browser which is associated with the \a property.
+    In order to get all children items created by the property
+    browser in this call, the returned item should be traversed.
+
+    If the specified \a property is already added, this function does
+    nothing and returns 0.
+
+    \sa insertProperty(), QtProperty::addSubProperty(), properties()
+*/
+QtBrowserItem *QtAbstractPropertyBrowser::addProperty(QtProperty *property)
+{
+    QtProperty *afterProperty = 0;
+    if (d_ptr->m_subItems.count() > 0)
+        afterProperty = d_ptr->m_subItems.last();
+    return insertProperty(property, afterProperty);
+}
+
+/*!
+    \fn QtBrowserItem *QtAbstractPropertyBrowser::insertProperty(QtProperty *property,
+            QtProperty *afterProperty)
+
+    Inserts the given \a property (and its subproperties) after
+    the specified \a afterProperty in the browser's list of top
+    level properties. Returns item created by property browser which
+    is associated with the \a property. In order to get all children items
+    created by the property browser in this call returned item should be traversed.
+
+    If the specified \a afterProperty is 0, the given \a property is
+    inserted at the beginning of the list.  If \a property is
+    already inserted, this function does nothing and returns 0.
+
+    \sa addProperty(), QtProperty::insertSubProperty(), properties()
+*/
+QtBrowserItem *QtAbstractPropertyBrowser::insertProperty(QtProperty *property,
+            QtProperty *afterProperty)
+{
+    if (!property)
+        return 0;
+
+    // if item is already inserted in this item then cannot add.
+    QList<QtProperty *> pendingList = properties();
+    int pos = 0;
+    int newPos = 0;
+    QtProperty *properAfterProperty = 0;
+    while (pos < pendingList.count()) {
+        QtProperty *prop = pendingList.at(pos);
+        if (prop == property)
+            return 0;
+        if (prop == afterProperty) {
+            newPos = pos + 1;
+            properAfterProperty = afterProperty;
+        }
+        pos++;
+    }
+    d_ptr->createBrowserIndexes(property, 0, afterProperty);
+
+    // traverse inserted subtree and connect to manager's signals
+    d_ptr->insertSubTree(property, 0);
+
+    d_ptr->m_subItems.insert(newPos, property);
+    //propertyInserted(property, 0, properAfterProperty);
+    return topLevelItem(property);
+}
+
+/*!
+    Removes the specified \a property (and its subproperties) from the
+    property browser's list of top level properties. All items
+    that were associated with the given \a property and its children
+    are deleted.
+
+    Note that the properties are \e not deleted since they can still
+    be used in other editors.
+
+    \sa clear(), QtProperty::removeSubProperty(), properties()
+*/
+void QtAbstractPropertyBrowser::removeProperty(QtProperty *property)
+{
+    if (!property)
+        return;
+
+    QList<QtProperty *> pendingList = properties();
+    int pos = 0;
+    while (pos < pendingList.count()) {
+        if (pendingList.at(pos) == property) {
+            d_ptr->m_subItems.removeAt(pos); //perhaps this two lines
+            d_ptr->removeSubTree(property, 0); //should be moved down after propertyRemoved call.
+            //propertyRemoved(property, 0);
+
+            d_ptr->removeBrowserIndexes(property, 0);
+
+            // when item is deleted, item will call removeItem for top level items,
+            // and itemRemoved for nested items.
+
+            return;
+        }
+        pos++;
+    }
+}
+
+/*!
+    Creates an editing widget (with the given \a parent) for the given
+    \a property according to the previously established associations
+    between property managers and editor factories.
+
+    If the property is created by a property manager which was not
+    associated with any of the existing factories in \e this property
+    editor, the function returns 0.
+
+    To make a property editable in the property browser, the
+    createEditor() function must be called to provide the
+    property with a suitable editing widget.
+
+    Reimplement this function to provide additional decoration for the
+    editing widgets created by the installed factories.
+
+    \sa setFactoryForManager()
+*/
+QWidget *QtAbstractPropertyBrowser::createEditor(QtProperty *property,
+                QWidget *parent)
+{
+    QtAbstractEditorFactoryBase *factory = 0;
+    QtAbstractPropertyManager *manager = property->propertyManager();
+
+    if (m_viewToManagerToFactory()->contains(this) &&
+        (*m_viewToManagerToFactory())[this].contains(manager)) {
+        factory = (*m_viewToManagerToFactory())[this][manager];
+    }
+
+    if (!factory)
+        return 0;
+    return factory->createEditor(property, parent);
+}
+
+bool QtAbstractPropertyBrowser::addFactory(QtAbstractPropertyManager *abstractManager,
+            QtAbstractEditorFactoryBase *abstractFactory)
+{
+    bool connectNeeded = false;
+    if (!m_managerToFactoryToViews()->contains(abstractManager) ||
+        !(*m_managerToFactoryToViews())[abstractManager].contains(abstractFactory)) {
+        connectNeeded = true;
+    } else if ((*m_managerToFactoryToViews())[abstractManager][abstractFactory]
+                    .contains(this)) {
+        return connectNeeded;
+    }
+
+    if (m_viewToManagerToFactory()->contains(this) &&
+        (*m_viewToManagerToFactory())[this].contains(abstractManager)) {
+        unsetFactoryForManager(abstractManager);
+    }
+
+    (*m_managerToFactoryToViews())[abstractManager][abstractFactory].append(this);
+    (*m_viewToManagerToFactory())[this][abstractManager] = abstractFactory;
+
+    return connectNeeded;
+}
+
+/*!
+    Removes the association between the given \a manager and the
+    factory bound to it, automatically calling the
+    QtAbstractEditorFactory::removePropertyManager() function if necessary.
+
+    \sa setFactoryForManager()
+*/
+void QtAbstractPropertyBrowser::unsetFactoryForManager(QtAbstractPropertyManager *manager)
+{
+    if (!m_viewToManagerToFactory()->contains(this) ||
+        !(*m_viewToManagerToFactory())[this].contains(manager)) {
+        return;
+    }
+
+    QtAbstractEditorFactoryBase *abstractFactory =
+                (*m_viewToManagerToFactory())[this][manager];
+    (*m_viewToManagerToFactory())[this].remove(manager);
+    if ((*m_viewToManagerToFactory())[this].isEmpty()) {
+        (*m_viewToManagerToFactory()).remove(this);
+    }
+
+    (*m_managerToFactoryToViews())[manager][abstractFactory].removeAll(this);
+    if ((*m_managerToFactoryToViews())[manager][abstractFactory].isEmpty()) {
+        (*m_managerToFactoryToViews())[manager].remove(abstractFactory);
+        abstractFactory->breakConnection(manager);
+        if ((*m_managerToFactoryToViews())[manager].isEmpty()) {
+            (*m_managerToFactoryToViews()).remove(manager);
+        }
+    }
+}
+
+/*!
+    Returns the current item in the property browser.
+
+    \sa setCurrentItem()
+*/
+QtBrowserItem *QtAbstractPropertyBrowser::currentItem() const
+{
+    return d_ptr->m_currentItem;
+}
+
+/*!
+    Sets the current item in the property browser to \a item.
+
+    \sa currentItem(), currentItemChanged()
+*/
+void QtAbstractPropertyBrowser::setCurrentItem(QtBrowserItem *item)
+{
+    QtBrowserItem *oldItem = d_ptr->m_currentItem;
+    d_ptr->m_currentItem = item;
+    if (oldItem != item)
+        emit  currentItemChanged(item);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qtpropertybrowser.cpp"