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"