1 /****************************************************************************
2 **
3 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the Qt Solutions component.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
14 ** * Redistributions of source code must retain the above copyright
15 ** notice, this list of conditions and the following disclaimer.
16 ** * Redistributions in binary form must reproduce the above copyright
17 ** notice, this list of conditions and the following disclaimer in
18 ** the documentation and/or other materials provided with the
19 ** distribution.
20 ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
21 ** of its contributors may be used to endorse or promote products derived
22 ** from this software without specific prior written permission.
23 **
24 **
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40
41
42 #include "qttreepropertybrowser.h"
43 #include <QSet>
44 #include <QIcon>
45 #include <QTreeWidget>
46 #include <QItemDelegate>
47 #include <QHBoxLayout>
48 #include <QHeaderView>
49 #include <QPainter>
50 #include <QApplication>
51 #include <QFocusEvent>
52 #include <QStyle>
53 #include <QPalette>
54 #include <QScreen>
55
56 #ifndef Q_OS_MAC
defaultDpiScale()57 static qreal defaultDpiScale()
58 {
59 if (const QScreen *screen = QGuiApplication::primaryScreen())
60 return screen->logicalDotsPerInchX() / 96.0;
61 return 1.0;
62 }
63 #endif
64
dpiScaled(qreal value)65 static qreal dpiScaled(qreal value)
66 {
67 #ifdef Q_OS_MAC
68 // On mac the DPI is always 72 so we should not scale it
69 return value;
70 #else
71 static const qreal scale = defaultDpiScale();
72 return value * scale;
73 #endif
74 }
75
dpiScaled(QSize value)76 static QSize dpiScaled(QSize value)
77 {
78 return QSize(qRound(dpiScaled(value.width())),
79 qRound(dpiScaled(value.height())));
80 }
81
82
83 #if QT_VERSION >= 0x040400
84 QT_BEGIN_NAMESPACE
85 #endif
86
87 class QtPropertyEditorView;
88
89 class QtTreePropertyBrowserPrivate
90 {
91 QtTreePropertyBrowser *q_ptr;
92 Q_DECLARE_PUBLIC(QtTreePropertyBrowser)
93
94 public:
95 QtTreePropertyBrowserPrivate();
96 void init(QWidget *parent);
97
98 void propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex);
99 void propertyRemoved(QtBrowserItem *index);
100 void propertyChanged(QtBrowserItem *index);
createEditor(QtProperty * property,QWidget * parent) const101 QWidget *createEditor(QtProperty *property, QWidget *parent) const
102 { return q_ptr->createEditor(property, parent); }
103 QtProperty *indexToProperty(const QModelIndex &index) const;
104 QTreeWidgetItem *indexToItem(const QModelIndex &index) const;
105 QtBrowserItem *indexToBrowserItem(const QModelIndex &index) const;
106 bool lastColumn(int column) const;
107 void disableItem(QTreeWidgetItem *item) const;
108 void enableItem(QTreeWidgetItem *item) const;
109 bool hasValue(QTreeWidgetItem *item) const;
110
111 void slotCollapsed(const QModelIndex &index);
112 void slotExpanded(const QModelIndex &index);
113
114 QColor calculatedBackgroundColor(QtBrowserItem *item) const;
115
treeWidget() const116 QtPropertyEditorView *treeWidget() const { return m_treeWidget; }
markPropertiesWithoutValue() const117 bool markPropertiesWithoutValue() const { return m_markPropertiesWithoutValue; }
118
119 QtBrowserItem *currentItem() const;
120 void setCurrentItem(QtBrowserItem *browserItem, bool block);
121 void editItem(QtBrowserItem *browserItem);
122
123 QList<QtBrowserItem*> selectedItems() const;
124
125 void slotCurrentBrowserItemChanged(QtBrowserItem *item);
126 void slotCurrentTreeItemChanged(QTreeWidgetItem *newItem, QTreeWidgetItem *);
127 void slotItemSelectionChanged();
128
129 QTreeWidgetItem *editedItem() const;
130 QtBrowserItem *editedBrowserItem() const;
131
132 private:
133 void updateItem(QTreeWidgetItem *item);
134
135 QMap<QtBrowserItem *, QTreeWidgetItem *> m_indexToItem;
136 QMap<QTreeWidgetItem *, QtBrowserItem *> m_itemToIndex;
137
138 QMap<QtBrowserItem *, QColor> m_indexToBackgroundColor;
139
140 QtPropertyEditorView *m_treeWidget;
141
142 bool m_headerVisible;
143 bool m_allowMultiSelection;
144 QtTreePropertyBrowser::ResizeMode m_resizeMode;
145 class QtPropertyEditorDelegate *m_delegate;
146 bool m_markPropertiesWithoutValue;
147 bool m_browserChangedBlocked;
148 QIcon m_expandIcon;
149 };
150
151 // ------------ QtPropertyEditorView
152 class QtPropertyEditorView : public QTreeWidget
153 {
154 Q_OBJECT
155 public:
156 explicit QtPropertyEditorView(QWidget *parent = 0);
157
setEditorPrivate(QtTreePropertyBrowserPrivate * editorPrivate)158 void setEditorPrivate(QtTreePropertyBrowserPrivate *editorPrivate)
159 { m_editorPrivate = editorPrivate; }
160
indexToItem(const QModelIndex & index) const161 QTreeWidgetItem *indexToItem(const QModelIndex &index) const
162 { return itemFromIndex(index); }
163
164 protected:
165 void keyPressEvent(QKeyEvent *event);
166 void mousePressEvent(QMouseEvent *event);
167 void drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
168
169 private:
170 QtTreePropertyBrowserPrivate *m_editorPrivate;
171 };
172
QtPropertyEditorView(QWidget * parent)173 QtPropertyEditorView::QtPropertyEditorView(QWidget *parent) :
174 QTreeWidget(parent),
175 m_editorPrivate(0)
176 {
177 setUniformRowHeights(true);
178 connect(header(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(resizeColumnToContents(int)));
179 }
180
drawRow(QPainter * painter,const QStyleOptionViewItem & option,const QModelIndex & index) const181 void QtPropertyEditorView::drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
182 {
183 QStyleOptionViewItem opt = option;
184 bool hasValue = true;
185 if (m_editorPrivate) {
186 QtProperty *property = m_editorPrivate->indexToProperty(index);
187 if (property)
188 hasValue = property->hasValue();
189 }
190 if (!hasValue && m_editorPrivate->markPropertiesWithoutValue()) {
191 const QColor c = option.palette.color(QPalette::Dark);
192 painter->fillRect(option.rect, c);
193 opt.palette.setColor(QPalette::AlternateBase, c);
194 } else {
195 const QColor c = m_editorPrivate->calculatedBackgroundColor(m_editorPrivate->indexToBrowserItem(index));
196 if (c.isValid()) {
197 painter->fillRect(option.rect, c);
198 opt.palette.setColor(QPalette::AlternateBase, c.lighter(112));
199 }
200 }
201 QTreeWidget::drawRow(painter, opt, index);
202 QColor color = static_cast<QRgb>(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &opt));
203 painter->save();
204 painter->setPen(QPen(color));
205 painter->drawLine(opt.rect.x(), opt.rect.bottom(), opt.rect.right(), opt.rect.bottom());
206 painter->restore();
207 }
208
keyPressEvent(QKeyEvent * event)209 void QtPropertyEditorView::keyPressEvent(QKeyEvent *event)
210 {
211 switch (event->key()) {
212 case Qt::Key_Return:
213 case Qt::Key_Enter:
214 case Qt::Key_Space: // Trigger Edit
215 if (!m_editorPrivate->editedItem())
216 if (const QTreeWidgetItem *item = currentItem())
217 if (item->columnCount() >= 2 && ((item->flags() & (Qt::ItemIsEditable | Qt::ItemIsEnabled)) == (Qt::ItemIsEditable | Qt::ItemIsEnabled))) {
218 event->accept();
219 // If the current position is at column 0, move to 1.
220 QModelIndex index = currentIndex();
221 if (index.column() == 0) {
222 index = index.sibling(index.row(), 1);
223 setCurrentIndex(index);
224 }
225 edit(index);
226 return;
227 }
228 break;
229 default:
230 break;
231 }
232 QTreeWidget::keyPressEvent(event);
233 }
234
mousePressEvent(QMouseEvent * event)235 void QtPropertyEditorView::mousePressEvent(QMouseEvent *event)
236 {
237 QTreeWidget::mousePressEvent(event);
238 QTreeWidgetItem *item = itemAt(event->pos());
239
240 if (item) {
241 if ((item != m_editorPrivate->editedItem()) && (event->button() == Qt::LeftButton)
242 && (header()->logicalIndexAt(event->pos().x()) == 1)
243 && ((item->flags() & (Qt::ItemIsEditable | Qt::ItemIsEnabled)) == (Qt::ItemIsEditable | Qt::ItemIsEnabled))) {
244 editItem(item, 1);
245 } else if (!m_editorPrivate->hasValue(item) && m_editorPrivate->markPropertiesWithoutValue() && !rootIsDecorated()) {
246 if (event->pos().x() + header()->offset() < 20)
247 item->setExpanded(!item->isExpanded());
248 }
249 }
250 }
251
252 // ------------ QtPropertyEditorDelegate
253 class QtPropertyEditorDelegate : public QItemDelegate
254 {
255 Q_OBJECT
256 public:
QtPropertyEditorDelegate(QObject * parent=0)257 explicit QtPropertyEditorDelegate(QObject *parent = 0)
258 : QItemDelegate(parent), m_editorPrivate(0), m_editedItem(0), m_editedWidget(0), m_disablePainting(false)
259 {}
260
setEditorPrivate(QtTreePropertyBrowserPrivate * editorPrivate)261 void setEditorPrivate(QtTreePropertyBrowserPrivate *editorPrivate)
262 { m_editorPrivate = editorPrivate; }
263
264 QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
265 const QModelIndex &index) const;
266
267 void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
268 const QModelIndex &index) const;
269
270 void paint(QPainter *painter, const QStyleOptionViewItem &option,
271 const QModelIndex &index) const;
272
273 QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
274
setModelData(QWidget *,QAbstractItemModel *,const QModelIndex &) const275 void setModelData(QWidget *, QAbstractItemModel *,
276 const QModelIndex &) const {}
277
setEditorData(QWidget *,const QModelIndex &) const278 void setEditorData(QWidget *, const QModelIndex &) const {}
279
280 bool eventFilter(QObject *object, QEvent *event);
281 void closeEditor(QtProperty *property);
282
editedItem() const283 QTreeWidgetItem *editedItem() const { return m_editedItem; }
284
285 protected:
286
287 void drawDecoration(QPainter *painter, const QStyleOptionViewItem &option,
288 const QRect &rect, const QPixmap &pixmap) const;
289 void drawDisplay(QPainter *painter, const QStyleOptionViewItem &option,
290 const QRect &rect, const QString &text) const;
291
292 private slots:
293 void slotEditorDestroyed(QObject *object);
294
295 private:
296 int indentation(const QModelIndex &index) const;
297
298 typedef QMap<QWidget *, QtProperty *> EditorToPropertyMap;
299 mutable EditorToPropertyMap m_editorToProperty;
300
301 typedef QMap<QtProperty *, QWidget *> PropertyToEditorMap;
302 mutable PropertyToEditorMap m_propertyToEditor;
303 QtTreePropertyBrowserPrivate *m_editorPrivate;
304 mutable QTreeWidgetItem *m_editedItem;
305 mutable QWidget *m_editedWidget;
306 mutable bool m_disablePainting;
307 };
308
indentation(const QModelIndex & index) const309 int QtPropertyEditorDelegate::indentation(const QModelIndex &index) const
310 {
311 if (!m_editorPrivate)
312 return 0;
313
314 QTreeWidgetItem *item = m_editorPrivate->indexToItem(index);
315 int indent = 0;
316 while (item->parent()) {
317 item = item->parent();
318 ++indent;
319 }
320 if (m_editorPrivate->treeWidget()->rootIsDecorated())
321 ++indent;
322 return indent * m_editorPrivate->treeWidget()->indentation();
323 }
324
slotEditorDestroyed(QObject * object)325 void QtPropertyEditorDelegate::slotEditorDestroyed(QObject *object)
326 {
327 if (QWidget *w = qobject_cast<QWidget *>(object)) {
328 const EditorToPropertyMap::iterator it = m_editorToProperty.find(w);
329 if (it != m_editorToProperty.end()) {
330 m_propertyToEditor.remove(it.value());
331 m_editorToProperty.erase(it);
332 }
333 if (m_editedWidget == w) {
334 m_editedWidget = 0;
335 m_editedItem = 0;
336 }
337 }
338 }
339
closeEditor(QtProperty * property)340 void QtPropertyEditorDelegate::closeEditor(QtProperty *property)
341 {
342 if (QWidget *w = m_propertyToEditor.value(property, 0))
343 w->deleteLater();
344 }
345
createEditor(QWidget * parent,const QStyleOptionViewItem &,const QModelIndex & index) const346 QWidget *QtPropertyEditorDelegate::createEditor(QWidget *parent,
347 const QStyleOptionViewItem &, const QModelIndex &index) const
348 {
349 if (index.column() == 1 && m_editorPrivate) {
350 QtProperty *property = m_editorPrivate->indexToProperty(index);
351 QTreeWidgetItem *item = m_editorPrivate->indexToItem(index);
352 if (property && item && (item->flags() & Qt::ItemIsEnabled)) {
353 QWidget *editor = m_editorPrivate->createEditor(property, parent);
354 if (editor) {
355 editor->setAutoFillBackground(true);
356 editor->installEventFilter(const_cast<QtPropertyEditorDelegate *>(this));
357 connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *)));
358 m_propertyToEditor[property] = editor;
359 m_editorToProperty[editor] = property;
360 m_editedItem = item;
361 m_editedWidget = editor;
362 }
363 return editor;
364 }
365 }
366 return 0;
367 }
368
updateEditorGeometry(QWidget * editor,const QStyleOptionViewItem & option,const QModelIndex & index) const369 void QtPropertyEditorDelegate::updateEditorGeometry(QWidget *editor,
370 const QStyleOptionViewItem &option, const QModelIndex &index) const
371 {
372 Q_UNUSED(index)
373 editor->setGeometry(option.rect.adjusted(0, 0, 0, -1));
374 }
375
paint(QPainter * painter,const QStyleOptionViewItem & option,const QModelIndex & index) const376 void QtPropertyEditorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
377 const QModelIndex &index) const
378 {
379 bool hasValue = true;
380 if (m_editorPrivate) {
381 QtProperty *property = m_editorPrivate->indexToProperty(index);
382 if (property)
383 hasValue = property->hasValue();
384 }
385 QStyleOptionViewItem opt = option;
386 if ((m_editorPrivate && index.column() == 0) || !hasValue) {
387 QtProperty *property = m_editorPrivate->indexToProperty(index);
388 if (property && property->isModified()) {
389 opt.font.setBold(true);
390 opt.fontMetrics = QFontMetrics(opt.font);
391 }
392 }
393 QColor c;
394 if (!hasValue && m_editorPrivate->markPropertiesWithoutValue()) {
395 c = opt.palette.color(QPalette::Dark);
396 opt.palette.setColor(QPalette::Text, opt.palette.color(QPalette::BrightText));
397 } else {
398 c = m_editorPrivate->calculatedBackgroundColor(m_editorPrivate->indexToBrowserItem(index));
399 if (c.isValid() && (opt.features & QStyleOptionViewItem::Alternate))
400 c = c.lighter(112);
401 }
402 if (c.isValid())
403 painter->fillRect(option.rect, c);
404 opt.state &= ~QStyle::State_HasFocus;
405 if (index.column() == 1) {
406 QTreeWidgetItem *item = m_editorPrivate->indexToItem(index);
407 if (m_editedItem && m_editedItem == item)
408 m_disablePainting = true;
409 }
410 QItemDelegate::paint(painter, opt, index);
411 if (option.type)
412 m_disablePainting = false;
413
414 opt.palette.setCurrentColorGroup(QPalette::Active);
415 QColor color = static_cast<QRgb>(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &opt));
416 painter->save();
417 painter->setPen(QPen(color));
418 if (!m_editorPrivate || (!m_editorPrivate->lastColumn(index.column()) && hasValue)) {
419 int right = (option.direction == Qt::LeftToRight) ? option.rect.right() : option.rect.left();
420 painter->drawLine(right, option.rect.y(), right, option.rect.bottom());
421 }
422 painter->restore();
423 }
424
drawDecoration(QPainter * painter,const QStyleOptionViewItem & option,const QRect & rect,const QPixmap & pixmap) const425 void QtPropertyEditorDelegate::drawDecoration(QPainter *painter, const QStyleOptionViewItem &option,
426 const QRect &rect, const QPixmap &pixmap) const
427 {
428 if (m_disablePainting)
429 return;
430
431 QItemDelegate::drawDecoration(painter, option, rect, pixmap);
432 }
433
drawDisplay(QPainter * painter,const QStyleOptionViewItem & option,const QRect & rect,const QString & text) const434 void QtPropertyEditorDelegate::drawDisplay(QPainter *painter, const QStyleOptionViewItem &option,
435 const QRect &rect, const QString &text) const
436 {
437 if (m_disablePainting)
438 return;
439
440 QItemDelegate::drawDisplay(painter, option, rect, text);
441 }
442
sizeHint(const QStyleOptionViewItem & option,const QModelIndex & index) const443 QSize QtPropertyEditorDelegate::sizeHint(const QStyleOptionViewItem &option,
444 const QModelIndex &index) const
445 {
446 return QItemDelegate::sizeHint(option, index) + dpiScaled(QSize(3, 4));
447 }
448
eventFilter(QObject * object,QEvent * event)449 bool QtPropertyEditorDelegate::eventFilter(QObject *object, QEvent *event)
450 {
451 if (event->type() == QEvent::FocusOut) {
452 QFocusEvent *fe = static_cast<QFocusEvent *>(event);
453 if (fe->reason() == Qt::ActiveWindowFocusReason)
454 return false;
455 }
456 return QItemDelegate::eventFilter(object, event);
457 }
458
459 // -------- QtTreePropertyBrowserPrivate implementation
QtTreePropertyBrowserPrivate()460 QtTreePropertyBrowserPrivate::QtTreePropertyBrowserPrivate() :
461 m_treeWidget(0),
462 m_headerVisible(true),
463 m_allowMultiSelection(false),
464 m_resizeMode(QtTreePropertyBrowser::Stretch),
465 m_delegate(0),
466 m_markPropertiesWithoutValue(false),
467 m_browserChangedBlocked(false)
468 {
469 }
470
471 // Draw an icon indicating opened/closing branches
drawIndicatorIcon(const QPalette & palette,QStyle * style)472 static QIcon drawIndicatorIcon(const QPalette &palette, QStyle *style)
473 {
474 QPixmap pix(14, 14);
475 pix.fill(Qt::transparent);
476 QStyleOption branchOption;
477 QRect r(QPoint(0, 0), pix.size());
478 branchOption.rect = QRect(2, 2, 9, 9); // ### hardcoded in qcommonstyle.cpp
479 branchOption.palette = palette;
480 branchOption.state = QStyle::State_Children;
481
482 QPainter p;
483 // Draw closed state
484 p.begin(&pix);
485 style->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, &p);
486 p.end();
487 QIcon rc = pix;
488 rc.addPixmap(pix, QIcon::Selected, QIcon::Off);
489 // Draw opened state
490 branchOption.state |= QStyle::State_Open;
491 pix.fill(Qt::transparent);
492 p.begin(&pix);
493 style->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, &p);
494 p.end();
495
496 rc.addPixmap(pix, QIcon::Normal, QIcon::On);
497 rc.addPixmap(pix, QIcon::Selected, QIcon::On);
498 return rc;
499 }
500
init(QWidget * parent)501 void QtTreePropertyBrowserPrivate::init(QWidget *parent)
502 {
503 QHBoxLayout *layout = new QHBoxLayout(parent);
504 layout->setContentsMargins(0, 0, 0, 0);
505 m_treeWidget = new QtPropertyEditorView(parent);
506 m_treeWidget->setEditorPrivate(this);
507 m_treeWidget->setIconSize(QSize(18, 18));
508 layout->addWidget(m_treeWidget);
509 parent->setFocusProxy(m_treeWidget);
510
511 m_treeWidget->setColumnCount(2);
512 QStringList labels;
513 labels.append(QCoreApplication::translate("QtTreePropertyBrowser", "Property"));
514 labels.append(QCoreApplication::translate("QtTreePropertyBrowser", "Value"));
515 m_treeWidget->setHeaderLabels(labels);
516 m_treeWidget->setAlternatingRowColors(true);
517 m_treeWidget->setEditTriggers(QAbstractItemView::EditKeyPressed);
518 m_delegate = new QtPropertyEditorDelegate(parent);
519 m_delegate->setEditorPrivate(this);
520 m_treeWidget->setItemDelegate(m_delegate);
521 #if QT_VERSION >= 0x050000
522 m_treeWidget->header()->setSectionsMovable(false);
523 m_treeWidget->header()->setSectionResizeMode(QHeaderView::Stretch);
524 #else
525 m_treeWidget->header()->setMovable(false);
526 m_treeWidget->header()->setResizeMode(QHeaderView::Stretch);
527 #endif
528
529 m_expandIcon = drawIndicatorIcon(q_ptr->palette(), q_ptr->style());
530
531 QObject::connect(m_treeWidget, SIGNAL(collapsed(const QModelIndex &)), q_ptr, SLOT(slotCollapsed(const QModelIndex &)));
532 QObject::connect(m_treeWidget, SIGNAL(expanded(const QModelIndex &)), q_ptr, SLOT(slotExpanded(const QModelIndex &)));
533 QObject::connect(m_treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), q_ptr, SLOT(slotCurrentTreeItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)));
534 QObject::connect(m_treeWidget, SIGNAL(itemSelectionChanged()), q_ptr, SLOT(slotItemSelectionChanged()));
535 }
536
currentItem() const537 QtBrowserItem *QtTreePropertyBrowserPrivate::currentItem() const
538 {
539 if (QTreeWidgetItem *treeItem = m_treeWidget->currentItem())
540 return m_itemToIndex.value(treeItem);
541 return 0;
542 }
543
setCurrentItem(QtBrowserItem * browserItem,bool block)544 void QtTreePropertyBrowserPrivate::setCurrentItem(QtBrowserItem *browserItem, bool block)
545 {
546 const bool blocked = block ? m_treeWidget->blockSignals(true) : false;
547 if (browserItem == 0)
548 m_treeWidget->setCurrentItem(0);
549 else
550 m_treeWidget->setCurrentItem(m_indexToItem.value(browserItem));
551 if (block)
552 m_treeWidget->blockSignals(blocked);
553 }
554
indexToProperty(const QModelIndex & index) const555 QtProperty *QtTreePropertyBrowserPrivate::indexToProperty(const QModelIndex &index) const
556 {
557 QTreeWidgetItem *item = m_treeWidget->indexToItem(index);
558 QtBrowserItem *idx = m_itemToIndex.value(item);
559 if (idx)
560 return idx->property();
561 return 0;
562 }
563
indexToBrowserItem(const QModelIndex & index) const564 QtBrowserItem *QtTreePropertyBrowserPrivate::indexToBrowserItem(const QModelIndex &index) const
565 {
566 QTreeWidgetItem *item = m_treeWidget->indexToItem(index);
567 return m_itemToIndex.value(item);
568 }
569
indexToItem(const QModelIndex & index) const570 QTreeWidgetItem *QtTreePropertyBrowserPrivate::indexToItem(const QModelIndex &index) const
571 {
572 return m_treeWidget->indexToItem(index);
573 }
574
lastColumn(int column) const575 bool QtTreePropertyBrowserPrivate::lastColumn(int column) const
576 {
577 return m_treeWidget->header()->visualIndex(column) == m_treeWidget->columnCount() - 1;
578 }
579
disableItem(QTreeWidgetItem * item) const580 void QtTreePropertyBrowserPrivate::disableItem(QTreeWidgetItem *item) const
581 {
582 Qt::ItemFlags flags = item->flags();
583 if (flags & Qt::ItemIsEnabled) {
584 flags &= ~Qt::ItemIsEnabled;
585 item->setFlags(flags);
586 m_delegate->closeEditor(m_itemToIndex[item]->property());
587 const int childCount = item->childCount();
588 for (int i = 0; i < childCount; i++) {
589 QTreeWidgetItem *child = item->child(i);
590 disableItem(child);
591 }
592 }
593 }
594
enableItem(QTreeWidgetItem * item) const595 void QtTreePropertyBrowserPrivate::enableItem(QTreeWidgetItem *item) const
596 {
597 Qt::ItemFlags flags = item->flags();
598 flags |= Qt::ItemIsEnabled;
599 item->setFlags(flags);
600 const int childCount = item->childCount();
601 for (int i = 0; i < childCount; i++) {
602 QTreeWidgetItem *child = item->child(i);
603 QtProperty *property = m_itemToIndex[child]->property();
604 if (property->isEnabled()) {
605 enableItem(child);
606 }
607 }
608 }
609
hasValue(QTreeWidgetItem * item) const610 bool QtTreePropertyBrowserPrivate::hasValue(QTreeWidgetItem *item) const
611 {
612 QtBrowserItem *browserItem = m_itemToIndex.value(item);
613 if (browserItem)
614 return browserItem->property()->hasValue();
615 return false;
616 }
617
propertyInserted(QtBrowserItem * index,QtBrowserItem * afterIndex)618 void QtTreePropertyBrowserPrivate::propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex)
619 {
620 QTreeWidgetItem *afterItem = m_indexToItem.value(afterIndex);
621 QTreeWidgetItem *parentItem = m_indexToItem.value(index->parent());
622
623 QTreeWidgetItem *newItem = 0;
624 if (parentItem) {
625 newItem = new QTreeWidgetItem(parentItem, afterItem);
626 } else {
627 newItem = new QTreeWidgetItem(m_treeWidget, afterItem);
628 }
629 m_itemToIndex[newItem] = index;
630 m_indexToItem[index] = newItem;
631
632 newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
633 newItem->setExpanded(true);
634
635 updateItem(newItem);
636 }
637
propertyRemoved(QtBrowserItem * index)638 void QtTreePropertyBrowserPrivate::propertyRemoved(QtBrowserItem *index)
639 {
640 QTreeWidgetItem *item = m_indexToItem.value(index);
641
642 if (m_treeWidget->currentItem() == item) {
643 m_treeWidget->setCurrentItem(0);
644 }
645
646 delete item;
647
648 m_indexToItem.remove(index);
649 m_itemToIndex.remove(item);
650 m_indexToBackgroundColor.remove(index);
651 }
652
propertyChanged(QtBrowserItem * index)653 void QtTreePropertyBrowserPrivate::propertyChanged(QtBrowserItem *index)
654 {
655 QTreeWidgetItem *item = m_indexToItem.value(index);
656
657 updateItem(item);
658 }
659
updateItem(QTreeWidgetItem * item)660 void QtTreePropertyBrowserPrivate::updateItem(QTreeWidgetItem *item)
661 {
662 QtProperty *property = m_itemToIndex[item]->property();
663
664 if (property->nameColor().isValid())
665 item->setForeground(0, QBrush(property->nameColor()));
666 if (property->valueColor().isValid())
667 item->setForeground(1, QBrush(property->valueColor()));
668
669 QIcon expandIcon;
670 if (property->hasValue()) {
671 QString toolTip = property->toolTip();
672 if (toolTip.isEmpty())
673 toolTip = property->displayText();
674 item->setToolTip(1, toolTip);
675 item->setIcon(1, property->valueIcon());
676 property->displayText().isEmpty() ? item->setText(1, property->valueText()) : item->setText(1, property->displayText());
677 } else if (markPropertiesWithoutValue() && !m_treeWidget->rootIsDecorated()) {
678 expandIcon = m_expandIcon;
679 }
680 item->setIcon(0, expandIcon);
681 item->setFirstColumnSpanned(!property->hasValue());
682 item->setToolTip(0, property->propertyName());
683 item->setStatusTip(0, property->statusTip());
684 item->setWhatsThis(0, property->whatsThis());
685 item->setText(0, property->propertyName());
686 bool wasEnabled = item->flags() & Qt::ItemIsEnabled;
687 bool isEnabled = wasEnabled;
688 if (property->isEnabled()) {
689 QTreeWidgetItem *parent = item->parent();
690 if (!parent || (parent->flags() & Qt::ItemIsEnabled))
691 isEnabled = true;
692 else
693 isEnabled = false;
694 } else {
695 isEnabled = false;
696 }
697 if (wasEnabled != isEnabled) {
698 if (isEnabled)
699 enableItem(item);
700 else
701 disableItem(item);
702 }
703 m_treeWidget->viewport()->update();
704 }
705
calculatedBackgroundColor(QtBrowserItem * item) const706 QColor QtTreePropertyBrowserPrivate::calculatedBackgroundColor(QtBrowserItem *item) const
707 {
708 QtBrowserItem *i = item;
709 const QMap<QtBrowserItem *, QColor>::const_iterator itEnd = m_indexToBackgroundColor.constEnd();
710 while (i) {
711 QMap<QtBrowserItem *, QColor>::const_iterator it = m_indexToBackgroundColor.constFind(i);
712 if (it != itEnd)
713 return it.value();
714 i = i->parent();
715 }
716 return QColor();
717 }
718
slotCollapsed(const QModelIndex & index)719 void QtTreePropertyBrowserPrivate::slotCollapsed(const QModelIndex &index)
720 {
721 QTreeWidgetItem *item = indexToItem(index);
722 QtBrowserItem *idx = m_itemToIndex.value(item);
723 if (item)
724 emit q_ptr->collapsed(idx);
725 }
726
slotExpanded(const QModelIndex & index)727 void QtTreePropertyBrowserPrivate::slotExpanded(const QModelIndex &index)
728 {
729 QTreeWidgetItem *item = indexToItem(index);
730 QtBrowserItem *idx = m_itemToIndex.value(item);
731 if (item)
732 emit q_ptr->expanded(idx);
733 }
734
slotCurrentBrowserItemChanged(QtBrowserItem * item)735 void QtTreePropertyBrowserPrivate::slotCurrentBrowserItemChanged(QtBrowserItem *item)
736 {
737 if (!m_browserChangedBlocked && item != currentItem())
738 setCurrentItem(item, true);
739 }
740
slotCurrentTreeItemChanged(QTreeWidgetItem * newItem,QTreeWidgetItem *)741 void QtTreePropertyBrowserPrivate::slotCurrentTreeItemChanged(QTreeWidgetItem *newItem, QTreeWidgetItem *)
742 {
743 QtBrowserItem *browserItem = newItem ? m_itemToIndex.value(newItem) : 0;
744 m_browserChangedBlocked = true;
745 q_ptr->setCurrentItem(browserItem);
746 m_browserChangedBlocked = false;
747 }
748
slotItemSelectionChanged()749 void QtTreePropertyBrowserPrivate::slotItemSelectionChanged()
750 {
751 emit q_ptr->selectedItemsChanged();
752 }
753
editedItem() const754 QTreeWidgetItem *QtTreePropertyBrowserPrivate::editedItem() const
755 {
756 return m_delegate->editedItem();
757 }
758
editedBrowserItem() const759 QtBrowserItem *QtTreePropertyBrowserPrivate::editedBrowserItem() const
760 {
761 return m_itemToIndex.value(editedItem());
762 }
763
editItem(QtBrowserItem * browserItem)764 void QtTreePropertyBrowserPrivate::editItem(QtBrowserItem *browserItem)
765 {
766 if (QTreeWidgetItem *treeItem = m_indexToItem.value(browserItem, 0)) {
767 m_treeWidget->setCurrentItem (treeItem, 1);
768 m_treeWidget->editItem(treeItem, 1);
769 }
770 }
771
selectedItems() const772 QList<QtBrowserItem *> QtTreePropertyBrowserPrivate::selectedItems() const
773 {
774 const QList<QTreeWidgetItem*> selectedTreeItems = m_treeWidget->selectedItems();
775 QList<QtBrowserItem*> browserItems;
776
777 for (QTreeWidgetItem *treeItem : selectedTreeItems)
778 if (QtBrowserItem *browserItem = m_itemToIndex.value(treeItem, 0))
779 browserItems.append(browserItem);
780
781 return browserItems;
782 }
783
784 /*!
785 \class QtTreePropertyBrowser
786
787 \brief The QtTreePropertyBrowser class provides QTreeWidget based
788 property browser.
789
790 A property browser is a widget that enables the user to edit a
791 given set of properties. Each property is represented by a label
792 specifying the property's name, and an editing widget (e.g. a line
793 edit or a combobox) holding its value. A property can have zero or
794 more subproperties.
795
796 QtTreePropertyBrowser provides a tree based view for all nested
797 properties, i.e. properties that have subproperties can be in an
798 expanded (subproperties are visible) or collapsed (subproperties
799 are hidden) state. For example:
800
801 \image qttreepropertybrowser.png
802
803 Use the QtAbstractPropertyBrowser API to add, insert and remove
804 properties from an instance of the QtTreePropertyBrowser class.
805 The properties themselves are created and managed by
806 implementations of the QtAbstractPropertyManager class.
807
808 \sa QtGroupBoxPropertyBrowser, QtAbstractPropertyBrowser
809 */
810
811 /*!
812 \fn void QtTreePropertyBrowser::collapsed(QtBrowserItem *item)
813
814 This signal is emitted when the \a item is collapsed.
815
816 \sa expanded(), setExpanded()
817 */
818
819 /*!
820 \fn void QtTreePropertyBrowser::expanded(QtBrowserItem *item)
821
822 This signal is emitted when the \a item is expanded.
823
824 \sa collapsed(), setExpanded()
825 */
826
827 /*!
828 Creates a property browser with the given \a parent.
829 */
QtTreePropertyBrowser(QWidget * parent)830 QtTreePropertyBrowser::QtTreePropertyBrowser(QWidget *parent)
831 : QtAbstractPropertyBrowser(parent)
832 {
833 d_ptr = new QtTreePropertyBrowserPrivate;
834 d_ptr->q_ptr = this;
835
836 d_ptr->init(this);
837 connect(this, SIGNAL(currentItemChanged(QtBrowserItem*)), this, SLOT(slotCurrentBrowserItemChanged(QtBrowserItem*)));
838 }
839
840 /*!
841 Destroys this property browser.
842
843 Note that the properties that were inserted into this browser are
844 \e not destroyed since they may still be used in other
845 browsers. The properties are owned by the manager that created
846 them.
847
848 \sa QtProperty, QtAbstractPropertyManager
849 */
~QtTreePropertyBrowser()850 QtTreePropertyBrowser::~QtTreePropertyBrowser()
851 {
852 delete d_ptr;
853 }
854
855 /*!
856 \property QtTreePropertyBrowser::indentation
857 \brief indentation of the items in the tree view.
858 */
indentation() const859 int QtTreePropertyBrowser::indentation() const
860 {
861 return d_ptr->m_treeWidget->indentation();
862 }
863
setIndentation(int i)864 void QtTreePropertyBrowser::setIndentation(int i)
865 {
866 d_ptr->m_treeWidget->setIndentation(i);
867 }
868
869 /*!
870 \property QtTreePropertyBrowser::rootIsDecorated
871 \brief whether to show controls for expanding and collapsing root items.
872 */
rootIsDecorated() const873 bool QtTreePropertyBrowser::rootIsDecorated() const
874 {
875 return d_ptr->m_treeWidget->rootIsDecorated();
876 }
877
setRootIsDecorated(bool show)878 void QtTreePropertyBrowser::setRootIsDecorated(bool show)
879 {
880 d_ptr->m_treeWidget->setRootIsDecorated(show);
881 QMapIterator<QTreeWidgetItem *, QtBrowserItem *> it(d_ptr->m_itemToIndex);
882 while (it.hasNext()) {
883 QtProperty *property = it.next().value()->property();
884 if (!property->hasValue())
885 d_ptr->updateItem(it.key());
886 }
887 }
888
889 /*!
890 \property QtTreePropertyBrowser::alternatingRowColors
891 \brief whether to draw the background using alternating colors.
892 By default this property is set to true.
893 */
alternatingRowColors() const894 bool QtTreePropertyBrowser::alternatingRowColors() const
895 {
896 return d_ptr->m_treeWidget->alternatingRowColors();
897 }
898
setAlternatingRowColors(bool enable)899 void QtTreePropertyBrowser::setAlternatingRowColors(bool enable)
900 {
901 d_ptr->m_treeWidget->setAlternatingRowColors(enable);
902 QMapIterator<QTreeWidgetItem *, QtBrowserItem *> it(d_ptr->m_itemToIndex);
903 }
904
905 /*!
906 \property QtTreePropertyBrowser::headerVisible
907 \brief whether to show the header.
908 */
isHeaderVisible() const909 bool QtTreePropertyBrowser::isHeaderVisible() const
910 {
911 return d_ptr->m_headerVisible;
912 }
913
setHeaderVisible(bool visible)914 void QtTreePropertyBrowser::setHeaderVisible(bool visible)
915 {
916 if (d_ptr->m_headerVisible == visible)
917 return;
918
919 d_ptr->m_headerVisible = visible;
920 d_ptr->m_treeWidget->header()->setVisible(visible);
921 }
922
923 /*!
924 \property QtTreePropertyBrowser::allowMultiSelection
925 \brief whether to allow multiple selection items.
926 */
allowMultiSelection() const927 bool QtTreePropertyBrowser::allowMultiSelection() const
928 {
929 return d_ptr->m_allowMultiSelection;
930 }
931
setAllowMultiSelection(bool multiSelection)932 void QtTreePropertyBrowser::setAllowMultiSelection(bool multiSelection)
933 {
934 if (d_ptr->m_allowMultiSelection == multiSelection)
935 return;
936
937 d_ptr->m_allowMultiSelection = multiSelection;
938 d_ptr->m_treeWidget->setSelectionMode(multiSelection ? QAbstractItemView::ExtendedSelection
939 : QAbstractItemView::SingleSelection);
940 }
941
942 /*!
943 \enum QtTreePropertyBrowser::ResizeMode
944
945 The resize mode specifies the behavior of the header sections.
946
947 \value Interactive The user can resize the sections.
948 The sections can also be resized programmatically using setSplitterPosition().
949
950 \value Fixed The user cannot resize the section.
951 The section can only be resized programmatically using setSplitterPosition().
952
953 \value Stretch QHeaderView will automatically resize the section to fill the available space.
954 The size cannot be changed by the user or programmatically.
955
956 \value ResizeToContents QHeaderView will automatically resize the section to its optimal
957 size based on the contents of the entire column.
958 The size cannot be changed by the user or programmatically.
959
960 \sa setResizeMode()
961 */
962
963 /*!
964 \property QtTreePropertyBrowser::resizeMode
965 \brief the resize mode of setions in the header.
966 */
967
resizeMode() const968 QtTreePropertyBrowser::ResizeMode QtTreePropertyBrowser::resizeMode() const
969 {
970 return d_ptr->m_resizeMode;
971 }
972
setResizeMode(QtTreePropertyBrowser::ResizeMode mode)973 void QtTreePropertyBrowser::setResizeMode(QtTreePropertyBrowser::ResizeMode mode)
974 {
975 if (d_ptr->m_resizeMode == mode)
976 return;
977
978 d_ptr->m_resizeMode = mode;
979 QHeaderView::ResizeMode m = QHeaderView::Stretch;
980 switch (mode) {
981 case QtTreePropertyBrowser::Interactive: m = QHeaderView::Interactive; break;
982 case QtTreePropertyBrowser::Fixed: m = QHeaderView::Fixed; break;
983 case QtTreePropertyBrowser::ResizeToContents: m = QHeaderView::ResizeToContents; break;
984 case QtTreePropertyBrowser::Stretch:
985 default: m = QHeaderView::Stretch; break;
986 }
987 #if QT_VERSION >= 0x050000
988 d_ptr->m_treeWidget->header()->setSectionResizeMode(m);
989 #else
990 d_ptr->m_treeWidget->header()->setResizeMode(m);
991 #endif
992 }
993
994 /*!
995 \property QtTreePropertyBrowser::splitterPosition
996 \brief the position of the splitter between the colunms.
997 */
998
splitterPosition() const999 int QtTreePropertyBrowser::splitterPosition() const
1000 {
1001 return d_ptr->m_treeWidget->header()->sectionSize(0);
1002 }
1003
setSplitterPosition(int position)1004 void QtTreePropertyBrowser::setSplitterPosition(int position)
1005 {
1006 d_ptr->m_treeWidget->header()->resizeSection(0, position);
1007 }
1008
1009 /*!
1010 Sets the \a item to either collapse or expanded, depending on the value of \a expanded.
1011
1012 \sa isExpanded(), expanded(), collapsed()
1013 */
1014
setExpanded(QtBrowserItem * item,bool expanded)1015 void QtTreePropertyBrowser::setExpanded(QtBrowserItem *item, bool expanded)
1016 {
1017 QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item);
1018 if (treeItem)
1019 treeItem->setExpanded(expanded);
1020 }
1021
1022 /*!
1023 Returns true if the \a item is expanded; otherwise returns false.
1024
1025 \sa setExpanded()
1026 */
1027
isExpanded(QtBrowserItem * item) const1028 bool QtTreePropertyBrowser::isExpanded(QtBrowserItem *item) const
1029 {
1030 QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item);
1031 if (treeItem)
1032 return treeItem->isExpanded();
1033 return false;
1034 }
1035
1036 /*!
1037 Returns true if the \a item is visible; otherwise returns false.
1038
1039 \sa setItemVisible()
1040 \since 4.5
1041 */
1042
isItemVisible(QtBrowserItem * item) const1043 bool QtTreePropertyBrowser::isItemVisible(QtBrowserItem *item) const
1044 {
1045 if (const QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item))
1046 return !treeItem->isHidden();
1047 return false;
1048 }
1049
1050 /*!
1051 Sets the \a item to be visible, depending on the value of \a visible.
1052
1053 \sa isItemVisible()
1054 \since 4.5
1055 */
1056
setItemVisible(QtBrowserItem * item,bool visible)1057 void QtTreePropertyBrowser::setItemVisible(QtBrowserItem *item, bool visible)
1058 {
1059 if (QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item))
1060 treeItem->setHidden(!visible);
1061 }
1062
1063 /*!
1064 Sets the \a item's background color to \a color. Note that while item's background
1065 is rendered every second row is being drawn with alternate color (which is a bit lighter than items \a color)
1066
1067 \sa backgroundColor(), calculatedBackgroundColor()
1068 */
1069
setBackgroundColor(QtBrowserItem * item,const QColor & color)1070 void QtTreePropertyBrowser::setBackgroundColor(QtBrowserItem *item, const QColor &color)
1071 {
1072 if (!d_ptr->m_indexToItem.contains(item))
1073 return;
1074 if (color.isValid())
1075 d_ptr->m_indexToBackgroundColor[item] = color;
1076 else
1077 d_ptr->m_indexToBackgroundColor.remove(item);
1078 d_ptr->m_treeWidget->viewport()->update();
1079 }
1080
1081 /*!
1082 Returns the \a item's color. If there is no color set for item it returns invalid color.
1083
1084 \sa calculatedBackgroundColor(), setBackgroundColor()
1085 */
1086
backgroundColor(QtBrowserItem * item) const1087 QColor QtTreePropertyBrowser::backgroundColor(QtBrowserItem *item) const
1088 {
1089 return d_ptr->m_indexToBackgroundColor.value(item);
1090 }
1091
1092 /*!
1093 Returns the \a item's color. If there is no color set for item it returns parent \a item's
1094 color (if there is no color set for parent it returns grandparent's color and so on). In case
1095 the color is not set for \a item and it's top level item it returns invalid color.
1096
1097 \sa backgroundColor(), setBackgroundColor()
1098 */
1099
calculatedBackgroundColor(QtBrowserItem * item) const1100 QColor QtTreePropertyBrowser::calculatedBackgroundColor(QtBrowserItem *item) const
1101 {
1102 return d_ptr->calculatedBackgroundColor(item);
1103 }
1104
1105 /*!
1106 \property QtTreePropertyBrowser::propertiesWithoutValueMarked
1107 \brief whether to enable or disable marking properties without value.
1108
1109 When marking is enabled the item's background is rendered in dark color and item's
1110 foreground is rendered with light color.
1111
1112 \sa propertiesWithoutValueMarked()
1113 */
setPropertiesWithoutValueMarked(bool mark)1114 void QtTreePropertyBrowser::setPropertiesWithoutValueMarked(bool mark)
1115 {
1116 if (d_ptr->m_markPropertiesWithoutValue == mark)
1117 return;
1118
1119 d_ptr->m_markPropertiesWithoutValue = mark;
1120 QMapIterator<QTreeWidgetItem *, QtBrowserItem *> it(d_ptr->m_itemToIndex);
1121 while (it.hasNext()) {
1122 QtProperty *property = it.next().value()->property();
1123 if (!property->hasValue())
1124 d_ptr->updateItem(it.key());
1125 }
1126 d_ptr->m_treeWidget->viewport()->update();
1127 }
1128
propertiesWithoutValueMarked() const1129 bool QtTreePropertyBrowser::propertiesWithoutValueMarked() const
1130 {
1131 return d_ptr->m_markPropertiesWithoutValue;
1132 }
1133
1134 /*!
1135 \reimp
1136 */
itemInserted(QtBrowserItem * item,QtBrowserItem * afterItem)1137 void QtTreePropertyBrowser::itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem)
1138 {
1139 d_ptr->propertyInserted(item, afterItem);
1140 }
1141
1142 /*!
1143 \reimp
1144 */
itemRemoved(QtBrowserItem * item)1145 void QtTreePropertyBrowser::itemRemoved(QtBrowserItem *item)
1146 {
1147 d_ptr->propertyRemoved(item);
1148 }
1149
1150 /*!
1151 \reimp
1152 */
itemChanged(QtBrowserItem * item)1153 void QtTreePropertyBrowser::itemChanged(QtBrowserItem *item)
1154 {
1155 d_ptr->propertyChanged(item);
1156 }
1157
1158 /*!
1159 Sets the current item to \a item and opens the relevant editor for it.
1160 */
editItem(QtBrowserItem * item)1161 void QtTreePropertyBrowser::editItem(QtBrowserItem *item)
1162 {
1163 d_ptr->editItem(item);
1164 }
1165
1166 /*!
1167 Returns the current item being edited, if any.
1168 */
editedItem() const1169 QtBrowserItem *QtTreePropertyBrowser::editedItem() const
1170 {
1171 return d_ptr->editedBrowserItem();
1172 }
1173
1174 /*!
1175 Returns the selected items.
1176
1177 \sa setAllowMultiSelection()
1178 */
selectedItems() const1179 QList<QtBrowserItem *> QtTreePropertyBrowser::selectedItems() const
1180 {
1181 return d_ptr->selectedItems();
1182 }
1183
1184 #if QT_VERSION >= 0x040400
1185 QT_END_NAMESPACE
1186 #endif
1187
1188 #include "moc_qttreepropertybrowser.cpp"
1189 #include "qttreepropertybrowser.moc"
1190