45 #include <QTreeWidget>
46 #include <QItemDelegate>
47 #include <QHBoxLayout>
48 #include <QHeaderView>
50 #include <QApplication>
51 #include <QFocusEvent>
66 void init(QWidget* parent);
81 bool hasValue(QTreeWidgetItem* item)
const;
94 return m_markPropertiesWithoutValue;
107 void updateItem(QTreeWidgetItem* item);
109 QMap<QtBrowserItem*, QTreeWidgetItem*> m_indexToItem;
110 QMap<QTreeWidgetItem*, QtBrowserItem*> m_itemToIndex;
112 QMap<QtBrowserItem*, QColor> m_indexToBackgroundColor;
116 bool m_headerVisible;
119 bool m_markPropertiesWithoutValue;
120 bool m_browserChangedBlocked;
133 m_editorPrivate = editorPrivate;
138 return itemFromIndex(
index);
144 void drawRow(QPainter* painter,
const QStyleOptionViewItem&
option,
const QModelIndex&
index)
const override;
154 connect(header(), SIGNAL(sectionDoubleClicked(
int)),
this, SLOT(resizeColumnToContents(
int)));
159 QStyleOptionViewItem opt =
option;
160 bool hasValue =
true;
174 const QColor
c =
option.palette.color(QPalette::Dark);
175 painter->fillRect(
option.rect,
c);
176 opt.palette.setColor(QPalette::AlternateBase,
c);
184 painter->fillRect(
option.rect,
c);
185 opt.palette.setColor(QPalette::AlternateBase,
c.lighter(112));
189 QTreeWidget::drawRow(painter, opt,
index);
190 QColor color =
static_cast<QRgb
>(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &opt));
192 painter->setPen(QPen(color));
193 painter->drawLine(opt.rect.x(), opt.rect.bottom(), opt.rect.right(), opt.rect.bottom());
199 switch (event->key())
205 if (
const QTreeWidgetItem* item = currentItem())
206 if (item->columnCount() >= 2 && ((item->flags() & (Qt::ItemIsEditable | Qt::ItemIsEnabled)) == (Qt::ItemIsEditable | Qt::ItemIsEnabled)))
210 QModelIndex
index = currentIndex();
212 if (
index.column() == 0)
215 setCurrentIndex(
index);
228 QTreeWidget::keyPressEvent(event);
233 QTreeWidget::mousePressEvent(event);
234 QTreeWidgetItem* item = itemAt(event->pos());
238 if ((item != m_editorPrivate->
editedItem()) && (event->button() == Qt::LeftButton)
239 && (header()->logicalIndexAt(event->pos().x()) == 1)
240 && ((item->flags() & (Qt::ItemIsEditable | Qt::ItemIsEnabled)) == (Qt::ItemIsEditable | Qt::ItemIsEnabled)))
246 if (event->pos().x() + header()->offset() < 20)
248 item->setExpanded(!item->isExpanded());
260 : QItemDelegate(parent), m_editorPrivate(0), m_editedItem(0), m_editedWidget(0), m_disablePainting(false)
265 m_editorPrivate = editorPrivate;
269 const QModelIndex&
index)
const override;
272 const QModelIndex&
index)
const override;
274 void paint(QPainter* painter,
const QStyleOptionViewItem&
option,
275 const QModelIndex&
index)
const override;
277 QSize
sizeHint(
const QStyleOptionViewItem&
option,
const QModelIndex&
index)
const override;
280 const QModelIndex&)
const override {}
284 bool eventFilter(QObject*
object, QEvent* event)
override;
295 const QRect& rect,
const QPixmap& pixmap)
const override;
297 const QRect& rect,
const QString& text)
const override;
300 void slotEditorDestroyed(QObject*
object);
303 int indentation(
const QModelIndex&
index)
const;
305 using EditorToPropertyMap = QMap<QWidget*, QtProperty*>;
306 mutable EditorToPropertyMap m_editorToProperty;
308 using PropertyToEditorMap = QMap<QtProperty*, QWidget*>;
309 mutable PropertyToEditorMap m_propertyToEditor;
311 mutable QTreeWidgetItem* m_editedItem;
312 mutable QWidget* m_editedWidget;
313 mutable bool m_disablePainting;
316 int QtPropertyEditorDelegate::indentation(
const QModelIndex&
index)
const
318 if (!m_editorPrivate)
326 while (item->parent())
328 item = item->parent();
332 if (m_editorPrivate->
treeWidget()->rootIsDecorated())
337 return indent * m_editorPrivate->
treeWidget()->indentation();
340 void QtPropertyEditorDelegate::slotEditorDestroyed(QObject*
object)
342 if (QWidget* w = qobject_cast<QWidget*>(
object))
344 const EditorToPropertyMap::iterator it = m_editorToProperty.find(w);
346 if (it != m_editorToProperty.end())
348 m_propertyToEditor.remove(it.value());
349 m_editorToProperty.erase(it);
352 if (m_editedWidget == w)
362 if (QWidget* w = m_propertyToEditor.value(property, 0))
369 const QStyleOptionViewItem&,
const QModelIndex&
index)
const
371 if (
index.column() == 1 && m_editorPrivate)
376 if (property && item && (item->flags() & Qt::ItemIsEnabled))
378 QWidget* editor = m_editorPrivate->
createEditor(property, parent);
382 editor->setAutoFillBackground(
true);
384 connect(editor, SIGNAL(destroyed(QObject*)),
this, SLOT(slotEditorDestroyed(QObject*)));
385 m_propertyToEditor[property] = editor;
386 m_editorToProperty[editor] = property;
388 m_editedWidget = editor;
399 const QStyleOptionViewItem&
option,
const QModelIndex&
index)
const
402 editor->setGeometry(
option.rect.adjusted(0, 0, 0, -1));
406 const QModelIndex&
index)
const
408 bool hasValue =
true;
420 QStyleOptionViewItem opt =
option;
422 if ((m_editorPrivate &&
index.column() == 0) || !hasValue)
426 if (property && property->isModified())
428 opt.font.setBold(
true);
429 opt.fontMetrics = QFontMetrics(opt.font);
437 c = opt.palette.color(QPalette::Dark);
438 opt.palette.setColor(QPalette::Text, opt.palette.color(QPalette::BrightText));
444 if (
c.isValid() && (opt.features & QStyleOptionViewItemV2::Alternate))
452 painter->fillRect(
option.rect,
c);
455 opt.state &= ~QStyle::State_HasFocus;
457 if (
index.column() == 1)
461 if (m_editedItem && m_editedItem == item)
463 m_disablePainting =
true;
467 QItemDelegate::paint(painter, opt,
index);
471 m_disablePainting =
false;
474 opt.palette.setCurrentColorGroup(QPalette::Active);
475 QColor color =
static_cast<QRgb
>(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &opt));
477 painter->setPen(QPen(color));
479 if (!m_editorPrivate || (!m_editorPrivate->
lastColumn(
index.column()) && hasValue))
481 int right = (
option.direction == Qt::LeftToRight) ?
option.rect.right() :
option.rect.left();
482 painter->drawLine(right,
option.rect.y(), right,
option.rect.bottom());
489 const QRect& rect,
const QPixmap& pixmap)
const
491 if (m_disablePainting)
496 QItemDelegate::drawDecoration(painter,
option, rect, pixmap);
500 const QRect& rect,
const QString& text)
const
502 if (m_disablePainting)
507 QItemDelegate::drawDisplay(painter,
option, rect, text);
511 const QModelIndex&
index)
const
513 return QItemDelegate::sizeHint(
option,
index) + QSize(3, 4);
518 if (event->type() == QEvent::FocusOut)
520 QFocusEvent* fe =
static_cast<QFocusEvent*
>(event);
522 if (fe->reason() == Qt::ActiveWindowFocusReason)
528 return QItemDelegate::eventFilter(
object, event);
534 m_headerVisible(true),
537 m_markPropertiesWithoutValue(false),
538 m_browserChangedBlocked(false)
543 static QIcon drawIndicatorIcon(
const QPalette& palette, QStyle* style)
547 QStyleOption branchOption;
548 QRect r(QPoint(0, 0), pix.size());
549 branchOption.rect = QRect(2, 2, 9, 9);
550 branchOption.palette = palette;
551 branchOption.state = QStyle::State_Children;
556 style->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, &p);
559 rc.addPixmap(pix, QIcon::Selected,
QIcon::Off);
561 branchOption.state |= QStyle::State_Open;
564 style->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, &p);
567 rc.addPixmap(pix, QIcon::Normal,
QIcon::On);
568 rc.addPixmap(pix, QIcon::Selected,
QIcon::On);
574 QHBoxLayout* layout =
new QHBoxLayout(parent);
575 layout->setMargin(0);
578 m_treeWidget->setIconSize(QSize(18, 18));
579 layout->addWidget(m_treeWidget);
580 parent->setFocusProxy(m_treeWidget);
582 m_treeWidget->setColumnCount(2);
584 labels.append(QCoreApplication::translate(
"QtTreePropertyBrowser",
"Property"));
585 labels.append(QCoreApplication::translate(
"QtTreePropertyBrowser",
"Value"));
586 m_treeWidget->setHeaderLabels(labels);
587 m_treeWidget->setAlternatingRowColors(
true);
588 m_treeWidget->setEditTriggers(QAbstractItemView::EditKeyPressed);
591 m_treeWidget->setItemDelegate(m_delegate);
592 m_treeWidget->header()->setMovable(
false);
593 m_treeWidget->header()->setResizeMode(QHeaderView::Stretch);
595 m_expandIcon = drawIndicatorIcon(q_ptr->palette(), q_ptr->style());
597 QObject::connect(m_treeWidget, SIGNAL(collapsed(
const QModelIndex&)), q_ptr, SLOT(
slotCollapsed(
const QModelIndex&)));
598 QObject::connect(m_treeWidget, SIGNAL(expanded(
const QModelIndex&)), q_ptr, SLOT(
slotExpanded(
const QModelIndex&)));
599 QObject::connect(m_treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), q_ptr, SLOT(
slotCurrentTreeItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
604 if (QTreeWidgetItem* treeItem = m_treeWidget->currentItem())
606 return m_itemToIndex.value(treeItem);
614 const bool blocked = block ? m_treeWidget->blockSignals(
true) :
false;
616 if (browserItem == 0)
618 m_treeWidget->setCurrentItem(0);
622 m_treeWidget->setCurrentItem(m_indexToItem.value(browserItem));
627 m_treeWidget->blockSignals(blocked);
647 return m_itemToIndex.value(item);
657 return m_treeWidget->header()->visualIndex(column) == m_treeWidget->columnCount() - 1;
662 Qt::ItemFlags flags = item->flags();
664 if (flags & Qt::ItemIsEnabled)
666 flags &= ~Qt::ItemIsEnabled;
667 item->setFlags(flags);
668 m_delegate->
closeEditor(m_itemToIndex[item]->property());
669 const int childCount = item->childCount();
671 for (
int i = 0; i < childCount; i++)
673 QTreeWidgetItem* child = item->child(i);
681 Qt::ItemFlags flags = item->flags();
682 flags |= Qt::ItemIsEnabled;
683 item->setFlags(flags);
684 const int childCount = item->childCount();
686 for (
int i = 0; i < childCount; i++)
688 QTreeWidgetItem* child = item->child(i);
689 QtProperty*
property = m_itemToIndex[child]->property();
691 if (property->isEnabled())
712 QTreeWidgetItem* afterItem = m_indexToItem.value(afterIndex);
713 QTreeWidgetItem* parentItem = m_indexToItem.value(
index->parent());
715 QTreeWidgetItem* newItem = 0;
719 newItem =
new QTreeWidgetItem(parentItem, afterItem);
723 newItem =
new QTreeWidgetItem(m_treeWidget, afterItem);
726 m_itemToIndex[newItem] =
index;
727 m_indexToItem[
index] = newItem;
729 newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
730 m_treeWidget->setItemExpanded(newItem,
true);
737 QTreeWidgetItem* item = m_indexToItem.value(
index);
739 if (m_treeWidget->currentItem() == item)
741 m_treeWidget->setCurrentItem(0);
746 m_indexToItem.remove(
index);
747 m_itemToIndex.remove(item);
748 m_indexToBackgroundColor.remove(
index);
753 QTreeWidgetItem* item = m_indexToItem.value(
index);
758 void QtTreePropertyBrowserPrivate::updateItem(QTreeWidgetItem* item)
760 QtProperty*
property = m_itemToIndex[item]->property();
763 if (property->hasValue())
765 QString toolTip =
property->toolTip();
767 if (toolTip.isEmpty())
769 toolTip =
property->displayText();
772 item->setToolTip(1, toolTip);
773 item->setIcon(1, property->valueIcon());
774 property->displayText().isEmpty() ? item->setText(1, property->valueText()) : item->setText(1, property->displayText());
778 expandIcon = m_expandIcon;
781 item->setIcon(0, expandIcon);
782 item->setFirstColumnSpanned(!property->hasValue());
783 item->setToolTip(0, property->propertyName());
784 item->setStatusTip(0, property->statusTip());
785 item->setWhatsThis(0, property->whatsThis());
786 item->setText(0, property->propertyName());
787 bool wasEnabled = item->flags() & Qt::ItemIsEnabled;
788 bool isEnabled = wasEnabled;
790 if (property->isEnabled())
792 QTreeWidgetItem* parent = item->parent();
794 if (!parent || (parent->flags() & Qt::ItemIsEnabled))
808 if (wasEnabled != isEnabled)
820 m_treeWidget->viewport()->update();
826 const QMap<QtBrowserItem*, QColor>::const_iterator itEnd = m_indexToBackgroundColor.constEnd();
830 QMap<QtBrowserItem*, QColor>::const_iterator it = m_indexToBackgroundColor.constFind(i);
867 if (!m_browserChangedBlocked && item !=
currentItem())
875 QtBrowserItem* browserItem = newItem ? m_itemToIndex.value(newItem) : 0;
876 m_browserChangedBlocked =
true;
878 m_browserChangedBlocked =
false;
888 if (QTreeWidgetItem* treeItem = m_indexToItem.value(browserItem, 0))
890 m_treeWidget->setCurrentItem(treeItem, 1);
891 m_treeWidget->editItem(treeItem, 1);
972 return d_ptr->m_treeWidget->indentation();
977 d_ptr->m_treeWidget->setIndentation(i);
986 return d_ptr->m_treeWidget->rootIsDecorated();
991 d_ptr->m_treeWidget->setRootIsDecorated(show);
992 QMapIterator<QTreeWidgetItem*, QtBrowserItem*> it(d_ptr->m_itemToIndex);
996 QtProperty*
property = it.next().value()->property();
998 if (!property->hasValue())
1000 d_ptr->updateItem(it.key());
1012 return d_ptr->m_treeWidget->alternatingRowColors();
1017 d_ptr->m_treeWidget->setAlternatingRowColors(enable);
1018 QMapIterator<QTreeWidgetItem*, QtBrowserItem*> it(d_ptr->m_itemToIndex);
1027 return d_ptr->m_headerVisible;
1032 if (d_ptr->m_headerVisible == visible)
1037 d_ptr->m_headerVisible = visible;
1038 d_ptr->m_treeWidget->header()->setVisible(visible);
1069 return d_ptr->m_resizeMode;
1074 if (d_ptr->m_resizeMode == mode)
1079 d_ptr->m_resizeMode = mode;
1080 QHeaderView::ResizeMode m = QHeaderView::Stretch;
1085 m = QHeaderView::Interactive;
1089 m = QHeaderView::Fixed;
1093 m = QHeaderView::ResizeToContents;
1098 m = QHeaderView::Stretch;
1102 d_ptr->m_treeWidget->header()->setResizeMode(m);
1112 return d_ptr->m_treeWidget->header()->sectionSize(0);
1117 d_ptr->m_treeWidget->header()->resizeSection(0, position);
1128 QTreeWidgetItem* treeItem = d_ptr->m_indexToItem.value(item);
1144 QTreeWidgetItem* treeItem = d_ptr->m_indexToItem.value(item);
1148 return treeItem->isExpanded();
1163 if (
const QTreeWidgetItem* treeItem = d_ptr->m_indexToItem.value(item))
1165 return !treeItem->isHidden();
1180 if (QTreeWidgetItem* treeItem = d_ptr->m_indexToItem.value(item))
1182 treeItem->setHidden(!visible);
1195 if (!d_ptr->m_indexToItem.contains(item))
1200 if (color.isValid())
1202 d_ptr->m_indexToBackgroundColor[item] = color;
1206 d_ptr->m_indexToBackgroundColor.remove(item);
1209 d_ptr->m_treeWidget->viewport()->update();
1220 return d_ptr->m_indexToBackgroundColor.value(item);
1247 if (d_ptr->m_markPropertiesWithoutValue == mark)
1252 d_ptr->m_markPropertiesWithoutValue = mark;
1253 QMapIterator<QTreeWidgetItem*, QtBrowserItem*> it(d_ptr->m_itemToIndex);
1255 while (it.hasNext())
1257 QtProperty*
property = it.next().value()->property();
1259 if (!property->hasValue())
1261 d_ptr->updateItem(it.key());
1265 d_ptr->m_treeWidget->viewport()->update();
1270 return d_ptr->m_markPropertiesWithoutValue;
1307 #include "moc_qttreepropertybrowser.cpp"
1308 #include "qttreepropertybrowser.moc"