source: trunk/tools/shared/qtpropertybrowser/qtpropertybrowser.cpp@ 158

Last change on this file since 158 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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