Merge branch 'master' of scm.dev.nokia.troll.no:qt/oslo-staging-1 into master-integration
[qt-netbsd.git] / tools / shared / qtpropertybrowser / qttreepropertybrowser.cpp
blobf578cc315a33fda122c98213b2fc1de238fd5631
1 /****************************************************************************
2 **
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the tools applications of the Qt Toolkit.
8 **
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
14 ** this package.
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.
38 ** $QT_END_LICENSE$
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>
55 QT_BEGIN_NAMESPACE
57 class QtPropertyEditorView;
59 class QtTreePropertyBrowserPrivate
61 QtTreePropertyBrowser *q_ptr;
62 Q_DECLARE_PUBLIC(QtTreePropertyBrowser)
64 public:
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;
98 private:
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;
113 QIcon m_expandIcon;
116 // ------------ QtPropertyEditorView
117 class QtPropertyEditorView : public QTreeWidget
119 Q_OBJECT
120 public:
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); }
129 protected:
130 void keyPressEvent(QKeyEvent *event);
131 void mousePressEvent(QMouseEvent *event);
132 void drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
134 private:
135 QtTreePropertyBrowserPrivate *m_editorPrivate;
138 QtPropertyEditorView::QtPropertyEditorView(QWidget *parent) :
139 QTreeWidget(parent),
140 m_editorPrivate(0)
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);
151 if (property)
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);
158 } else {
159 const QColor c = m_editorPrivate->calculatedBackgroundColor(m_editorPrivate->indexToBrowserItem(index));
160 if (c.isValid()) {
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));
167 painter->save();
168 painter->setPen(QPen(color));
169 painter->drawLine(opt.rect.x(), opt.rect.bottom(), opt.rect.right(), opt.rect.bottom());
170 painter->restore();
173 void QtPropertyEditorView::keyPressEvent(QKeyEvent *event)
175 switch (event->key()) {
176 case Qt::Key_Return:
177 case Qt::Key_Enter:
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))) {
182 event->accept();
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);
189 edit(index);
190 return;
192 break;
193 default:
194 break;
196 QTreeWidget::keyPressEvent(event);
199 void QtPropertyEditorView::mousePressEvent(QMouseEvent *event)
201 QTreeWidget::mousePressEvent(event);
202 QTreeWidgetItem *item = itemAt(event->pos());
204 if (item) {
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))) {
208 editItem(item, 1);
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
219 Q_OBJECT
220 public:
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; }
249 private slots:
250 void slotEditorDestroyed(QObject *object);
252 private:
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)
268 return 0;
270 QTreeWidgetItem *item = m_editorPrivate->indexToItem(index);
271 int indent = 0;
272 while (item->parent()) {
273 item = item->parent();
274 ++indent;
276 if (m_editorPrivate->treeWidget()->rootIsDecorated())
277 ++indent;
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) {
290 m_editedWidget = 0;
291 m_editedItem = 0;
296 void QtPropertyEditorDelegate::closeEditor(QtProperty *property)
298 if (QWidget *w = m_propertyToEditor.value(property, 0))
299 w->deleteLater();
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);
310 if (editor) {
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;
316 m_editedItem = item;
317 m_editedWidget = editor;
319 return editor;
322 return 0;
325 void QtPropertyEditorDelegate::updateEditorGeometry(QWidget *editor,
326 const QStyleOptionViewItem &option, const QModelIndex &index) const
328 Q_UNUSED(index)
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);
338 if (property)
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);
349 QColor c;
350 if (!hasValue && m_editorPrivate->markPropertiesWithoutValue()) {
351 c = opt.palette.color(QPalette::Dark);
352 opt.palette.setColor(QPalette::Text, opt.palette.color(QPalette::BrightText));
353 } else {
354 c = m_editorPrivate->calculatedBackgroundColor(m_editorPrivate->indexToBrowserItem(index));
355 if (c.isValid() && (opt.features & QStyleOptionViewItemV2::Alternate))
356 c = c.lighter(112);
358 if (c.isValid())
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));
365 painter->save();
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());
371 painter->restore();
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)
385 return false;
387 return QItemDelegate::eventFilter(object, event);
390 // -------- QtTreePropertyBrowserPrivate implementation
391 QtTreePropertyBrowserPrivate::QtTreePropertyBrowserPrivate() :
392 m_treeWidget(0),
393 m_headerVisible(true),
394 m_resizeMode(QtTreePropertyBrowser::Stretch),
395 m_delegate(0),
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)
404 QPixmap pix(14, 14);
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;
412 QPainter p;
413 // Draw closed state
414 p.begin(&pix);
415 style->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, &p);
416 p.end();
417 QIcon rc = pix;
418 rc.addPixmap(pix, QIcon::Selected, QIcon::Off);
419 // Draw opened state
420 branchOption.state |= QStyle::State_Open;
421 pix.fill(Qt::transparent);
422 p.begin(&pix);
423 style->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, &p);
424 p.end();
426 rc.addPixmap(pix, QIcon::Normal, QIcon::On);
427 rc.addPixmap(pix, QIcon::Selected, QIcon::On);
428 return rc;
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);
441 QStringList labels;
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);
464 return 0;
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);
472 else
473 m_treeWidget->setCurrentItem(m_indexToItem.value(browserItem));
474 if (block)
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);
482 if (idx)
483 return idx->property();
484 return 0;
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);
513 disableItem(child);
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()) {
528 enableItem(child);
533 bool QtTreePropertyBrowserPrivate::hasValue(QTreeWidgetItem *item) const
535 QtBrowserItem *browserItem = m_itemToIndex.value(item);
536 if (browserItem)
537 return browserItem->property()->hasValue();
538 return false;
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;
547 if (parentItem) {
548 newItem = new QTreeWidgetItem(parentItem, afterItem);
549 } else {
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);
558 updateItem(newItem);
561 void QtTreePropertyBrowserPrivate::propertyRemoved(QtBrowserItem *index)
563 QTreeWidgetItem *item = m_indexToItem.value(index);
565 if (m_treeWidget->currentItem() == item) {
566 m_treeWidget->setCurrentItem(0);
569 delete item;
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);
580 updateItem(item);
583 void QtTreePropertyBrowserPrivate::updateItem(QTreeWidgetItem *item)
585 QtProperty *property = m_itemToIndex[item]->property();
586 QIcon expandIcon;
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))
608 isEnabled = true;
609 else
610 isEnabled = false;
611 } else {
612 isEnabled = false;
614 if (wasEnabled != isEnabled) {
615 if (isEnabled)
616 enableItem(item);
617 else
618 disableItem(item);
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();
627 while (i) {
628 QMap<QtBrowserItem *, QColor>::const_iterator it = m_indexToBackgroundColor.constFind(i);
629 if (it != itEnd)
630 return it.value();
631 i = i->parent();
633 return QColor();
636 void QtTreePropertyBrowserPrivate::slotCollapsed(const QModelIndex &index)
638 QTreeWidgetItem *item = indexToItem(index);
639 QtBrowserItem *idx = m_itemToIndex.value(item);
640 if (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);
648 if (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
681 \internal
682 \inmodule QtDesigner
683 \since 4.4
685 \brief The QtTreePropertyBrowser class provides QTreeWidget based
686 property browser.
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
692 more subproperties.
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)
731 d_ptr->q_ptr = this;
733 d_ptr->init(this);
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
743 them.
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)
813 return;
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.
837 \sa setResizeMode()
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)
853 return;
855 d_ptr->m_resizeMode = mode;
856 QHeaderView::ResizeMode m = QHeaderView::Stretch;
857 switch (mode) {
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);
891 if (treeItem)
892 treeItem->setExpanded(expanded);
896 Returns true if the \a item is expanded; otherwise returns false.
898 \sa setExpanded()
901 bool QtTreePropertyBrowser::isExpanded(QtBrowserItem *item) const
903 QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item);
904 if (treeItem)
905 return treeItem->isExpanded();
906 return false;
910 Returns true if the \a item is visible; otherwise returns false.
912 \sa setItemVisible()
913 \since 4.5
916 bool QtTreePropertyBrowser::isItemVisible(QtBrowserItem *item) const
918 if (const QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item))
919 return !treeItem->isHidden();
920 return false;
924 Sets the \a item to be visible, depending on the value of \a visible.
926 \sa isItemVisible()
927 \since 4.5
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))
946 return;
947 if (color.isValid())
948 d_ptr->m_indexToBackgroundColor[item] = color;
949 else
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)
990 return;
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;
1008 \reimp
1010 void QtTreePropertyBrowser::itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem)
1012 d_ptr->propertyInserted(item, afterItem);
1016 \reimp
1018 void QtTreePropertyBrowser::itemRemoved(QtBrowserItem *item)
1020 d_ptr->propertyRemoved(item);
1024 \reimp
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);
1039 QT_END_NAMESPACE
1041 #include "moc_qttreepropertybrowser.cpp"
1042 #include "qttreepropertybrowser.moc"