File indexing completed on 2024-05-12 04:35:10

0001 /****************************************************************************
0002 **
0003 ** Copyright (C) 2016 The Qt Company Ltd.
0004 ** Contact: https://www.qt.io/licensing/
0005 **
0006 ** This file is part of the tools applications of the Qt Toolkit.
0007 **
0008 ** $QT_BEGIN_LICENSE:LGPL$
0009 ** Commercial License Usage
0010 ** Licensees holding valid commercial Qt licenses may use this file in
0011 ** accordance with the commercial license agreement provided with the
0012 ** Software or, alternatively, in accordance with the terms contained in
0013 ** a written agreement between you and The Qt Company. For licensing terms
0014 ** and conditions see https://www.qt.io/terms-conditions. For further
0015 ** information use the contact form at https://www.qt.io/contact-us.
0016 **
0017 ** GNU Lesser General Public License Usage
0018 ** Alternatively, this file may be used under the terms of the GNU Lesser
0019 ** General Public License version 3 as published by the Free Software
0020 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
0021 ** packaging of this file. Please review the following information to
0022 ** ensure the GNU Lesser General Public License version 3 requirements
0023 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
0024 **
0025 ** GNU General Public License Usage
0026 ** Alternatively, this file may be used under the terms of the GNU
0027 ** General Public License version 2.0 or (at your option) the GNU General
0028 ** Public license version 3 or any later version approved by the KDE Free
0029 ** Qt Foundation. The licenses are as published by the Free Software
0030 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
0031 ** included in the packaging of this file. Please review the following
0032 ** information to ensure the GNU General Public License requirements will
0033 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
0034 ** https://www.gnu.org/licenses/gpl-3.0.html.
0035 **
0036 ** $QT_END_LICENSE$
0037 **
0038 ****************************************************************************/
0039 
0040 #include "qtpropertybrowser.h"
0041 #include <QtCore/QSet>
0042 #include <QtCore/QMap>
0043 #include <QtGui/QIcon>
0044 
0045 #if defined(Q_CC_MSVC)
0046 #    pragma warning(disable: 4786) /* MS VS 6: truncating debug info after 255 characters */
0047 #endif
0048 
0049 QT_BEGIN_NAMESPACE
0050 
0051 class QtPropertyPrivate
0052 {
0053 public:
0054     QtPropertyPrivate(QtAbstractPropertyManager *manager) : m_enabled(true), m_modified(false), m_manager(manager) {}
0055     QtProperty *q_ptr;
0056 
0057     QSet<QtProperty *> m_parentItems;
0058     QList<QtProperty *> m_subItems;
0059 
0060     QString m_valueToolTip;
0061     QString m_descriptionToolTip;
0062     QString m_statusTip;
0063     QString m_whatsThis;
0064     QString m_name;
0065     bool m_enabled;
0066     bool m_modified;
0067 
0068     QtAbstractPropertyManager * const m_manager;
0069 };
0070 
0071 class QtAbstractPropertyManagerPrivate
0072 {
0073     QtAbstractPropertyManager *q_ptr;
0074     Q_DECLARE_PUBLIC(QtAbstractPropertyManager)
0075 public:
0076     void propertyDestroyed(QtProperty *property);
0077     void propertyChanged(QtProperty *property) const;
0078     void propertyRemoved(QtProperty *property,
0079                 QtProperty *parentProperty) const;
0080     void propertyInserted(QtProperty *property, QtProperty *parentProperty,
0081                 QtProperty *afterProperty) const;
0082 
0083     QSet<QtProperty *> m_properties;
0084 };
0085 
0086 /*!
0087     \class QtProperty
0088     \internal
0089     \inmodule QtDesigner
0090     \since 4.4
0091 
0092     \brief The QtProperty class encapsulates an instance of a property.
0093 
0094     Properties are created by objects of QtAbstractPropertyManager
0095     subclasses; a manager can create properties of a given type, and
0096     is used in conjunction with the QtAbstractPropertyBrowser class. A
0097     property is always owned by the manager that created it, which can
0098     be retrieved using the propertyManager() function.
0099 
0100     QtProperty contains the most common property attributes, and
0101     provides functions for retrieving as well as setting their values:
0102 
0103     \table
0104     \header \li Getter \li Setter
0105     \row
0106     \li propertyName() \li setPropertyName()
0107     \row
0108     \li statusTip() \li setStatusTip()
0109     \row
0110     \li descriptionToolTip() \li setDescriptionToolTip()
0111     \row
0112     \li valueToolTip() \li setValueToolTip()
0113     \row
0114     \li toolTip() \deprecated in 5.6 \li setToolTip() \deprecated in 5.6
0115     \row
0116     \li whatsThis() \li setWhatsThis()
0117     \row
0118     \li isEnabled() \li setEnabled()
0119     \row
0120     \li isModified() \li setModified()
0121     \row
0122     \li valueText() \li Nop
0123     \row
0124     \li valueIcon() \li Nop
0125     \endtable
0126 
0127     It is also possible to nest properties: QtProperty provides the
0128     addSubProperty(), insertSubProperty() and removeSubProperty() functions to
0129     manipulate the set of subproperties. Use the subProperties()
0130     function to retrieve a property's current set of subproperties.
0131     Note that nested properties are not owned by the parent property,
0132     i.e. each subproperty is owned by the manager that created it.
0133 
0134     \sa QtAbstractPropertyManager, QtBrowserItem
0135 */
0136 
0137 /*!
0138     Creates a property with the given \a manager.
0139 
0140     This constructor is only useful when creating a custom QtProperty
0141     subclass (e.g. QtVariantProperty). To create a regular QtProperty
0142     object, use the QtAbstractPropertyManager::addProperty()
0143     function instead.
0144 
0145     \sa QtAbstractPropertyManager::addProperty()
0146 */
0147 QtProperty::QtProperty(QtAbstractPropertyManager *manager)
0148     : d_ptr(new QtPropertyPrivate(manager))
0149 {
0150     d_ptr->q_ptr = this;
0151 }
0152 
0153 /*!
0154     Destroys this property.
0155 
0156     Note that subproperties are detached but not destroyed, i.e. they
0157     can still be used in another context.
0158 
0159     \sa QtAbstractPropertyManager::clear()
0160 
0161 */
0162 QtProperty::~QtProperty()
0163 {
0164     for (QtProperty *property : qAsConst(d_ptr->m_parentItems))
0165         property->d_ptr->m_manager->d_ptr->propertyRemoved(this, property);
0166 
0167     d_ptr->m_manager->d_ptr->propertyDestroyed(this);
0168 
0169     for (QtProperty *property : qAsConst(d_ptr->m_subItems))
0170         property->d_ptr->m_parentItems.remove(this);
0171 
0172     for (QtProperty *property : qAsConst(d_ptr->m_parentItems))
0173         property->d_ptr->m_subItems.removeAll(this);
0174 }
0175 
0176 /*!
0177     Returns the set of subproperties.
0178 
0179     Note that subproperties are not owned by \e this property, but by
0180     the manager that created them.
0181 
0182     \sa insertSubProperty(), removeSubProperty()
0183 */
0184 QList<QtProperty *> QtProperty::subProperties() const
0185 {
0186     return d_ptr->m_subItems;
0187 }
0188 
0189 /*!
0190     Returns a pointer to the manager that owns this property.
0191 */
0192 QtAbstractPropertyManager *QtProperty::propertyManager() const
0193 {
0194     return d_ptr->m_manager;
0195 }
0196 
0197 /* Note: As of 17.7.2015 for Qt 5.6, the existing 'toolTip' of the Property
0198  * Browser solution was split into valueToolTip() and descriptionToolTip()
0199  * to be able to implement custom tool tip for QTBUG-45442. This could
0200  * be back-ported to the solution. */
0201 
0202 /*!
0203     Returns the property value's  tool tip.
0204 
0205     This is suitable for tool tips over the value (item delegate).
0206 
0207     \since 5.6
0208     \sa setValueToolTip()
0209 */
0210 QString QtProperty::valueToolTip() const
0211 {
0212     return d_ptr->m_valueToolTip;
0213 }
0214 
0215 /*!
0216     Returns the property description's  tool tip.
0217 
0218     This is suitable for tool tips over the description (label).
0219 
0220     \since 5.6
0221     \sa setDescriptionToolTip()
0222 */
0223 QString QtProperty::descriptionToolTip() const
0224 {
0225     return d_ptr->m_descriptionToolTip;
0226 }
0227 
0228 /*!
0229     Returns the property's status tip.
0230 
0231     \sa setStatusTip()
0232 */
0233 QString QtProperty::statusTip() const
0234 {
0235     return d_ptr->m_statusTip;
0236 }
0237 
0238 /*!
0239     Returns the property's "What's This" help text.
0240 
0241     \sa setWhatsThis()
0242 */
0243 QString QtProperty::whatsThis() const
0244 {
0245     return d_ptr->m_whatsThis;
0246 }
0247 
0248 /*!
0249     Returns the property's name.
0250 
0251     \sa setPropertyName()
0252 */
0253 QString QtProperty::propertyName() const
0254 {
0255     return d_ptr->m_name;
0256 }
0257 
0258 /*!
0259     Returns whether the property is enabled.
0260 
0261     \sa setEnabled()
0262 */
0263 bool QtProperty::isEnabled() const
0264 {
0265     return d_ptr->m_enabled;
0266 }
0267 
0268 /*!
0269     Returns whether the property is modified.
0270 
0271     \sa setModified()
0272 */
0273 bool QtProperty::isModified() const
0274 {
0275     return d_ptr->m_modified;
0276 }
0277 
0278 /*!
0279     Returns whether the property has a value.
0280 
0281     \sa QtAbstractPropertyManager::hasValue()
0282 */
0283 bool QtProperty::hasValue() const
0284 {
0285     return d_ptr->m_manager->hasValue(this);
0286 }
0287 
0288 /*!
0289     Returns an icon representing the current state of this property.
0290 
0291     If the given property type can not generate such an icon, this
0292     function returns an invalid icon.
0293 
0294     \sa QtAbstractPropertyManager::valueIcon()
0295 */
0296 QIcon QtProperty::valueIcon() const
0297 {
0298     return d_ptr->m_manager->valueIcon(this);
0299 }
0300 
0301 /*!
0302     Returns a string representing the current state of this property.
0303 
0304     If the given property type can not generate such a string, this
0305     function returns an empty string.
0306 
0307     \sa QtAbstractPropertyManager::valueText()
0308 */
0309 QString QtProperty::valueText() const
0310 {
0311     return d_ptr->m_manager->valueText(this);
0312 }
0313 
0314 /*!
0315     Sets the property value's tool tip to the given \a text.
0316 
0317     \since 5.6
0318     \sa valueToolTip()
0319 */
0320 void QtProperty::setValueToolTip(const QString &text)
0321 {
0322     if (d_ptr->m_valueToolTip == text)
0323         return;
0324 
0325     d_ptr->m_valueToolTip = text;
0326     propertyChanged();
0327 }
0328 
0329 /*!
0330     Sets the property description's tool tip to the given \a text.
0331 
0332     \since 5.6
0333     \sa descriptionToolTip()
0334 */
0335 void QtProperty::setDescriptionToolTip(const QString &text)
0336 {
0337     if (d_ptr->m_descriptionToolTip == text)
0338         return;
0339 
0340     d_ptr->m_descriptionToolTip = text;
0341     propertyChanged();
0342 }
0343 
0344 /*!
0345     Sets the property's status tip to the given \a text.
0346 
0347     \sa statusTip()
0348 */
0349 void QtProperty::setStatusTip(const QString &text)
0350 {
0351     if (d_ptr->m_statusTip == text)
0352         return;
0353 
0354     d_ptr->m_statusTip = text;
0355     propertyChanged();
0356 }
0357 
0358 /*!
0359     Sets the property's "What's This" help text to the given \a text.
0360 
0361     \sa whatsThis()
0362 */
0363 void QtProperty::setWhatsThis(const QString &text)
0364 {
0365     if (d_ptr->m_whatsThis == text)
0366         return;
0367 
0368     d_ptr->m_whatsThis = text;
0369     propertyChanged();
0370 }
0371 
0372 /*!
0373     \fn void QtProperty::setPropertyName(const QString &name)
0374 
0375     Sets the property's  name to the given \a name.
0376 
0377     \sa propertyName()
0378 */
0379 void QtProperty::setPropertyName(const QString &text)
0380 {
0381     if (d_ptr->m_name == text)
0382         return;
0383 
0384     d_ptr->m_name = text;
0385     propertyChanged();
0386 }
0387 
0388 /*!
0389     Enables or disables the property according to the passed \a enable value.
0390 
0391     \sa isEnabled()
0392 */
0393 void QtProperty::setEnabled(bool enable)
0394 {
0395     if (d_ptr->m_enabled == enable)
0396         return;
0397 
0398     d_ptr->m_enabled = enable;
0399     propertyChanged();
0400 }
0401 
0402 /*!
0403     Sets the property's modified state according to the passed \a modified value.
0404 
0405     \sa isModified()
0406 */
0407 void QtProperty::setModified(bool modified)
0408 {
0409     if (d_ptr->m_modified == modified)
0410         return;
0411 
0412     d_ptr->m_modified = modified;
0413     propertyChanged();
0414 }
0415 
0416 /*!
0417     Appends the given \a property to this property's subproperties.
0418 
0419     If the given \a property already is added, this function does
0420     nothing.
0421 
0422     \sa insertSubProperty(), removeSubProperty()
0423 */
0424 void QtProperty::addSubProperty(QtProperty *property)
0425 {
0426     QtProperty *after = 0;
0427     if (d_ptr->m_subItems.count() > 0)
0428         after = d_ptr->m_subItems.last();
0429     insertSubProperty(property, after);
0430 }
0431 
0432 /*!
0433     \fn void QtProperty::insertSubProperty(QtProperty *property, QtProperty *precedingProperty)
0434 
0435     Inserts the given \a property after the specified \a
0436     precedingProperty into this property's list of subproperties.  If
0437     \a precedingProperty is 0, the specified \a property is inserted
0438     at the beginning of the list.
0439 
0440     If the given \a property already is inserted, this function does
0441     nothing.
0442 
0443     \sa addSubProperty(), removeSubProperty()
0444 */
0445 void QtProperty::insertSubProperty(QtProperty *property,
0446             QtProperty *afterProperty)
0447 {
0448     if (!property)
0449         return;
0450 
0451     if (property == this)
0452         return;
0453 
0454     // traverse all children of item. if this item is a child of item then cannot add.
0455     QList<QtProperty *> pendingList = property->subProperties();
0456     QMap<QtProperty *, bool> visited;
0457     while (!pendingList.isEmpty()) {
0458         QtProperty *i = pendingList.first();
0459         if (i == this)
0460             return;
0461         pendingList.removeFirst();
0462         if (visited.contains(i))
0463             continue;
0464         visited[i] = true;
0465         pendingList += i->subProperties();
0466     }
0467 
0468     pendingList = subProperties();
0469     int pos = 0;
0470     int newPos = 0;
0471     QtProperty *properAfterProperty = 0;
0472     while (pos < pendingList.count()) {
0473         QtProperty *i = pendingList.at(pos);
0474         if (i == property)
0475             return; // if item is already inserted in this item then cannot add.
0476         if (i == afterProperty) {
0477             newPos = pos + 1;
0478             properAfterProperty = afterProperty;
0479         }
0480         pos++;
0481     }
0482 
0483     d_ptr->m_subItems.insert(newPos, property);
0484     property->d_ptr->m_parentItems.insert(this);
0485 
0486     d_ptr->m_manager->d_ptr->propertyInserted(property, this, properAfterProperty);
0487 }
0488 
0489 /*!
0490     Removes the given \a property from the list of subproperties
0491     without deleting it.
0492 
0493     \sa addSubProperty(), insertSubProperty()
0494 */
0495 void QtProperty::removeSubProperty(QtProperty *property)
0496 {
0497     if (!property)
0498         return;
0499 
0500     d_ptr->m_manager->d_ptr->propertyRemoved(property, this);
0501 
0502     QList<QtProperty *> pendingList = subProperties();
0503     int pos = 0;
0504     while (pos < pendingList.count()) {
0505         if (pendingList.at(pos) == property) {
0506             d_ptr->m_subItems.removeAt(pos);
0507             property->d_ptr->m_parentItems.remove(this);
0508 
0509             return;
0510         }
0511         pos++;
0512     }
0513 }
0514 
0515 /*!
0516     \internal
0517 */
0518 void QtProperty::propertyChanged()
0519 {
0520     d_ptr->m_manager->d_ptr->propertyChanged(this);
0521 }
0522 
0523 ////////////////////////////////
0524 
0525 void QtAbstractPropertyManagerPrivate::propertyDestroyed(QtProperty *property)
0526 {
0527     if (m_properties.contains(property)) {
0528         Q_EMIT q_ptr->propertyDestroyed(property);
0529         q_ptr->uninitializeProperty(property);
0530         m_properties.remove(property);
0531     }
0532 }
0533 
0534 void QtAbstractPropertyManagerPrivate::propertyChanged(QtProperty *property) const
0535 {
0536     Q_EMIT q_ptr->propertyChanged(property);
0537 }
0538 
0539 void QtAbstractPropertyManagerPrivate::propertyRemoved(QtProperty *property,
0540             QtProperty *parentProperty) const
0541 {
0542     Q_EMIT q_ptr->propertyRemoved(property, parentProperty);
0543 }
0544 
0545 void QtAbstractPropertyManagerPrivate::propertyInserted(QtProperty *property,
0546             QtProperty *parentProperty, QtProperty *afterProperty) const
0547 {
0548     Q_EMIT q_ptr->propertyInserted(property, parentProperty, afterProperty);
0549 }
0550 
0551 /*!
0552     \class QtAbstractPropertyManager
0553     \internal
0554     \inmodule QtDesigner
0555     \since 4.4
0556 
0557     \brief The QtAbstractPropertyManager provides an interface for
0558     property managers.
0559 
0560     A manager can create and manage properties of a given type, and is
0561     used in conjunction with the QtAbstractPropertyBrowser class.
0562 
0563     When using a property browser widget, the properties are created
0564     and managed by implementations of the QtAbstractPropertyManager
0565     class. To ensure that the properties' values will be displayed
0566     using suitable editing widgets, the managers are associated with
0567     objects of QtAbstractEditorFactory subclasses. The property browser
0568     will use these associations to determine which factories it should
0569     use to create the preferred editing widgets.
0570 
0571     The QtAbstractPropertyManager class provides common functionality
0572     like creating a property using the addProperty() function, and
0573     retrieving the properties created by the manager using the
0574     properties() function. The class also provides signals that are
0575     emitted when the manager's properties change: propertyInserted(),
0576     propertyRemoved(), propertyChanged() and propertyDestroyed().
0577 
0578     QtAbstractPropertyManager subclasses are supposed to provide their
0579     own type specific API. Note that several ready-made
0580     implementations are available:
0581 
0582     \list
0583     \li QtBoolPropertyManager
0584     \li QtColorPropertyManager
0585     \li QtDatePropertyManager
0586     \li QtDateTimePropertyManager
0587     \li QtDoublePropertyManager
0588     \li QtEnumPropertyManager
0589     \li QtFlagPropertyManager
0590     \li QtFontPropertyManager
0591     \li QtGroupPropertyManager
0592     \li QtIntPropertyManager
0593     \li QtPointPropertyManager
0594     \li QtRectPropertyManager
0595     \li QtSizePropertyManager
0596     \li QtSizePolicyPropertyManager
0597     \li QtStringPropertyManager
0598     \li QtTimePropertyManager
0599     \li QtVariantPropertyManager
0600     \endlist
0601 
0602     \sa QtAbstractEditorFactoryBase, QtAbstractPropertyBrowser, QtProperty
0603 */
0604 
0605 /*!
0606     \fn void QtAbstractPropertyManager::propertyInserted(QtProperty *newProperty,
0607                 QtProperty *parentProperty, QtProperty *precedingProperty)
0608 
0609     This signal is emitted when a new subproperty is inserted into an
0610     existing property, passing pointers to the \a newProperty, \a
0611     parentProperty and \a precedingProperty as parameters.
0612 
0613     If \a precedingProperty is 0, the \a newProperty was inserted at
0614     the beginning of the \a parentProperty's subproperties list.
0615 
0616     Note that signal is emitted only if the \a parentProperty is created
0617     by this manager.
0618 
0619     \sa QtAbstractPropertyBrowser::itemInserted()
0620 */
0621 
0622 /*!
0623     \fn void QtAbstractPropertyManager::propertyChanged(QtProperty *property)
0624 
0625     This signal is emitted whenever a property's data changes, passing
0626     a pointer to the \a property as parameter.
0627 
0628     Note that signal is only emitted for properties that are created by
0629     this manager.
0630 
0631     \sa QtAbstractPropertyBrowser::itemChanged()
0632 */
0633 
0634 /*!
0635     \fn void QtAbstractPropertyManager::propertyRemoved(QtProperty *property, QtProperty *parent)
0636 
0637     This signal is emitted when a subproperty is removed, passing
0638     pointers to the removed \a property and the \a parent property as
0639     parameters.
0640 
0641     Note that signal is emitted only when the \a parent property is
0642     created by this manager.
0643 
0644     \sa QtAbstractPropertyBrowser::itemRemoved()
0645 */
0646 
0647 /*!
0648     \fn void QtAbstractPropertyManager::propertyDestroyed(QtProperty *property)
0649 
0650     This signal is emitted when the specified \a property is about to
0651     be destroyed.
0652 
0653     Note that signal is only emitted for properties that are created
0654     by this manager.
0655 
0656     \sa clear(), uninitializeProperty()
0657 */
0658 
0659 /*!
0660     \fn void QtAbstractPropertyBrowser::currentItemChanged(QtBrowserItem *current)
0661 
0662     This signal is emitted when the current item changes. The current item is specified by \a current.
0663 
0664     \sa QtAbstractPropertyBrowser::setCurrentItem()
0665 */
0666 
0667 /*!
0668     Creates an abstract property manager with the given \a parent.
0669 */
0670 QtAbstractPropertyManager::QtAbstractPropertyManager(QObject *parent)
0671     : QObject(parent), d_ptr(new QtAbstractPropertyManagerPrivate)
0672 {
0673     d_ptr->q_ptr = this;
0674 
0675 }
0676 
0677 /*!
0678     Destroys the manager. All properties created by the manager are
0679     destroyed.
0680 */
0681 QtAbstractPropertyManager::~QtAbstractPropertyManager()
0682 {
0683     clear();
0684 }
0685 
0686 /*!
0687     Destroys all the properties that this manager has created.
0688 
0689     \sa propertyDestroyed(), uninitializeProperty()
0690 */
0691 void QtAbstractPropertyManager::clear() const
0692 {
0693     while (!d_ptr->m_properties.isEmpty())
0694         delete *d_ptr->m_properties.cbegin();
0695 }
0696 
0697 /*!
0698     Returns the set of properties created by this manager.
0699 
0700     \sa addProperty()
0701 */
0702 QSet<QtProperty *> QtAbstractPropertyManager::properties() const
0703 {
0704     return d_ptr->m_properties;
0705 }
0706 
0707 /*!
0708     Returns whether the given \a property has a value.
0709 
0710     The default implementation of this function returns true.
0711 
0712     \sa QtProperty::hasValue()
0713 */
0714 bool QtAbstractPropertyManager::hasValue(const QtProperty *property) const
0715 {
0716     Q_UNUSED(property)
0717     return true;
0718 }
0719 
0720 /*!
0721     Returns an icon representing the current state of the given \a
0722     property.
0723 
0724     The default implementation of this function returns an invalid
0725     icon.
0726 
0727     \sa QtProperty::valueIcon()
0728 */
0729 QIcon QtAbstractPropertyManager::valueIcon(const QtProperty *property) const
0730 {
0731     Q_UNUSED(property)
0732     return QIcon();
0733 }
0734 
0735 /*!
0736     Returns a string representing the current state of the given \a
0737     property.
0738 
0739     The default implementation of this function returns an empty
0740     string.
0741 
0742     \sa QtProperty::valueText()
0743 */
0744 QString QtAbstractPropertyManager::valueText(const QtProperty *property) const
0745 {
0746     Q_UNUSED(property)
0747     return QString();
0748 }
0749 
0750 /*!
0751     Creates a property with the given \a name which then is owned by this manager.
0752 
0753     Internally, this function calls the createProperty() and
0754     initializeProperty() functions.
0755 
0756     \sa initializeProperty(), properties()
0757 */
0758 QtProperty *QtAbstractPropertyManager::addProperty(const QString &name)
0759 {
0760     QtProperty *property = createProperty();
0761     if (property) {
0762         property->setPropertyName(name);
0763         d_ptr->m_properties.insert(property);
0764         initializeProperty(property);
0765     }
0766     return property;
0767 }
0768 
0769 /*!
0770     Creates a property.
0771 
0772     The base implementation produce QtProperty instances; Reimplement
0773     this function to make this manager produce objects of a QtProperty
0774     subclass.
0775 
0776     \sa addProperty(), initializeProperty()
0777 */
0778 QtProperty *QtAbstractPropertyManager::createProperty()
0779 {
0780     return new QtProperty(this);
0781 }
0782 
0783 /*!
0784     \fn void QtAbstractPropertyManager::initializeProperty(QtProperty *property) = 0
0785 
0786     This function is called whenever a new valid property pointer has
0787     been created, passing the pointer as parameter.
0788 
0789     The purpose is to let the manager know that the \a property has
0790     been created so that it can provide additional attributes for the
0791     new property, e.g. QtIntPropertyManager adds \l
0792     {QtIntPropertyManager::value()}{value}, \l
0793     {QtIntPropertyManager::minimum()}{minimum} and \l
0794     {QtIntPropertyManager::maximum()}{maximum} attributes. Since each manager
0795     subclass adds type specific attributes, this function is pure
0796     virtual and must be reimplemented when deriving from the
0797     QtAbstractPropertyManager class.
0798 
0799     \sa addProperty(), createProperty()
0800 */
0801 
0802 /*!
0803     This function is called just before the specified \a property is destroyed.
0804 
0805     The purpose is to let the property manager know that the \a
0806     property is being destroyed so that it can remove the property's
0807     additional attributes.
0808 
0809     \sa clear(), propertyDestroyed()
0810 */
0811 void QtAbstractPropertyManager::uninitializeProperty(QtProperty *property)
0812 {
0813     Q_UNUSED(property)
0814 }
0815 
0816 ////////////////////////////////////
0817 
0818 /*!
0819     \class QtAbstractEditorFactoryBase
0820     \internal
0821     \inmodule QtDesigner
0822     \since 4.4
0823 
0824     \brief The QtAbstractEditorFactoryBase provides an interface for
0825     editor factories.
0826 
0827     An editor factory is a class that is able to create an editing
0828     widget of a specified type (e.g. line edits or comboboxes) for a
0829     given QtProperty object, and it is used in conjunction with the
0830     QtAbstractPropertyManager and QtAbstractPropertyBrowser classes.
0831 
0832     When using a property browser widget, the properties are created
0833     and managed by implementations of the QtAbstractPropertyManager
0834     class. To ensure that the properties' values will be displayed
0835     using suitable editing widgets, the managers are associated with
0836     objects of QtAbstractEditorFactory subclasses. The property browser
0837     will use these associations to determine which factories it should
0838     use to create the preferred editing widgets.
0839 
0840     Typically, an editor factory is created by subclassing the
0841     QtAbstractEditorFactory template class which inherits
0842     QtAbstractEditorFactoryBase. But note that several ready-made
0843     implementations are available:
0844 
0845     \list
0846     \li QtCheckBoxFactory
0847     \li QtDateEditFactory
0848     \li QtDateTimeEditFactory
0849     \li QtDoubleSpinBoxFactory
0850     \li QtEnumEditorFactory
0851     \li QtLineEditFactory
0852     \li QtScrollBarFactory
0853     \li QtSliderFactory
0854     \li QtSpinBoxFactory
0855     \li QtTimeEditFactory
0856     \li QtVariantEditorFactory
0857     \endlist
0858 
0859     \sa QtAbstractPropertyManager, QtAbstractPropertyBrowser
0860 */
0861 
0862 /*!
0863     \fn virtual QWidget *QtAbstractEditorFactoryBase::createEditor(QtProperty *property,
0864         QWidget *parent) = 0
0865 
0866     Creates an editing widget (with the given \a parent) for the given
0867     \a property.
0868 
0869     This function is reimplemented in QtAbstractEditorFactory template class
0870     which also provides a pure virtual convenience overload of this
0871     function enabling access to the property's manager.
0872 
0873     \sa QtAbstractEditorFactory::createEditor()
0874 */
0875 
0876 /*!
0877     \fn QtAbstractEditorFactoryBase::QtAbstractEditorFactoryBase(QObject *parent = 0)
0878 
0879     Creates an abstract editor factory with the given \a parent.
0880 */
0881 
0882 /*!
0883     \fn virtual void QtAbstractEditorFactoryBase::breakConnection(QtAbstractPropertyManager *manager) = 0
0884 
0885     \internal
0886 
0887     Detaches property manager from factory.
0888     This method is reimplemented in QtAbstractEditorFactory template subclass.
0889     You don't need to reimplement it in your subclasses. Instead implement more convenient
0890     QtAbstractEditorFactory::disconnectPropertyManager() which gives you access to particular manager subclass.
0891 */
0892 
0893 /*!
0894     \fn virtual void QtAbstractEditorFactoryBase::managerDestroyed(QObject *manager) = 0
0895 
0896     \internal
0897 
0898     This method is called when property manager is being destroyed.
0899     Basically it notifies factory not to produce editors for properties owned by \a manager.
0900     You don't need to reimplement it in your subclass. This method is implemented in
0901     QtAbstractEditorFactory template subclass.
0902 */
0903 
0904 /*!
0905     \class QtAbstractEditorFactory
0906     \internal
0907     \inmodule QtDesigner
0908     \since 4.4
0909 
0910     \brief The QtAbstractEditorFactory is the base template class for editor
0911     factories.
0912 
0913     An editor factory is a class that is able to create an editing
0914     widget of a specified type (e.g. line edits or comboboxes) for a
0915     given QtProperty object, and it is used in conjunction with the
0916     QtAbstractPropertyManager and QtAbstractPropertyBrowser classes.
0917 
0918     Note that the QtAbstractEditorFactory functions are using the
0919     PropertyManager template argument class which can be any
0920     QtAbstractPropertyManager subclass. For example:
0921 
0922     \snippet doc/src/snippets/code/tools_shared_qtpropertybrowser_qtpropertybrowser.cpp 0
0923 
0924     Note that QtSpinBoxFactory by definition creates editing widgets
0925     \e only for properties created by QtIntPropertyManager.
0926 
0927     When using a property browser widget, the properties are created
0928     and managed by implementations of the QtAbstractPropertyManager
0929     class. To ensure that the properties' values will be displayed
0930     using suitable editing widgets, the managers are associated with
0931     objects of QtAbstractEditorFactory subclasses. The property browser will
0932     use these associations to determine which factories it should use
0933     to create the preferred editing widgets.
0934 
0935     A QtAbstractEditorFactory object is capable of producing editors for
0936     several property managers at the same time. To create an
0937     association between this factory and a given manager, use the
0938     addPropertyManager() function. Use the removePropertyManager() function to make
0939     this factory stop producing editors for a given property
0940     manager. Use the propertyManagers() function to retrieve the set of
0941     managers currently associated with this factory.
0942 
0943     Several ready-made implementations of the QtAbstractEditorFactory class
0944     are available:
0945 
0946     \list
0947     \li QtCheckBoxFactory
0948     \li QtDateEditFactory
0949     \li QtDateTimeEditFactory
0950     \li QtDoubleSpinBoxFactory
0951     \li QtEnumEditorFactory
0952     \li QtLineEditFactory
0953     \li QtScrollBarFactory
0954     \li QtSliderFactory
0955     \li QtSpinBoxFactory
0956     \li QtTimeEditFactory
0957     \li QtVariantEditorFactory
0958     \endlist
0959 
0960     When deriving from the QtAbstractEditorFactory class, several pure virtual
0961     functions must be implemented: the connectPropertyManager() function is
0962     used by the factory to connect to the given manager's signals, the
0963     createEditor() function is supposed to create an editor for the
0964     given property controlled by the given manager, and finally the
0965     disconnectPropertyManager() function is used by the factory to disconnect
0966     from the specified manager's signals.
0967 
0968     \sa QtAbstractEditorFactoryBase, QtAbstractPropertyManager
0969 */
0970 
0971 /*!
0972     \fn QtAbstractEditorFactory::QtAbstractEditorFactory(QObject *parent = 0)
0973 
0974     Creates an editor factory with the given \a parent.
0975 
0976     \sa addPropertyManager()
0977 */
0978 
0979 /*!
0980     \fn QWidget *QtAbstractEditorFactory::createEditor(QtProperty *property, QWidget *parent)
0981 
0982     Creates an editing widget (with the given \a parent) for the given
0983     \a property.
0984 */
0985 
0986 /*!
0987     \fn void QtAbstractEditorFactory::addPropertyManager(PropertyManager *manager)
0988 
0989     Adds the given \a manager to this factory's set of managers,
0990     making this factory produce editing widgets for properties created
0991     by the given manager.
0992 
0993     The PropertyManager type is a template argument class, and represents the chosen
0994     QtAbstractPropertyManager subclass.
0995 
0996     \sa propertyManagers(), removePropertyManager()
0997 */
0998 
0999 /*!
1000     \fn void QtAbstractEditorFactory::removePropertyManager(PropertyManager *manager)
1001 
1002     Removes the given \a manager from this factory's set of
1003     managers. The PropertyManager type is a template argument class, and may be
1004     any QtAbstractPropertyManager subclass.
1005 
1006     \sa propertyManagers(), addPropertyManager()
1007 */
1008 
1009 /*!
1010     \fn virtual void QtAbstractEditorFactory::connectPropertyManager(PropertyManager *manager) = 0
1011 
1012     Connects this factory to the given \a manager's signals.  The
1013     PropertyManager type is a template argument class, and represents
1014     the chosen QtAbstractPropertyManager subclass.
1015 
1016     This function is used internally by the addPropertyManager() function, and
1017     makes it possible to update an editing widget when the associated
1018     property's data changes. This is typically done in custom slots
1019     responding to the signals emitted by the property's manager,
1020     e.g. QtIntPropertyManager::valueChanged() and
1021     QtIntPropertyManager::rangeChanged().
1022 
1023     \sa propertyManagers(), disconnectPropertyManager()
1024 */
1025 
1026 /*!
1027     \fn virtual QWidget *QtAbstractEditorFactory::createEditor(PropertyManager *manager, QtProperty *property,
1028                 QWidget *parent) = 0
1029 
1030     Creates an editing widget with the given \a parent for the
1031     specified \a property created by the given \a manager. The
1032     PropertyManager type is a template argument class, and represents
1033     the chosen QtAbstractPropertyManager subclass.
1034 
1035     This function must be implemented in derived classes: It is
1036     recommended to store a pointer to the widget and map it to the
1037     given \a property, since the widget must be updated whenever the
1038     associated property's data changes. This is typically done in
1039     custom slots responding to the signals emitted by the property's
1040     manager, e.g. QtIntPropertyManager::valueChanged() and
1041     QtIntPropertyManager::rangeChanged().
1042 
1043     \sa connectPropertyManager()
1044 */
1045 
1046 /*!
1047     \fn virtual void QtAbstractEditorFactory::disconnectPropertyManager(PropertyManager *manager) = 0
1048 
1049     Disconnects this factory from the given \a manager's signals. The
1050     PropertyManager type is a template argument class, and represents
1051     the chosen QtAbstractPropertyManager subclass.
1052 
1053     This function is used internally by the removePropertyManager() function.
1054 
1055     \sa propertyManagers(), connectPropertyManager()
1056 */
1057 
1058 /*!
1059     \fn QSet<PropertyManager *> QtAbstractEditorFactory::propertyManagers() const
1060 
1061     Returns the factory's set of associated managers.  The
1062     PropertyManager type is a template argument class, and represents
1063     the chosen QtAbstractPropertyManager subclass.
1064 
1065     \sa addPropertyManager(), removePropertyManager()
1066 */
1067 
1068 /*!
1069     \fn PropertyManager *QtAbstractEditorFactory::propertyManager(QtProperty *property) const
1070 
1071     Returns the property manager for the given \a property, or 0 if
1072     the given \a property doesn't belong to any of this factory's
1073     registered managers.
1074 
1075     The PropertyManager type is a template argument class, and represents the chosen
1076     QtAbstractPropertyManager subclass.
1077 
1078     \sa propertyManagers()
1079 */
1080 
1081 /*!
1082     \fn virtual void QtAbstractEditorFactory::managerDestroyed(QObject *manager)
1083 
1084     \internal
1085 */
1086 
1087 ////////////////////////////////////
1088 class QtBrowserItemPrivate
1089 {
1090 public:
1091     QtBrowserItemPrivate(QtAbstractPropertyBrowser *browser, QtProperty *property, QtBrowserItem *parent)
1092         : m_browser(browser), m_property(property), m_parent(parent), q_ptr(0) {}
1093 
1094     void addChild(QtBrowserItem *index, QtBrowserItem *after);
1095     void removeChild(QtBrowserItem *index);
1096 
1097     QtAbstractPropertyBrowser * const m_browser;
1098     QtProperty *m_property;
1099     QtBrowserItem *m_parent;
1100 
1101     QtBrowserItem *q_ptr;
1102 
1103     QList<QtBrowserItem *> m_children;
1104 
1105 };
1106 
1107 void QtBrowserItemPrivate::addChild(QtBrowserItem *index, QtBrowserItem *after)
1108 {
1109     if (m_children.contains(index))
1110         return;
1111     int idx = m_children.indexOf(after) + 1; // we insert after returned idx, if it was -1 then we set idx to 0;
1112     m_children.insert(idx, index);
1113 }
1114 
1115 void QtBrowserItemPrivate::removeChild(QtBrowserItem *index)
1116 {
1117     m_children.removeAll(index);
1118 }
1119 
1120 
1121 /*!
1122     \class QtBrowserItem
1123     \internal
1124     \inmodule QtDesigner
1125     \since 4.4
1126 
1127     \brief The QtBrowserItem class represents a property in
1128     a property browser instance.
1129 
1130     Browser items are created whenever a QtProperty is inserted to the
1131     property browser. A QtBrowserItem uniquely identifies a
1132     browser's item. Thus, if the same QtProperty is inserted multiple
1133     times, each occurrence gets its own unique QtBrowserItem. The
1134     items are owned by QtAbstractPropertyBrowser and automatically
1135     deleted when they are removed from the browser.
1136 
1137     You can traverse a browser's properties by calling parent() and
1138     children(). The property and the browser associated with an item
1139     are available as property() and browser().
1140 
1141     \sa QtAbstractPropertyBrowser, QtProperty
1142 */
1143 
1144 /*!
1145     Returns the property which is accosiated with this item. Note that
1146     several items can be associated with the same property instance in
1147     the same property browser.
1148 
1149     \sa QtAbstractPropertyBrowser::items()
1150 */
1151 
1152 QtProperty *QtBrowserItem::property() const
1153 {
1154     return d_ptr->m_property;
1155 }
1156 
1157 /*!
1158     Returns the parent item of \e this item. Returns 0 if \e this item
1159     is associated with top-level property in item's property browser.
1160 
1161     \sa children()
1162 */
1163 
1164 QtBrowserItem *QtBrowserItem::parent() const
1165 {
1166     return d_ptr->m_parent;
1167 }
1168 
1169 /*!
1170     Returns the children items of \e this item. The properties
1171     reproduced from children items are always the same as
1172     reproduced from associated property' children, for example:
1173 
1174     \snippet doc/src/snippets/code/tools_shared_qtpropertybrowser_qtpropertybrowser.cpp 1
1175 
1176     The \e childrenItems list represents the same list as \e childrenProperties.
1177 */
1178 
1179 QList<QtBrowserItem *> QtBrowserItem::children() const
1180 {
1181     return d_ptr->m_children;
1182 }
1183 
1184 /*!
1185     Returns the property browser which owns \e this item.
1186 */
1187 
1188 QtAbstractPropertyBrowser *QtBrowserItem::browser() const
1189 {
1190     return d_ptr->m_browser;
1191 }
1192 
1193 QtBrowserItem::QtBrowserItem(QtAbstractPropertyBrowser *browser, QtProperty *property, QtBrowserItem *parent)
1194     : d_ptr(new QtBrowserItemPrivate(browser, property, parent))
1195 {
1196     d_ptr->q_ptr = this;
1197 }
1198 
1199 QtBrowserItem::~QtBrowserItem()
1200 {
1201 }
1202 
1203 
1204 ////////////////////////////////////
1205 
1206 typedef QMap<QtAbstractPropertyBrowser *, QMap<QtAbstractPropertyManager *,
1207                             QtAbstractEditorFactoryBase *> > Map1;
1208 typedef QMap<QtAbstractPropertyManager *, QMap<QtAbstractEditorFactoryBase *,
1209                             QList<QtAbstractPropertyBrowser *> > > Map2;
1210 Q_GLOBAL_STATIC(Map1, m_viewToManagerToFactory)
1211 Q_GLOBAL_STATIC(Map2, m_managerToFactoryToViews)
1212 
1213 class QtAbstractPropertyBrowserPrivate
1214 {
1215     QtAbstractPropertyBrowser *q_ptr;
1216     Q_DECLARE_PUBLIC(QtAbstractPropertyBrowser)
1217 public:
1218     QtAbstractPropertyBrowserPrivate();
1219 
1220     void insertSubTree(QtProperty *property,
1221             QtProperty *parentProperty);
1222     void removeSubTree(QtProperty *property,
1223             QtProperty *parentProperty);
1224     void createBrowserIndexes(QtProperty *property, QtProperty *parentProperty, QtProperty *afterProperty);
1225     void removeBrowserIndexes(QtProperty *property, QtProperty *parentProperty);
1226     QtBrowserItem *createBrowserIndex(QtProperty *property, QtBrowserItem *parentIndex, QtBrowserItem *afterIndex);
1227     void removeBrowserIndex(QtBrowserItem *index);
1228     void clearIndex(QtBrowserItem *index);
1229 
1230     void slotPropertyInserted(QtProperty *property,
1231             QtProperty *parentProperty, QtProperty *afterProperty);
1232     void slotPropertyRemoved(QtProperty *property, QtProperty *parentProperty);
1233     void slotPropertyDestroyed(QtProperty *property);
1234     void slotPropertyDataChanged(QtProperty *property);
1235 
1236     QList<QtProperty *> m_subItems;
1237     QMap<QtAbstractPropertyManager *, QList<QtProperty *> > m_managerToProperties;
1238     QMap<QtProperty *, QList<QtProperty *> > m_propertyToParents;
1239 
1240     QMap<QtProperty *, QtBrowserItem *> m_topLevelPropertyToIndex;
1241     QList<QtBrowserItem *> m_topLevelIndexes;
1242     QMap<QtProperty *, QList<QtBrowserItem *> > m_propertyToIndexes;
1243 
1244     QtBrowserItem *m_currentItem;
1245 };
1246 
1247 QtAbstractPropertyBrowserPrivate::QtAbstractPropertyBrowserPrivate() :
1248    m_currentItem(0)
1249 {
1250 }
1251 
1252 void QtAbstractPropertyBrowserPrivate::insertSubTree(QtProperty *property,
1253             QtProperty *parentProperty)
1254 {
1255     if (m_propertyToParents.contains(property)) {
1256         // property was already inserted, so its manager is connected
1257         // and all its children are inserted and theirs managers are connected
1258         // we just register new parent (parent has to be new).
1259         m_propertyToParents[property].append(parentProperty);
1260         // don't need to update m_managerToProperties map since
1261         // m_managerToProperties[manager] already contains property.
1262         return;
1263     }
1264     QtAbstractPropertyManager *manager = property->propertyManager();
1265     if (m_managerToProperties[manager].isEmpty()) {
1266         // connect manager's signals
1267         q_ptr->connect(manager, SIGNAL(propertyInserted(QtProperty *,
1268                             QtProperty *, QtProperty *)),
1269                 q_ptr, SLOT(slotPropertyInserted(QtProperty *,
1270                             QtProperty *, QtProperty *)));
1271         q_ptr->connect(manager, SIGNAL(propertyRemoved(QtProperty *,
1272                             QtProperty *)),
1273                 q_ptr, SLOT(slotPropertyRemoved(QtProperty*,QtProperty*)));
1274         q_ptr->connect(manager, SIGNAL(propertyDestroyed(QtProperty*)),
1275                 q_ptr, SLOT(slotPropertyDestroyed(QtProperty*)));
1276         q_ptr->connect(manager, SIGNAL(propertyChanged(QtProperty*)),
1277                 q_ptr, SLOT(slotPropertyDataChanged(QtProperty*)));
1278     }
1279     m_managerToProperties[manager].append(property);
1280     m_propertyToParents[property].append(parentProperty);
1281 
1282     const QList<QtProperty *> subList = property->subProperties();
1283     for (QtProperty *subProperty : subList)
1284         insertSubTree(subProperty, property);
1285 }
1286 
1287 void QtAbstractPropertyBrowserPrivate::removeSubTree(QtProperty *property,
1288             QtProperty *parentProperty)
1289 {
1290     if (!m_propertyToParents.contains(property)) {
1291         // ASSERT
1292         return;
1293     }
1294 
1295     m_propertyToParents[property].removeAll(parentProperty);
1296     if (!m_propertyToParents[property].isEmpty())
1297         return;
1298 
1299     m_propertyToParents.remove(property);
1300     QtAbstractPropertyManager *manager = property->propertyManager();
1301     m_managerToProperties[manager].removeAll(property);
1302     if (m_managerToProperties[manager].isEmpty()) {
1303         // disconnect manager's signals
1304         q_ptr->disconnect(manager, SIGNAL(propertyInserted(QtProperty *,
1305                             QtProperty *, QtProperty *)),
1306                 q_ptr, SLOT(slotPropertyInserted(QtProperty *,
1307                             QtProperty *, QtProperty *)));
1308         q_ptr->disconnect(manager, SIGNAL(propertyRemoved(QtProperty *,
1309                             QtProperty *)),
1310                 q_ptr, SLOT(slotPropertyRemoved(QtProperty*,QtProperty*)));
1311         q_ptr->disconnect(manager, SIGNAL(propertyDestroyed(QtProperty*)),
1312                 q_ptr, SLOT(slotPropertyDestroyed(QtProperty*)));
1313         q_ptr->disconnect(manager, SIGNAL(propertyChanged(QtProperty*)),
1314                 q_ptr, SLOT(slotPropertyDataChanged(QtProperty*)));
1315 
1316         m_managerToProperties.remove(manager);
1317     }
1318 
1319     const QList<QtProperty *> subList = property->subProperties();
1320     for (QtProperty *subProperty : subList)
1321         removeSubTree(subProperty, property);
1322 }
1323 
1324 void QtAbstractPropertyBrowserPrivate::createBrowserIndexes(QtProperty *property, QtProperty *parentProperty, QtProperty *afterProperty)
1325 {
1326     QMap<QtBrowserItem *, QtBrowserItem *> parentToAfter;
1327     if (afterProperty) {
1328         QMap<QtProperty *, QList<QtBrowserItem *> >::ConstIterator it =
1329             m_propertyToIndexes.constFind(afterProperty);
1330         if (it == m_propertyToIndexes.constEnd())
1331             return;
1332 
1333         for (QtBrowserItem *idx : it.value()) {
1334             QtBrowserItem *parentIdx = idx->parent();
1335             if ((parentProperty && parentIdx && parentIdx->property() == parentProperty) || (!parentProperty && !parentIdx))
1336                 parentToAfter[idx->parent()] = idx;
1337         }
1338     } else if (parentProperty) {
1339         QMap<QtProperty *, QList<QtBrowserItem *> >::ConstIterator it =
1340                 m_propertyToIndexes.find(parentProperty);
1341         if (it == m_propertyToIndexes.constEnd())
1342             return;
1343 
1344         for (QtBrowserItem *idx : it.value())
1345             parentToAfter[idx] = 0;
1346     } else {
1347         parentToAfter[0] = 0;
1348     }
1349 
1350     const QMap<QtBrowserItem *, QtBrowserItem *>::ConstIterator pcend = parentToAfter.constEnd();
1351     for (QMap<QtBrowserItem *, QtBrowserItem *>::ConstIterator it = parentToAfter.constBegin(); it != pcend; ++it)
1352         createBrowserIndex(property, it.key(), it.value());
1353 }
1354 
1355 QtBrowserItem *QtAbstractPropertyBrowserPrivate::createBrowserIndex(QtProperty *property,
1356         QtBrowserItem *parentIndex, QtBrowserItem *afterIndex)
1357 {
1358     QtBrowserItem *newIndex = new QtBrowserItem(q_ptr, property, parentIndex);
1359     if (parentIndex) {
1360         parentIndex->d_ptr->addChild(newIndex, afterIndex);
1361     } else {
1362         m_topLevelPropertyToIndex[property] = newIndex;
1363         m_topLevelIndexes.insert(m_topLevelIndexes.indexOf(afterIndex) + 1, newIndex);
1364     }
1365     m_propertyToIndexes[property].append(newIndex);
1366 
1367     q_ptr->itemInserted(newIndex, afterIndex);
1368 
1369     const QList<QtProperty *> subItems = property->subProperties();
1370     QtBrowserItem *afterChild = 0;
1371     for (QtProperty *child : subItems)
1372         afterChild = createBrowserIndex(child, newIndex, afterChild);
1373     return newIndex;
1374 }
1375 
1376 void QtAbstractPropertyBrowserPrivate::removeBrowserIndexes(QtProperty *property, QtProperty *parentProperty)
1377 {
1378     QList<QtBrowserItem *> toRemove;
1379     QMap<QtProperty *, QList<QtBrowserItem *> >::ConstIterator it =
1380         m_propertyToIndexes.constFind(property);
1381     if (it == m_propertyToIndexes.constEnd())
1382         return;
1383 
1384     for (QtBrowserItem *idx : it.value()) {
1385         QtBrowserItem *parentIdx = idx->parent();
1386         if ((parentProperty && parentIdx && parentIdx->property() == parentProperty) || (!parentProperty && !parentIdx))
1387             toRemove.append(idx);
1388     }
1389 
1390     for (QtBrowserItem *index : qAsConst(toRemove))
1391         removeBrowserIndex(index);
1392 }
1393 
1394 void QtAbstractPropertyBrowserPrivate::removeBrowserIndex(QtBrowserItem *index)
1395 {
1396     QList<QtBrowserItem *> children = index->children();
1397     for (int i = children.count(); i > 0; i--) {
1398         removeBrowserIndex(children.at(i - 1));
1399     }
1400 
1401     q_ptr->itemRemoved(index);
1402 
1403     if (index->parent()) {
1404         index->parent()->d_ptr->removeChild(index);
1405     } else {
1406         m_topLevelPropertyToIndex.remove(index->property());
1407         m_topLevelIndexes.removeAll(index);
1408     }
1409 
1410     QtProperty *property = index->property();
1411 
1412     m_propertyToIndexes[property].removeAll(index);
1413     if (m_propertyToIndexes[property].isEmpty())
1414         m_propertyToIndexes.remove(property);
1415 
1416     delete index;
1417 }
1418 
1419 void QtAbstractPropertyBrowserPrivate::clearIndex(QtBrowserItem *index)
1420 {
1421     const QList<QtBrowserItem *> children = index->children();
1422     for (QtBrowserItem *item : children)
1423         clearIndex(item);
1424     delete index;
1425 }
1426 
1427 void QtAbstractPropertyBrowserPrivate::slotPropertyInserted(QtProperty *property,
1428         QtProperty *parentProperty, QtProperty *afterProperty)
1429 {
1430     if (!m_propertyToParents.contains(parentProperty))
1431         return;
1432     createBrowserIndexes(property, parentProperty, afterProperty);
1433     insertSubTree(property, parentProperty);
1434     //q_ptr->propertyInserted(property, parentProperty, afterProperty);
1435 }
1436 
1437 void QtAbstractPropertyBrowserPrivate::slotPropertyRemoved(QtProperty *property,
1438         QtProperty *parentProperty)
1439 {
1440     if (!m_propertyToParents.contains(parentProperty))
1441         return;
1442     removeSubTree(property, parentProperty); // this line should be probably moved down after propertyRemoved call
1443     //q_ptr->propertyRemoved(property, parentProperty);
1444     removeBrowserIndexes(property, parentProperty);
1445 }
1446 
1447 void QtAbstractPropertyBrowserPrivate::slotPropertyDestroyed(QtProperty *property)
1448 {
1449     if (!m_subItems.contains(property))
1450         return;
1451     q_ptr->removeProperty(property);
1452 }
1453 
1454 void QtAbstractPropertyBrowserPrivate::slotPropertyDataChanged(QtProperty *property)
1455 {
1456     if (!m_propertyToParents.contains(property))
1457         return;
1458 
1459     QMap<QtProperty *, QList<QtBrowserItem *> >::ConstIterator it =
1460             m_propertyToIndexes.find(property);
1461     if (it == m_propertyToIndexes.constEnd())
1462         return;
1463 
1464     const QList<QtBrowserItem *> indexes = it.value();
1465     for (QtBrowserItem *idx : indexes)
1466         q_ptr->itemChanged(idx);
1467     //q_ptr->propertyChanged(property);
1468 }
1469 
1470 /*!
1471     \class QtAbstractPropertyBrowser
1472     \internal
1473     \inmodule QtDesigner
1474     \since 4.4
1475 
1476     \brief QtAbstractPropertyBrowser provides a base class for
1477     implementing property browsers.
1478 
1479     A property browser is a widget that enables the user to edit a
1480     given set of properties.  Each property is represented by a label
1481     specifying the property's name, and an editing widget (e.g. a line
1482     edit or a combobox) holding its value. A property can have zero or
1483     more subproperties.
1484 
1485     \image qtpropertybrowser.png
1486 
1487     The top level properties can be retrieved using the
1488     properties() function. To traverse each property's
1489     subproperties, use the QtProperty::subProperties() function. In
1490     addition, the set of top level properties can be manipulated using
1491     the addProperty(), insertProperty() and removeProperty()
1492     functions. Note that the QtProperty class provides a corresponding
1493     set of functions making it possible to manipulate the set of
1494     subproperties as well.
1495 
1496     To remove all the properties from the property browser widget, use
1497     the clear() function. This function will clear the editor, but it
1498     will not delete the properties since they can still be used in
1499     other editors.
1500 
1501     The properties themselves are created and managed by
1502     implementations of the QtAbstractPropertyManager class. A manager
1503     can handle (i.e. create and manage) properties of a given type. In
1504     the property browser the managers are associated with
1505     implementations of the QtAbstractEditorFactory: A factory is a
1506     class able to create an editing widget of a specified type.
1507 
1508     When using a property browser widget, managers must be created for
1509     each of the required property types before the properties
1510     themselves can be created. To ensure that the properties' values
1511     will be displayed using suitable editing widgets, the managers
1512     must be associated with objects of the preferred factory
1513     implementations using the setFactoryForManager() function. The
1514     property browser will use these associations to determine which
1515     factory it should use to create the preferred editing widget.
1516 
1517     Note that a factory can be associated with many managers, but a
1518     manager can only be associated with one single factory within the
1519     context of a single property browser.  The associations between
1520     managers and factories can at any time be removed using the
1521     unsetFactoryForManager() function.
1522 
1523     Whenever the property data changes or a property is inserted or
1524     removed, the itemChanged(), itemInserted() or
1525     itemRemoved() functions are called, respectively. These
1526     functions must be reimplemented in derived classes in order to
1527     update the property browser widget. Be aware that some property
1528     instances can appear several times in an abstract tree
1529     structure. For example:
1530 
1531     \table 100%
1532     \row
1533     \li
1534     \snippet doc/src/snippets/code/tools_shared_qtpropertybrowser_qtpropertybrowser.cpp 2
1535     \li  \image qtpropertybrowser-duplicate.png
1536     \endtable
1537 
1538     The addProperty() function returns a QtBrowserItem that uniquely
1539     identifies the created item.
1540 
1541     To make a property editable in the property browser, the
1542     createEditor() function must be called to provide the
1543     property with a suitable editing widget.
1544 
1545     Note that there are two ready-made property browser
1546     implementations:
1547 
1548     \list
1549         \li QtGroupBoxPropertyBrowser
1550         \li QtTreePropertyBrowser
1551     \endlist
1552 
1553     \sa QtAbstractPropertyManager, QtAbstractEditorFactoryBase
1554 */
1555 
1556 /*!
1557     \fn void QtAbstractPropertyBrowser::setFactoryForManager(PropertyManager *manager,
1558                     QtAbstractEditorFactory<PropertyManager> *factory)
1559 
1560     Connects the given \a manager to the given \a factory, ensuring
1561     that properties of the \a manager's type will be displayed with an
1562     editing widget suitable for their value.
1563 
1564     For example:
1565 
1566     \snippet doc/src/snippets/code/tools_shared_qtpropertybrowser_qtpropertybrowser.cpp 3
1567 
1568     In this example the \c myInteger property's value is displayed
1569     with a QSpinBox widget, while the \c myDouble property's value is
1570     displayed with a QDoubleSpinBox widget.
1571 
1572     Note that a factory can be associated with many managers, but a
1573     manager can only be associated with one single factory.  If the
1574     given \a manager already is associated with another factory, the
1575     old association is broken before the new one established.
1576 
1577     This function ensures that the given \a manager and the given \a
1578     factory are compatible, and it automatically calls the
1579     QtAbstractEditorFactory::addPropertyManager() function if necessary.
1580 
1581     \sa unsetFactoryForManager()
1582 */
1583 
1584 /*!
1585     \fn virtual void QtAbstractPropertyBrowser::itemInserted(QtBrowserItem *insertedItem,
1586         QtBrowserItem *precedingItem) = 0
1587 
1588     This function is called to update the widget whenever a property
1589     is inserted or added to the property browser, passing pointers to
1590     the \a insertedItem of property and the specified
1591     \a precedingItem as parameters.
1592 
1593     If \a precedingItem is 0, the \a insertedItem was put at
1594     the beginning of its parent item's list of subproperties. If
1595     the parent of \a insertedItem is 0, the \a insertedItem was added as a top
1596     level property of \e this property browser.
1597 
1598     This function must be reimplemented in derived classes. Note that
1599     if the \a insertedItem's property has subproperties, this
1600     method will be called for those properties as soon as the current call is finished.
1601 
1602     \sa insertProperty(), addProperty()
1603 */
1604 
1605 /*!
1606     \fn virtual void QtAbstractPropertyBrowser::itemRemoved(QtBrowserItem *item) = 0
1607 
1608     This function is called to update the widget whenever a property
1609     is removed from the property browser, passing the pointer to the
1610     \a item of the property as parameters. The passed \a item is
1611     deleted just after this call is finished.
1612 
1613     If the the parent of \a item is 0, the removed \a item was a
1614     top level property in this editor.
1615 
1616     This function must be reimplemented in derived classes. Note that
1617     if the removed \a item's property has subproperties, this
1618     method will be called for those properties just before the current call is started.
1619 
1620     \sa removeProperty()
1621 */
1622 
1623 /*!
1624     \fn virtual void QtAbstractPropertyBrowser::itemChanged(QtBrowserItem *item) = 0
1625 
1626     This function is called whenever a property's data changes,
1627     passing a pointer to the \a item of property as parameter.
1628 
1629     This function must be reimplemented in derived classes in order to
1630     update the property browser widget whenever a property's name,
1631     tool tip, status tip, "what's this" text, value text or value icon
1632     changes.
1633 
1634     Note that if the property browser contains several occurrences of
1635     the same property, this method will be called once for each
1636     occurrence (with a different item each time).
1637 
1638     \sa QtProperty, items()
1639 */
1640 
1641 /*!
1642     Creates an abstract property browser with the given \a parent.
1643 */
1644 QtAbstractPropertyBrowser::QtAbstractPropertyBrowser(QWidget *parent)
1645     : QWidget(parent), d_ptr(new QtAbstractPropertyBrowserPrivate)
1646 {
1647     d_ptr->q_ptr = this;
1648 
1649 }
1650 
1651 /*!
1652     Destroys the property browser, and destroys all the items that were
1653     created by this property browser.
1654 
1655     Note that the properties that were displayed in the editor are not
1656     deleted since they still can be used in other editors. Neither
1657     does the destructor delete the property managers and editor
1658     factories that were used by this property browser widget unless
1659     this widget was their parent.
1660 
1661     \sa QtAbstractPropertyManager::~QtAbstractPropertyManager()
1662 */
1663 QtAbstractPropertyBrowser::~QtAbstractPropertyBrowser()
1664 {
1665     const QList<QtBrowserItem *> indexes = topLevelItems();
1666     for (QtBrowserItem *item : indexes)
1667         d_ptr->clearIndex(item);
1668 }
1669 
1670 /*!
1671     Returns the property browser's list of top level properties.
1672 
1673     To traverse the subproperties, use the QtProperty::subProperties()
1674     function.
1675 
1676     \sa addProperty(), insertProperty(), removeProperty()
1677 */
1678 QList<QtProperty *> QtAbstractPropertyBrowser::properties() const
1679 {
1680     return d_ptr->m_subItems;
1681 }
1682 
1683 /*!
1684     Returns the property browser's list of all items associated
1685     with the given \a property.
1686 
1687     There is one item per instance of the property in the browser.
1688 
1689     \sa topLevelItem()
1690 */
1691 
1692 QList<QtBrowserItem *> QtAbstractPropertyBrowser::items(QtProperty *property) const
1693 {
1694     return d_ptr->m_propertyToIndexes.value(property);
1695 }
1696 
1697 /*!
1698     Returns the top-level items associated with the given \a property.
1699 
1700     Returns 0 if \a property wasn't inserted into this property
1701     browser or isn't a top-level one.
1702 
1703     \sa topLevelItems(), items()
1704 */
1705 
1706 QtBrowserItem *QtAbstractPropertyBrowser::topLevelItem(QtProperty *property) const
1707 {
1708     return d_ptr->m_topLevelPropertyToIndex.value(property);
1709 }
1710 
1711 /*!
1712     Returns the list of top-level items.
1713 
1714     \sa topLevelItem()
1715 */
1716 
1717 QList<QtBrowserItem *> QtAbstractPropertyBrowser::topLevelItems() const
1718 {
1719     return d_ptr->m_topLevelIndexes;
1720 }
1721 
1722 /*!
1723     Removes all the properties from the editor, but does not delete
1724     them since they can still be used in other editors.
1725 
1726     \sa removeProperty(), QtAbstractPropertyManager::clear()
1727 */
1728 void QtAbstractPropertyBrowser::clear()
1729 {
1730     const QList<QtProperty *> subList = properties();
1731     for (auto rit = subList.crbegin(), rend = subList.crend(); rit != rend; ++rit)
1732         removeProperty(*rit);
1733 }
1734 
1735 /*!
1736     Appends the given \a property (and its subproperties) to the
1737     property browser's list of top level properties. Returns the item
1738     created by property browser which is associated with the \a property.
1739     In order to get all children items created by the property
1740     browser in this call, the returned item should be traversed.
1741 
1742     If the specified \a property is already added, this function does
1743     nothing and returns 0.
1744 
1745     \sa insertProperty(), QtProperty::addSubProperty(), properties()
1746 */
1747 QtBrowserItem *QtAbstractPropertyBrowser::addProperty(QtProperty *property)
1748 {
1749     QtProperty *afterProperty = 0;
1750     if (d_ptr->m_subItems.count() > 0)
1751         afterProperty = d_ptr->m_subItems.last();
1752     return insertProperty(property, afterProperty);
1753 }
1754 
1755 /*!
1756     \fn QtBrowserItem *QtAbstractPropertyBrowser::insertProperty(QtProperty *property,
1757             QtProperty *afterProperty)
1758 
1759     Inserts the given \a property (and its subproperties) after
1760     the specified \a afterProperty in the browser's list of top
1761     level properties. Returns item created by property browser which
1762     is associated with the \a property. In order to get all children items
1763     created by the property browser in this call returned item should be traversed.
1764 
1765     If the specified \a afterProperty is 0, the given \a property is
1766     inserted at the beginning of the list.  If \a property is
1767     already inserted, this function does nothing and returns 0.
1768 
1769     \sa addProperty(), QtProperty::insertSubProperty(), properties()
1770 */
1771 QtBrowserItem *QtAbstractPropertyBrowser::insertProperty(QtProperty *property,
1772             QtProperty *afterProperty)
1773 {
1774     if (!property)
1775         return 0;
1776 
1777     // if item is already inserted in this item then cannot add.
1778     QList<QtProperty *> pendingList = properties();
1779     int pos = 0;
1780     int newPos = 0;
1781     while (pos < pendingList.count()) {
1782         QtProperty *prop = pendingList.at(pos);
1783         if (prop == property)
1784             return 0;
1785         if (prop == afterProperty) {
1786             newPos = pos + 1;
1787         }
1788         pos++;
1789     }
1790     d_ptr->createBrowserIndexes(property, 0, afterProperty);
1791 
1792     // traverse inserted subtree and connect to manager's signals
1793     d_ptr->insertSubTree(property, 0);
1794 
1795     d_ptr->m_subItems.insert(newPos, property);
1796     //propertyInserted(property, 0, properAfterProperty);
1797     return topLevelItem(property);
1798 }
1799 
1800 /*!
1801     Removes the specified \a property (and its subproperties) from the
1802     property browser's list of top level properties. All items
1803     that were associated with the given \a property and its children
1804     are deleted.
1805 
1806     Note that the properties are \e not deleted since they can still
1807     be used in other editors.
1808 
1809     \sa clear(), QtProperty::removeSubProperty(), properties()
1810 */
1811 void QtAbstractPropertyBrowser::removeProperty(QtProperty *property)
1812 {
1813     if (!property)
1814         return;
1815 
1816     QList<QtProperty *> pendingList = properties();
1817     int pos = 0;
1818     while (pos < pendingList.count()) {
1819         if (pendingList.at(pos) == property) {
1820             d_ptr->m_subItems.removeAt(pos); //perhaps this two lines
1821             d_ptr->removeSubTree(property, 0); //should be moved down after propertyRemoved call.
1822             //propertyRemoved(property, 0);
1823 
1824             d_ptr->removeBrowserIndexes(property, 0);
1825 
1826             // when item is deleted, item will call removeItem for top level items,
1827             // and itemRemoved for nested items.
1828 
1829             return;
1830         }
1831         pos++;
1832     }
1833 }
1834 
1835 /*!
1836     Creates an editing widget (with the given \a parent) for the given
1837     \a property according to the previously established associations
1838     between property managers and editor factories.
1839 
1840     If the property is created by a property manager which was not
1841     associated with any of the existing factories in \e this property
1842     editor, the function returns 0.
1843 
1844     To make a property editable in the property browser, the
1845     createEditor() function must be called to provide the
1846     property with a suitable editing widget.
1847 
1848     Reimplement this function to provide additional decoration for the
1849     editing widgets created by the installed factories.
1850 
1851     \sa setFactoryForManager()
1852 */
1853 QWidget *QtAbstractPropertyBrowser::createEditor(QtProperty *property,
1854                 QWidget *parent)
1855 {
1856     QtAbstractEditorFactoryBase *factory = 0;
1857     QtAbstractPropertyManager *manager = property->propertyManager();
1858 
1859     if (m_viewToManagerToFactory()->contains(this) &&
1860         (*m_viewToManagerToFactory())[this].contains(manager)) {
1861         factory = (*m_viewToManagerToFactory())[this][manager];
1862     }
1863 
1864     if (!factory)
1865         return 0;
1866     QWidget *w = factory->createEditor(property, parent);
1867     // Since some editors can be QComboBoxes, and we changed their focus policy in Qt 5
1868     // to make them feel more native on Mac, we need to relax the focus policy to something
1869     // more permissive to keep the combo box from losing focus, allowing it to stay alive,
1870     // when the user clicks on it to show the popup.
1871     if (w)
1872         w->setFocusPolicy(Qt::WheelFocus);
1873     return w;
1874 }
1875 
1876 bool QtAbstractPropertyBrowser::addFactory(QtAbstractPropertyManager *abstractManager,
1877             QtAbstractEditorFactoryBase *abstractFactory)
1878 {
1879     bool connectNeeded = false;
1880     if (!m_managerToFactoryToViews()->contains(abstractManager) ||
1881         !(*m_managerToFactoryToViews())[abstractManager].contains(abstractFactory)) {
1882         connectNeeded = true;
1883     } else if ((*m_managerToFactoryToViews())[abstractManager][abstractFactory]
1884                     .contains(this)) {
1885         return connectNeeded;
1886     }
1887 
1888     if (m_viewToManagerToFactory()->contains(this) &&
1889         (*m_viewToManagerToFactory())[this].contains(abstractManager)) {
1890         unsetFactoryForManager(abstractManager);
1891     }
1892 
1893     (*m_managerToFactoryToViews())[abstractManager][abstractFactory].append(this);
1894     (*m_viewToManagerToFactory())[this][abstractManager] = abstractFactory;
1895 
1896     return connectNeeded;
1897 }
1898 
1899 /*!
1900     Removes the association between the given \a manager and the
1901     factory bound to it, automatically calling the
1902     QtAbstractEditorFactory::removePropertyManager() function if necessary.
1903 
1904     \sa setFactoryForManager()
1905 */
1906 void QtAbstractPropertyBrowser::unsetFactoryForManager(QtAbstractPropertyManager *manager)
1907 {
1908     if (!m_viewToManagerToFactory()->contains(this) ||
1909         !(*m_viewToManagerToFactory())[this].contains(manager)) {
1910         return;
1911     }
1912 
1913     QtAbstractEditorFactoryBase *abstractFactory =
1914                 (*m_viewToManagerToFactory())[this][manager];
1915     (*m_viewToManagerToFactory())[this].remove(manager);
1916     if ((*m_viewToManagerToFactory())[this].isEmpty()) {
1917         (*m_viewToManagerToFactory()).remove(this);
1918     }
1919 
1920     (*m_managerToFactoryToViews())[manager][abstractFactory].removeAll(this);
1921     if ((*m_managerToFactoryToViews())[manager][abstractFactory].isEmpty()) {
1922         (*m_managerToFactoryToViews())[manager].remove(abstractFactory);
1923         abstractFactory->breakConnection(manager);
1924         if ((*m_managerToFactoryToViews())[manager].isEmpty()) {
1925             (*m_managerToFactoryToViews()).remove(manager);
1926         }
1927     }
1928 }
1929 
1930 /*!
1931     Returns the current item in the property browser.
1932 
1933     \sa setCurrentItem()
1934 */
1935 QtBrowserItem *QtAbstractPropertyBrowser::currentItem() const
1936 {
1937     return d_ptr->m_currentItem;
1938 }
1939 
1940 /*!
1941     Sets the current item in the property browser to \a item.
1942 
1943     \sa currentItem(), currentItemChanged()
1944 */
1945 void QtAbstractPropertyBrowser::setCurrentItem(QtBrowserItem *item)
1946 {
1947     QtBrowserItem *oldItem = d_ptr->m_currentItem;
1948     d_ptr->m_currentItem = item;
1949     if (oldItem != item)
1950         Q_EMIT  currentItemChanged(item);
1951 }
1952 
1953 QT_END_NAMESPACE
1954 
1955 #include "moc_qtpropertybrowser.cpp"