1 /****************************************************************************
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the tools applications of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "qttreepropertybrowser.h"
43 #include <QtCore/QSet>
44 #include <QtGui/QIcon>
45 #include <QtGui/QTreeWidget>
46 #include <QtGui/QItemDelegate>
47 #include <QtGui/QHBoxLayout>
48 #include <QtGui/QHeaderView>
49 #include <QtGui/QPainter>
50 #include <QtGui/QApplication>
51 #include <QtGui/QFocusEvent>
52 #include <QtGui/QStyle>
53 #include <QtGui/QPalette>
57 class QtPropertyEditorView
;
59 class QtTreePropertyBrowserPrivate
61 QtTreePropertyBrowser
*q_ptr
;
62 Q_DECLARE_PUBLIC(QtTreePropertyBrowser
)
65 QtTreePropertyBrowserPrivate();
66 void init(QWidget
*parent
);
68 void propertyInserted(QtBrowserItem
*index
, QtBrowserItem
*afterIndex
);
69 void propertyRemoved(QtBrowserItem
*index
);
70 void propertyChanged(QtBrowserItem
*index
);
71 QWidget
*createEditor(QtProperty
*property
, QWidget
*parent
) const
72 { return q_ptr
->createEditor(property
, parent
); }
73 QtProperty
*indexToProperty(const QModelIndex
&index
) const;
74 QTreeWidgetItem
*indexToItem(const QModelIndex
&index
) const;
75 QtBrowserItem
*indexToBrowserItem(const QModelIndex
&index
) const;
76 bool lastColumn(int column
) const;
77 void disableItem(QTreeWidgetItem
*item
) const;
78 void enableItem(QTreeWidgetItem
*item
) const;
79 bool hasValue(QTreeWidgetItem
*item
) const;
81 void slotCollapsed(const QModelIndex
&index
);
82 void slotExpanded(const QModelIndex
&index
);
84 QColor
calculatedBackgroundColor(QtBrowserItem
*item
) const;
86 QtPropertyEditorView
*treeWidget() const { return m_treeWidget
; }
87 bool markPropertiesWithoutValue() const { return m_markPropertiesWithoutValue
; }
89 QtBrowserItem
*currentItem() const;
90 void setCurrentItem(QtBrowserItem
*browserItem
, bool block
);
91 void editItem(QtBrowserItem
*browserItem
);
93 void slotCurrentBrowserItemChanged(QtBrowserItem
*item
);
94 void slotCurrentTreeItemChanged(QTreeWidgetItem
*newItem
, QTreeWidgetItem
*);
96 QTreeWidgetItem
*editedItem() const;
99 void updateItem(QTreeWidgetItem
*item
);
101 QMap
<QtBrowserItem
*, QTreeWidgetItem
*> m_indexToItem
;
102 QMap
<QTreeWidgetItem
*, QtBrowserItem
*> m_itemToIndex
;
104 QMap
<QtBrowserItem
*, QColor
> m_indexToBackgroundColor
;
106 QtPropertyEditorView
*m_treeWidget
;
108 bool m_headerVisible
;
109 QtTreePropertyBrowser::ResizeMode m_resizeMode
;
110 class QtPropertyEditorDelegate
*m_delegate
;
111 bool m_markPropertiesWithoutValue
;
112 bool m_browserChangedBlocked
;
116 // ------------ QtPropertyEditorView
117 class QtPropertyEditorView
: public QTreeWidget
121 QtPropertyEditorView(QWidget
*parent
= 0);
123 void setEditorPrivate(QtTreePropertyBrowserPrivate
*editorPrivate
)
124 { m_editorPrivate
= editorPrivate
; }
126 QTreeWidgetItem
*indexToItem(const QModelIndex
&index
) const
127 { return itemFromIndex(index
); }
130 void keyPressEvent(QKeyEvent
*event
);
131 void mousePressEvent(QMouseEvent
*event
);
132 void drawRow(QPainter
*painter
, const QStyleOptionViewItem
&option
, const QModelIndex
&index
) const;
135 QtTreePropertyBrowserPrivate
*m_editorPrivate
;
138 QtPropertyEditorView::QtPropertyEditorView(QWidget
*parent
) :
142 connect(header(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(resizeColumnToContents(int)));
145 void QtPropertyEditorView::drawRow(QPainter
*painter
, const QStyleOptionViewItem
&option
, const QModelIndex
&index
) const
147 QStyleOptionViewItemV3 opt
= option
;
148 bool hasValue
= true;
149 if (m_editorPrivate
) {
150 QtProperty
*property
= m_editorPrivate
->indexToProperty(index
);
152 hasValue
= property
->hasValue();
154 if (!hasValue
&& m_editorPrivate
->markPropertiesWithoutValue()) {
155 const QColor c
= option
.palette
.color(QPalette::Dark
);
156 painter
->fillRect(option
.rect
, c
);
157 opt
.palette
.setColor(QPalette::AlternateBase
, c
);
159 const QColor c
= m_editorPrivate
->calculatedBackgroundColor(m_editorPrivate
->indexToBrowserItem(index
));
161 painter
->fillRect(option
.rect
, c
);
162 opt
.palette
.setColor(QPalette::AlternateBase
, c
.lighter(112));
165 QTreeWidget::drawRow(painter
, opt
, index
);
166 QColor color
= static_cast<QRgb
>(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor
, &opt
));
168 painter
->setPen(QPen(color
));
169 painter
->drawLine(opt
.rect
.x(), opt
.rect
.bottom(), opt
.rect
.right(), opt
.rect
.bottom());
173 void QtPropertyEditorView::keyPressEvent(QKeyEvent
*event
)
175 switch (event
->key()) {
178 case Qt::Key_Space
: // Trigger Edit
179 if (!m_editorPrivate
->editedItem())
180 if (const QTreeWidgetItem
*item
= currentItem())
181 if (item
->columnCount() >= 2 && ((item
->flags() & (Qt::ItemIsEditable
| Qt::ItemIsEnabled
)) == (Qt::ItemIsEditable
| Qt::ItemIsEnabled
))) {
183 // If the current position is at column 0, move to 1.
184 QModelIndex index
= currentIndex();
185 if (index
.column() == 0) {
186 index
= index
.sibling(index
.row(), 1);
187 setCurrentIndex(index
);
196 QTreeWidget::keyPressEvent(event
);
199 void QtPropertyEditorView::mousePressEvent(QMouseEvent
*event
)
201 QTreeWidget::mousePressEvent(event
);
202 QTreeWidgetItem
*item
= itemAt(event
->pos());
205 if ((item
!= m_editorPrivate
->editedItem()) && (event
->button() == Qt::LeftButton
)
206 && (header()->logicalIndexAt(event
->pos().x()) == 1)
207 && ((item
->flags() & (Qt::ItemIsEditable
| Qt::ItemIsEnabled
)) == (Qt::ItemIsEditable
| Qt::ItemIsEnabled
))) {
209 } else if (!m_editorPrivate
->hasValue(item
) && m_editorPrivate
->markPropertiesWithoutValue() && !rootIsDecorated()) {
210 if (event
->pos().x() + header()->offset() < 20)
211 item
->setExpanded(!item
->isExpanded());
216 // ------------ QtPropertyEditorDelegate
217 class QtPropertyEditorDelegate
: public QItemDelegate
221 QtPropertyEditorDelegate(QObject
*parent
= 0)
222 : QItemDelegate(parent
), m_editorPrivate(0), m_editedItem(0), m_editedWidget(0)
225 void setEditorPrivate(QtTreePropertyBrowserPrivate
*editorPrivate
)
226 { m_editorPrivate
= editorPrivate
; }
228 QWidget
*createEditor(QWidget
*parent
, const QStyleOptionViewItem
&option
,
229 const QModelIndex
&index
) const;
231 void updateEditorGeometry(QWidget
*editor
, const QStyleOptionViewItem
&option
,
232 const QModelIndex
&index
) const;
234 void paint(QPainter
*painter
, const QStyleOptionViewItem
&option
,
235 const QModelIndex
&index
) const;
237 QSize
sizeHint(const QStyleOptionViewItem
&option
, const QModelIndex
&index
) const;
239 void setModelData(QWidget
*, QAbstractItemModel
*,
240 const QModelIndex
&) const {}
242 void setEditorData(QWidget
*, const QModelIndex
&) const {}
244 bool eventFilter(QObject
*object
, QEvent
*event
);
245 void closeEditor(QtProperty
*property
);
247 QTreeWidgetItem
*editedItem() const { return m_editedItem
; }
250 void slotEditorDestroyed(QObject
*object
);
253 int indentation(const QModelIndex
&index
) const;
255 typedef QMap
<QWidget
*, QtProperty
*> EditorToPropertyMap
;
256 mutable EditorToPropertyMap m_editorToProperty
;
258 typedef QMap
<QtProperty
*, QWidget
*> PropertyToEditorMap
;
259 mutable PropertyToEditorMap m_propertyToEditor
;
260 QtTreePropertyBrowserPrivate
*m_editorPrivate
;
261 mutable QTreeWidgetItem
*m_editedItem
;
262 mutable QWidget
*m_editedWidget
;
265 int QtPropertyEditorDelegate::indentation(const QModelIndex
&index
) const
267 if (!m_editorPrivate
)
270 QTreeWidgetItem
*item
= m_editorPrivate
->indexToItem(index
);
272 while (item
->parent()) {
273 item
= item
->parent();
276 if (m_editorPrivate
->treeWidget()->rootIsDecorated())
278 return indent
* m_editorPrivate
->treeWidget()->indentation();
281 void QtPropertyEditorDelegate::slotEditorDestroyed(QObject
*object
)
283 if (QWidget
*w
= qobject_cast
<QWidget
*>(object
)) {
284 const EditorToPropertyMap::iterator it
= m_editorToProperty
.find(w
);
285 if (it
!= m_editorToProperty
.end()) {
286 m_propertyToEditor
.remove(it
.value());
287 m_editorToProperty
.erase(it
);
289 if (m_editedWidget
== w
) {
296 void QtPropertyEditorDelegate::closeEditor(QtProperty
*property
)
298 if (QWidget
*w
= m_propertyToEditor
.value(property
, 0))
302 QWidget
*QtPropertyEditorDelegate::createEditor(QWidget
*parent
,
303 const QStyleOptionViewItem
&, const QModelIndex
&index
) const
305 if (index
.column() == 1 && m_editorPrivate
) {
306 QtProperty
*property
= m_editorPrivate
->indexToProperty(index
);
307 QTreeWidgetItem
*item
= m_editorPrivate
->indexToItem(index
);
308 if (property
&& item
&& (item
->flags() & Qt::ItemIsEnabled
)) {
309 QWidget
*editor
= m_editorPrivate
->createEditor(property
, parent
);
311 editor
->setAutoFillBackground(true);
312 editor
->installEventFilter(const_cast<QtPropertyEditorDelegate
*>(this));
313 connect(editor
, SIGNAL(destroyed(QObject
*)), this, SLOT(slotEditorDestroyed(QObject
*)));
314 m_propertyToEditor
[property
] = editor
;
315 m_editorToProperty
[editor
] = property
;
317 m_editedWidget
= editor
;
325 void QtPropertyEditorDelegate::updateEditorGeometry(QWidget
*editor
,
326 const QStyleOptionViewItem
&option
, const QModelIndex
&index
) const
329 editor
->setGeometry(option
.rect
.adjusted(0, 0, 0, -1));
332 void QtPropertyEditorDelegate::paint(QPainter
*painter
, const QStyleOptionViewItem
&option
,
333 const QModelIndex
&index
) const
335 bool hasValue
= true;
336 if (m_editorPrivate
) {
337 QtProperty
*property
= m_editorPrivate
->indexToProperty(index
);
339 hasValue
= property
->hasValue();
341 QStyleOptionViewItemV3 opt
= option
;
342 if ((m_editorPrivate
&& index
.column() == 0) || !hasValue
) {
343 QtProperty
*property
= m_editorPrivate
->indexToProperty(index
);
344 if (property
&& property
->isModified()) {
345 opt
.font
.setBold(true);
346 opt
.fontMetrics
= QFontMetrics(opt
.font
);
350 if (!hasValue
&& m_editorPrivate
->markPropertiesWithoutValue()) {
351 c
= opt
.palette
.color(QPalette::Dark
);
352 opt
.palette
.setColor(QPalette::Text
, opt
.palette
.color(QPalette::BrightText
));
354 c
= m_editorPrivate
->calculatedBackgroundColor(m_editorPrivate
->indexToBrowserItem(index
));
355 if (c
.isValid() && (opt
.features
& QStyleOptionViewItemV2::Alternate
))
359 painter
->fillRect(option
.rect
, c
);
360 opt
.state
&= ~QStyle::State_HasFocus
;
361 QItemDelegate::paint(painter
, opt
, index
);
363 opt
.palette
.setCurrentColorGroup(QPalette::Active
);
364 QColor color
= static_cast<QRgb
>(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor
, &opt
));
366 painter
->setPen(QPen(color
));
367 if (!m_editorPrivate
|| (!m_editorPrivate
->lastColumn(index
.column()) && hasValue
)) {
368 int right
= (option
.direction
== Qt::LeftToRight
) ? option
.rect
.right() : option
.rect
.left();
369 painter
->drawLine(right
, option
.rect
.y(), right
, option
.rect
.bottom());
374 QSize
QtPropertyEditorDelegate::sizeHint(const QStyleOptionViewItem
&option
,
375 const QModelIndex
&index
) const
377 return QItemDelegate::sizeHint(option
, index
) + QSize(3, 4);
380 bool QtPropertyEditorDelegate::eventFilter(QObject
*object
, QEvent
*event
)
382 if (event
->type() == QEvent::FocusOut
) {
383 QFocusEvent
*fe
= static_cast<QFocusEvent
*>(event
);
384 if (fe
->reason() == Qt::ActiveWindowFocusReason
)
387 return QItemDelegate::eventFilter(object
, event
);
390 // -------- QtTreePropertyBrowserPrivate implementation
391 QtTreePropertyBrowserPrivate::QtTreePropertyBrowserPrivate() :
393 m_headerVisible(true),
394 m_resizeMode(QtTreePropertyBrowser::Stretch
),
396 m_markPropertiesWithoutValue(false),
397 m_browserChangedBlocked(false)
401 // Draw an icon indicating opened/closing branches
402 static QIcon
drawIndicatorIcon(const QPalette
&palette
, QStyle
*style
)
405 pix
.fill(Qt::transparent
);
406 QStyleOption branchOption
;
407 QRect
r(QPoint(0, 0), pix
.size());
408 branchOption
.rect
= QRect(2, 2, 9, 9); // ### hardcoded in qcommonstyle.cpp
409 branchOption
.palette
= palette
;
410 branchOption
.state
= QStyle::State_Children
;
415 style
->drawPrimitive(QStyle::PE_IndicatorBranch
, &branchOption
, &p
);
418 rc
.addPixmap(pix
, QIcon::Selected
, QIcon::Off
);
420 branchOption
.state
|= QStyle::State_Open
;
421 pix
.fill(Qt::transparent
);
423 style
->drawPrimitive(QStyle::PE_IndicatorBranch
, &branchOption
, &p
);
426 rc
.addPixmap(pix
, QIcon::Normal
, QIcon::On
);
427 rc
.addPixmap(pix
, QIcon::Selected
, QIcon::On
);
431 void QtTreePropertyBrowserPrivate::init(QWidget
*parent
)
433 QHBoxLayout
*layout
= new QHBoxLayout(parent
);
434 layout
->setMargin(0);
435 m_treeWidget
= new QtPropertyEditorView(parent
);
436 m_treeWidget
->setEditorPrivate(this);
437 m_treeWidget
->setIconSize(QSize(18, 18));
438 layout
->addWidget(m_treeWidget
);
440 m_treeWidget
->setColumnCount(2);
442 labels
.append(QApplication::translate("QtTreePropertyBrowser", "Property", 0, QApplication::UnicodeUTF8
));
443 labels
.append(QApplication::translate("QtTreePropertyBrowser", "Value", 0, QApplication::UnicodeUTF8
));
444 m_treeWidget
->setHeaderLabels(labels
);
445 m_treeWidget
->setAlternatingRowColors(true);
446 m_treeWidget
->setEditTriggers(QAbstractItemView::EditKeyPressed
);
447 m_delegate
= new QtPropertyEditorDelegate(parent
);
448 m_delegate
->setEditorPrivate(this);
449 m_treeWidget
->setItemDelegate(m_delegate
);
450 m_treeWidget
->header()->setMovable(false);
451 m_treeWidget
->header()->setResizeMode(QHeaderView::Stretch
);
453 m_expandIcon
= drawIndicatorIcon(q_ptr
->palette(), q_ptr
->style());
455 QObject::connect(m_treeWidget
, SIGNAL(collapsed(QModelIndex
)), q_ptr
, SLOT(slotCollapsed(QModelIndex
)));
456 QObject::connect(m_treeWidget
, SIGNAL(expanded(QModelIndex
)), q_ptr
, SLOT(slotExpanded(QModelIndex
)));
457 QObject::connect(m_treeWidget
, SIGNAL(currentItemChanged(QTreeWidgetItem
*,QTreeWidgetItem
*)), q_ptr
, SLOT(slotCurrentTreeItemChanged(QTreeWidgetItem
*,QTreeWidgetItem
*)));
460 QtBrowserItem
*QtTreePropertyBrowserPrivate::currentItem() const
462 if (QTreeWidgetItem
*treeItem
= m_treeWidget
->currentItem())
463 return m_itemToIndex
.value(treeItem
);
467 void QtTreePropertyBrowserPrivate::setCurrentItem(QtBrowserItem
*browserItem
, bool block
)
469 const bool blocked
= block
? m_treeWidget
->blockSignals(true) : false;
470 if (browserItem
== 0)
471 m_treeWidget
->setCurrentItem(0);
473 m_treeWidget
->setCurrentItem(m_indexToItem
.value(browserItem
));
475 m_treeWidget
->blockSignals(blocked
);
478 QtProperty
*QtTreePropertyBrowserPrivate::indexToProperty(const QModelIndex
&index
) const
480 QTreeWidgetItem
*item
= m_treeWidget
->indexToItem(index
);
481 QtBrowserItem
*idx
= m_itemToIndex
.value(item
);
483 return idx
->property();
487 QtBrowserItem
*QtTreePropertyBrowserPrivate::indexToBrowserItem(const QModelIndex
&index
) const
489 QTreeWidgetItem
*item
= m_treeWidget
->indexToItem(index
);
490 return m_itemToIndex
.value(item
);
493 QTreeWidgetItem
*QtTreePropertyBrowserPrivate::indexToItem(const QModelIndex
&index
) const
495 return m_treeWidget
->indexToItem(index
);
498 bool QtTreePropertyBrowserPrivate::lastColumn(int column
) const
500 return m_treeWidget
->header()->visualIndex(column
) == m_treeWidget
->columnCount() - 1;
503 void QtTreePropertyBrowserPrivate::disableItem(QTreeWidgetItem
*item
) const
505 Qt::ItemFlags flags
= item
->flags();
506 if (flags
& Qt::ItemIsEnabled
) {
507 flags
&= ~Qt::ItemIsEnabled
;
508 item
->setFlags(flags
);
509 m_delegate
->closeEditor(m_itemToIndex
[item
]->property());
510 const int childCount
= item
->childCount();
511 for (int i
= 0; i
< childCount
; i
++) {
512 QTreeWidgetItem
*child
= item
->child(i
);
518 void QtTreePropertyBrowserPrivate::enableItem(QTreeWidgetItem
*item
) const
520 Qt::ItemFlags flags
= item
->flags();
521 flags
|= Qt::ItemIsEnabled
;
522 item
->setFlags(flags
);
523 const int childCount
= item
->childCount();
524 for (int i
= 0; i
< childCount
; i
++) {
525 QTreeWidgetItem
*child
= item
->child(i
);
526 QtProperty
*property
= m_itemToIndex
[child
]->property();
527 if (property
->isEnabled()) {
533 bool QtTreePropertyBrowserPrivate::hasValue(QTreeWidgetItem
*item
) const
535 QtBrowserItem
*browserItem
= m_itemToIndex
.value(item
);
537 return browserItem
->property()->hasValue();
541 void QtTreePropertyBrowserPrivate::propertyInserted(QtBrowserItem
*index
, QtBrowserItem
*afterIndex
)
543 QTreeWidgetItem
*afterItem
= m_indexToItem
.value(afterIndex
);
544 QTreeWidgetItem
*parentItem
= m_indexToItem
.value(index
->parent());
546 QTreeWidgetItem
*newItem
= 0;
548 newItem
= new QTreeWidgetItem(parentItem
, afterItem
);
550 newItem
= new QTreeWidgetItem(m_treeWidget
, afterItem
);
552 m_itemToIndex
[newItem
] = index
;
553 m_indexToItem
[index
] = newItem
;
555 newItem
->setFlags(newItem
->flags() | Qt::ItemIsEditable
);
556 m_treeWidget
->setItemExpanded(newItem
, true);
561 void QtTreePropertyBrowserPrivate::propertyRemoved(QtBrowserItem
*index
)
563 QTreeWidgetItem
*item
= m_indexToItem
.value(index
);
565 if (m_treeWidget
->currentItem() == item
) {
566 m_treeWidget
->setCurrentItem(0);
571 m_indexToItem
.remove(index
);
572 m_itemToIndex
.remove(item
);
573 m_indexToBackgroundColor
.remove(index
);
576 void QtTreePropertyBrowserPrivate::propertyChanged(QtBrowserItem
*index
)
578 QTreeWidgetItem
*item
= m_indexToItem
.value(index
);
583 void QtTreePropertyBrowserPrivate::updateItem(QTreeWidgetItem
*item
)
585 QtProperty
*property
= m_itemToIndex
[item
]->property();
587 if (property
->hasValue()) {
588 QString toolTip
= property
->toolTip();
589 if (toolTip
.isEmpty())
590 toolTip
= property
->valueText();
591 item
->setToolTip(1, toolTip
);
592 item
->setIcon(1, property
->valueIcon());
593 item
->setText(1, property
->valueText());
594 } else if (markPropertiesWithoutValue() && !m_treeWidget
->rootIsDecorated()) {
595 expandIcon
= m_expandIcon
;
597 item
->setIcon(0, expandIcon
);
598 item
->setFirstColumnSpanned(!property
->hasValue());
599 item
->setToolTip(0, property
->propertyName());
600 item
->setStatusTip(0, property
->statusTip());
601 item
->setWhatsThis(0, property
->whatsThis());
602 item
->setText(0, property
->propertyName());
603 bool wasEnabled
= item
->flags() & Qt::ItemIsEnabled
;
604 bool isEnabled
= wasEnabled
;
605 if (property
->isEnabled()) {
606 QTreeWidgetItem
*parent
= item
->parent();
607 if (!parent
|| (parent
->flags() & Qt::ItemIsEnabled
))
614 if (wasEnabled
!= isEnabled
) {
620 m_treeWidget
->viewport()->update();
623 QColor
QtTreePropertyBrowserPrivate::calculatedBackgroundColor(QtBrowserItem
*item
) const
625 QtBrowserItem
*i
= item
;
626 const QMap
<QtBrowserItem
*, QColor
>::const_iterator itEnd
= m_indexToBackgroundColor
.constEnd();
628 QMap
<QtBrowserItem
*, QColor
>::const_iterator it
= m_indexToBackgroundColor
.constFind(i
);
636 void QtTreePropertyBrowserPrivate::slotCollapsed(const QModelIndex
&index
)
638 QTreeWidgetItem
*item
= indexToItem(index
);
639 QtBrowserItem
*idx
= m_itemToIndex
.value(item
);
641 emit q_ptr
->collapsed(idx
);
644 void QtTreePropertyBrowserPrivate::slotExpanded(const QModelIndex
&index
)
646 QTreeWidgetItem
*item
= indexToItem(index
);
647 QtBrowserItem
*idx
= m_itemToIndex
.value(item
);
649 emit q_ptr
->expanded(idx
);
652 void QtTreePropertyBrowserPrivate::slotCurrentBrowserItemChanged(QtBrowserItem
*item
)
654 if (!m_browserChangedBlocked
&& item
!= currentItem())
655 setCurrentItem(item
, true);
658 void QtTreePropertyBrowserPrivate::slotCurrentTreeItemChanged(QTreeWidgetItem
*newItem
, QTreeWidgetItem
*)
660 QtBrowserItem
*browserItem
= newItem
? m_itemToIndex
.value(newItem
) : 0;
661 m_browserChangedBlocked
= true;
662 q_ptr
->setCurrentItem(browserItem
);
663 m_browserChangedBlocked
= false;
666 QTreeWidgetItem
*QtTreePropertyBrowserPrivate::editedItem() const
668 return m_delegate
->editedItem();
671 void QtTreePropertyBrowserPrivate::editItem(QtBrowserItem
*browserItem
)
673 if (QTreeWidgetItem
*treeItem
= m_indexToItem
.value(browserItem
, 0)) {
674 m_treeWidget
->setCurrentItem (treeItem
, 1);
675 m_treeWidget
->editItem(treeItem
, 1);
680 \class QtTreePropertyBrowser
685 \brief The QtTreePropertyBrowser class provides QTreeWidget based
688 A property browser is a widget that enables the user to edit a
689 given set of properties. Each property is represented by a label
690 specifying the property's name, and an editing widget (e.g. a line
691 edit or a combobox) holding its value. A property can have zero or
694 QtTreePropertyBrowser provides a tree based view for all nested
695 properties, i.e. properties that have subproperties can be in an
696 expanded (subproperties are visible) or collapsed (subproperties
697 are hidden) state. For example:
699 \image qttreepropertybrowser.png
701 Use the QtAbstractPropertyBrowser API to add, insert and remove
702 properties from an instance of the QtTreePropertyBrowser class.
703 The properties themselves are created and managed by
704 implementations of the QtAbstractPropertyManager class.
706 \sa QtGroupBoxPropertyBrowser, QtAbstractPropertyBrowser
710 \fn void QtTreePropertyBrowser::collapsed(QtBrowserItem *item)
712 This signal is emitted when the \a item is collapsed.
714 \sa expanded(), setExpanded()
718 \fn void QtTreePropertyBrowser::expanded(QtBrowserItem *item)
720 This signal is emitted when the \a item is expanded.
722 \sa collapsed(), setExpanded()
726 Creates a property browser with the given \a parent.
728 QtTreePropertyBrowser::QtTreePropertyBrowser(QWidget
*parent
)
729 : QtAbstractPropertyBrowser(parent
), d_ptr(new QtTreePropertyBrowserPrivate
)
734 connect(this, SIGNAL(currentItemChanged(QtBrowserItem
*)), this, SLOT(slotCurrentBrowserItemChanged(QtBrowserItem
*)));
738 Destroys this property browser.
740 Note that the properties that were inserted into this browser are
741 \e not destroyed since they may still be used in other
742 browsers. The properties are owned by the manager that created
745 \sa QtProperty, QtAbstractPropertyManager
747 QtTreePropertyBrowser::~QtTreePropertyBrowser()
752 \property QtTreePropertyBrowser::indentation
753 \brief indentation of the items in the tree view.
755 int QtTreePropertyBrowser::indentation() const
757 return d_ptr
->m_treeWidget
->indentation();
760 void QtTreePropertyBrowser::setIndentation(int i
)
762 d_ptr
->m_treeWidget
->setIndentation(i
);
766 \property QtTreePropertyBrowser::rootIsDecorated
767 \brief whether to show controls for expanding and collapsing root items.
769 bool QtTreePropertyBrowser::rootIsDecorated() const
771 return d_ptr
->m_treeWidget
->rootIsDecorated();
774 void QtTreePropertyBrowser::setRootIsDecorated(bool show
)
776 d_ptr
->m_treeWidget
->setRootIsDecorated(show
);
777 QMapIterator
<QTreeWidgetItem
*, QtBrowserItem
*> it(d_ptr
->m_itemToIndex
);
778 while (it
.hasNext()) {
779 QtProperty
*property
= it
.next().value()->property();
780 if (!property
->hasValue())
781 d_ptr
->updateItem(it
.key());
786 \property QtTreePropertyBrowser::alternatingRowColors
787 \brief whether to draw the background using alternating colors.
788 By default this property is set to true.
790 bool QtTreePropertyBrowser::alternatingRowColors() const
792 return d_ptr
->m_treeWidget
->alternatingRowColors();
795 void QtTreePropertyBrowser::setAlternatingRowColors(bool enable
)
797 d_ptr
->m_treeWidget
->setAlternatingRowColors(enable
);
798 QMapIterator
<QTreeWidgetItem
*, QtBrowserItem
*> it(d_ptr
->m_itemToIndex
);
802 \property QtTreePropertyBrowser::headerVisible
803 \brief whether to show the header.
805 bool QtTreePropertyBrowser::isHeaderVisible() const
807 return d_ptr
->m_headerVisible
;
810 void QtTreePropertyBrowser::setHeaderVisible(bool visible
)
812 if (d_ptr
->m_headerVisible
== visible
)
815 d_ptr
->m_headerVisible
= visible
;
816 d_ptr
->m_treeWidget
->header()->setVisible(visible
);
820 \enum QtTreePropertyBrowser::ResizeMode
822 The resize mode specifies the behavior of the header sections.
824 \value Interactive The user can resize the sections.
825 The sections can also be resized programmatically using setSplitterPosition().
827 \value Fixed The user cannot resize the section.
828 The section can only be resized programmatically using setSplitterPosition().
830 \value Stretch QHeaderView will automatically resize the section to fill the available space.
831 The size cannot be changed by the user or programmatically.
833 \value ResizeToContents QHeaderView will automatically resize the section to its optimal
834 size based on the contents of the entire column.
835 The size cannot be changed by the user or programmatically.
841 \property QtTreePropertyBrowser::resizeMode
842 \brief the resize mode of setions in the header.
845 QtTreePropertyBrowser::ResizeMode
QtTreePropertyBrowser::resizeMode() const
847 return d_ptr
->m_resizeMode
;
850 void QtTreePropertyBrowser::setResizeMode(QtTreePropertyBrowser::ResizeMode mode
)
852 if (d_ptr
->m_resizeMode
== mode
)
855 d_ptr
->m_resizeMode
= mode
;
856 QHeaderView::ResizeMode m
= QHeaderView::Stretch
;
858 case QtTreePropertyBrowser::Interactive
: m
= QHeaderView::Interactive
; break;
859 case QtTreePropertyBrowser::Fixed
: m
= QHeaderView::Fixed
; break;
860 case QtTreePropertyBrowser::ResizeToContents
: m
= QHeaderView::ResizeToContents
; break;
861 case QtTreePropertyBrowser::Stretch
:
862 default: m
= QHeaderView::Stretch
; break;
864 d_ptr
->m_treeWidget
->header()->setResizeMode(m
);
868 \property QtTreePropertyBrowser::splitterPosition
869 \brief the position of the splitter between the colunms.
872 int QtTreePropertyBrowser::splitterPosition() const
874 return d_ptr
->m_treeWidget
->header()->sectionSize(0);
877 void QtTreePropertyBrowser::setSplitterPosition(int position
)
879 d_ptr
->m_treeWidget
->header()->resizeSection(0, position
);
883 Sets the \a item to either collapse or expanded, depending on the value of \a expanded.
885 \sa isExpanded(), expanded(), collapsed()
888 void QtTreePropertyBrowser::setExpanded(QtBrowserItem
*item
, bool expanded
)
890 QTreeWidgetItem
*treeItem
= d_ptr
->m_indexToItem
.value(item
);
892 treeItem
->setExpanded(expanded
);
896 Returns true if the \a item is expanded; otherwise returns false.
901 bool QtTreePropertyBrowser::isExpanded(QtBrowserItem
*item
) const
903 QTreeWidgetItem
*treeItem
= d_ptr
->m_indexToItem
.value(item
);
905 return treeItem
->isExpanded();
910 Returns true if the \a item is visible; otherwise returns false.
916 bool QtTreePropertyBrowser::isItemVisible(QtBrowserItem
*item
) const
918 if (const QTreeWidgetItem
*treeItem
= d_ptr
->m_indexToItem
.value(item
))
919 return !treeItem
->isHidden();
924 Sets the \a item to be visible, depending on the value of \a visible.
930 void QtTreePropertyBrowser::setItemVisible(QtBrowserItem
*item
, bool visible
)
932 if (QTreeWidgetItem
*treeItem
= d_ptr
->m_indexToItem
.value(item
))
933 treeItem
->setHidden(!visible
);
937 Sets the \a item's background color to \a color. Note that while item's background
938 is rendered every second row is being drawn with alternate color (which is a bit lighter than items \a color)
940 \sa backgroundColor(), calculatedBackgroundColor()
943 void QtTreePropertyBrowser::setBackgroundColor(QtBrowserItem
*item
, const QColor
&color
)
945 if (!d_ptr
->m_indexToItem
.contains(item
))
948 d_ptr
->m_indexToBackgroundColor
[item
] = color
;
950 d_ptr
->m_indexToBackgroundColor
.remove(item
);
951 d_ptr
->m_treeWidget
->viewport()->update();
955 Returns the \a item's color. If there is no color set for item it returns invalid color.
957 \sa calculatedBackgroundColor(), setBackgroundColor()
960 QColor
QtTreePropertyBrowser::backgroundColor(QtBrowserItem
*item
) const
962 return d_ptr
->m_indexToBackgroundColor
.value(item
);
966 Returns the \a item's color. If there is no color set for item it returns parent \a item's
967 color (if there is no color set for parent it returns grandparent's color and so on). In case
968 the color is not set for \a item and it's top level item it returns invalid color.
970 \sa backgroundColor(), setBackgroundColor()
973 QColor
QtTreePropertyBrowser::calculatedBackgroundColor(QtBrowserItem
*item
) const
975 return d_ptr
->calculatedBackgroundColor(item
);
979 \property QtTreePropertyBrowser::propertiesWithoutValueMarked
980 \brief whether to enable or disable marking properties without value.
982 When marking is enabled the item's background is rendered in dark color and item's
983 foreground is rendered with light color.
985 \sa propertiesWithoutValueMarked()
987 void QtTreePropertyBrowser::setPropertiesWithoutValueMarked(bool mark
)
989 if (d_ptr
->m_markPropertiesWithoutValue
== mark
)
992 d_ptr
->m_markPropertiesWithoutValue
= mark
;
993 QMapIterator
<QTreeWidgetItem
*, QtBrowserItem
*> it(d_ptr
->m_itemToIndex
);
994 while (it
.hasNext()) {
995 QtProperty
*property
= it
.next().value()->property();
996 if (!property
->hasValue())
997 d_ptr
->updateItem(it
.key());
999 d_ptr
->m_treeWidget
->viewport()->update();
1002 bool QtTreePropertyBrowser::propertiesWithoutValueMarked() const
1004 return d_ptr
->m_markPropertiesWithoutValue
;
1010 void QtTreePropertyBrowser::itemInserted(QtBrowserItem
*item
, QtBrowserItem
*afterItem
)
1012 d_ptr
->propertyInserted(item
, afterItem
);
1018 void QtTreePropertyBrowser::itemRemoved(QtBrowserItem
*item
)
1020 d_ptr
->propertyRemoved(item
);
1026 void QtTreePropertyBrowser::itemChanged(QtBrowserItem
*item
)
1028 d_ptr
->propertyChanged(item
);
1032 Sets the current item to \a item and opens the relevant editor for it.
1034 void QtTreePropertyBrowser::editItem(QtBrowserItem
*item
)
1036 d_ptr
->editItem(item
);
1041 #include "moc_qttreepropertybrowser.cpp"
1042 #include "qttreepropertybrowser.moc"