From d760f39d5c7ec3a74f463abff5224fe741a1b19c Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Wed, 30 May 2018 22:00:08 +0200 Subject: [PATCH] QTreeWidget: Keep items hidden even if their parents are reparented When an item is explicitly hidden, then it should stay that way even if its parent is reparented. The item itself needs to be explicitly shown for it to be made visible. Task-number: QTBUG-54843 Change-Id: I0c6eea9a936f82d5874e3246292bd16365440411 Reviewed-by: Christian Ehrlicher Reviewed-by: Richard Moe Gustavsen --- src/widgets/itemviews/qtreewidget.cpp | 39 ++++++++++++++++++- src/widgets/itemviews/qtreewidget.h | 10 +---- src/widgets/itemviews/qtreewidget_p.h | 5 ++- .../itemviews/qtreewidget/tst_qtreewidget.cpp | 30 ++++++++++++++ 4 files changed, 74 insertions(+), 10 deletions(-) diff --git a/src/widgets/itemviews/qtreewidget.cpp b/src/widgets/itemviews/qtreewidget.cpp index 2578fa0958..d0728b1af2 100644 --- a/src/widgets/itemviews/qtreewidget.cpp +++ b/src/widgets/itemviews/qtreewidget.cpp @@ -1001,7 +1001,6 @@ void QTreeModel::timerEvent(QTimerEvent *ev) */ /*! - \fn void QTreeWidgetItem::setHidden(bool hide) \since 4.2 Hides the item if \a hide is true, otherwise shows the item. @@ -1012,6 +1011,14 @@ void QTreeModel::timerEvent(QTimerEvent *ev) \sa isHidden() */ +void QTreeWidgetItem::setHidden(bool ahide) +{ + if (view) { + view->setItemHidden(this, ahide); + d->hidden = ahide; + } +} + /*! \fn bool QTreeWidgetItem::isHidden() const \since 4.2 @@ -1021,6 +1028,11 @@ void QTreeModel::timerEvent(QTimerEvent *ev) \sa setHidden() */ +bool QTreeWidgetItem::isHidden() const +{ + return (view ? d->hidden : false); +} + /*! \fn void QTreeWidgetItem::setExpanded(bool expand) \since 4.2 @@ -1648,6 +1660,25 @@ void QTreeWidgetItem::setFlags(Qt::ItemFlags flags) itemChanged(); } +void QTreeWidgetItemPrivate::updateHiddenStatus(QTreeWidgetItem *item, bool inserting) +{ + QTreeModel *model = (item->view ? qobject_cast(item->view->model()) : 0); + if (!model) + return; + QStack parents; + parents.push(item); + while (!parents.isEmpty()) { + QTreeWidgetItem *parent = parents.pop(); + QModelIndex index = model->index(parent, 0); + if (parent->d->hidden) + item->view->setRowHidden(index.row(), index.parent(), inserting); + for (int i = 0; i < parent->children.count(); ++i) { + QTreeWidgetItem *child = parent->children.at(i); + parents.push(child); + } + } +} + void QTreeWidgetItemPrivate::propagateDisabled(QTreeWidgetItem *item) { Q_ASSERT(item); @@ -1937,6 +1968,7 @@ void QTreeWidgetItem::insertChild(int index, QTreeWidgetItem *child) stack.push(i->children.at(c)); } children.insert(index, child); + d->updateHiddenStatus(child, true); model->endInsertItems(); model->skipPendingSort = wasSkipSort; } else { @@ -1974,6 +2006,7 @@ QTreeWidgetItem *QTreeWidgetItem::takeChild(int index) } if (index >= 0 && index < children.count()) { if (model) model->beginRemoveItems(this, index, 1); + d->updateHiddenStatus(children.at(index), false); QTreeWidgetItem *item = children.takeAt(index); item->par = 0; QStack stack; @@ -2052,6 +2085,7 @@ void QTreeWidgetItem::insertChildren(int index, const QList &c this->children.insert(index + n, child); if (child->par) d->propagateDisabled(child); + d->updateHiddenStatus(child, true); } if (model) model->endInsertItems(); } @@ -3099,6 +3133,8 @@ bool QTreeWidget::isItemHidden(const QTreeWidgetItem *item) const */ void QTreeWidget::setItemHidden(const QTreeWidgetItem *item, bool hide) { + if (!item) + return; Q_D(QTreeWidget); if (item == d->treeModel()->headerItem) { header()->setHidden(hide); @@ -3106,6 +3142,7 @@ void QTreeWidget::setItemHidden(const QTreeWidgetItem *item, bool hide) const QModelIndex index = d->index(item); setRowHidden(index.row(), index.parent(), hide); } + item->d->hidden = hide; } /*! diff --git a/src/widgets/itemviews/qtreewidget.h b/src/widgets/itemviews/qtreewidget.h index 24919c411d..975f208702 100644 --- a/src/widgets/itemviews/qtreewidget.h +++ b/src/widgets/itemviews/qtreewidget.h @@ -82,8 +82,8 @@ public: inline void setSelected(bool select); inline bool isSelected() const; - inline void setHidden(bool hide); - inline bool isHidden() const; + void setHidden(bool hide); + bool isHidden() const; inline void setExpanded(bool expand); inline bool isExpanded() const; @@ -410,12 +410,6 @@ inline void QTreeWidgetItem::setSelected(bool aselect) inline bool QTreeWidgetItem::isSelected() const { return (view ? view->isItemSelected(this) : false); } -inline void QTreeWidgetItem::setHidden(bool ahide) -{ if (view) view->setItemHidden(this, ahide); } - -inline bool QTreeWidgetItem::isHidden() const -{ return (view ? view->isItemHidden(this) : false); } - inline void QTreeWidgetItem::setExpanded(bool aexpand) { if (view) view->setItemExpanded(this, aexpand); } diff --git a/src/widgets/itemviews/qtreewidget_p.h b/src/widgets/itemviews/qtreewidget_p.h index 7bc8af8fbd..adc2c2c421 100644 --- a/src/widgets/itemviews/qtreewidget_p.h +++ b/src/widgets/itemviews/qtreewidget_p.h @@ -187,13 +187,16 @@ class QTreeWidgetItemPrivate { public: QTreeWidgetItemPrivate(QTreeWidgetItem *item) - : q(item), disabled(false), selected(false), rowGuess(-1), policy(QTreeWidgetItem::DontShowIndicatorWhenChildless) {} + : q(item), disabled(false), selected(false), hidden(false), rowGuess(-1), + policy(QTreeWidgetItem::DontShowIndicatorWhenChildless) {} void propagateDisabled(QTreeWidgetItem *item); + void updateHiddenStatus(QTreeWidgetItem *item, bool inserting); void sortChildren(int column, Qt::SortOrder order, bool climb); QTreeWidgetItem *q; QVariantList display; uint disabled : 1; uint selected : 1; + uint hidden : 1; int rowGuess; QTreeWidgetItem::ChildIndicatorPolicy policy; }; diff --git a/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp index 1f438f59eb..db1b0d426a 100644 --- a/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp +++ b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp @@ -160,6 +160,7 @@ private slots: void task20345_sortChildren(); void getMimeDataWithInvalidItem(); void testVisualItemRect(); + void reparentHiddenItem(); public slots: void itemSelectionChanged(); @@ -3498,5 +3499,34 @@ void tst_QTreeWidget::testVisualItemRect() QCOMPARE(r.width(), sectionSize); } +void tst_QTreeWidget::reparentHiddenItem() +{ + QTreeWidgetItem *parent = new QTreeWidgetItem(testWidget); + parent->setText(0, "parent"); + QTreeWidgetItem *otherParent = new QTreeWidgetItem(testWidget); + otherParent->setText(0, "other parent"); + QTreeWidgetItem *child = new QTreeWidgetItem(parent); + child->setText(0, "child"); + QTreeWidgetItem *grandChild = new QTreeWidgetItem(child); + grandChild->setText(0, "grandchild"); + QVERIFY(child->parent()); + QVERIFY(grandChild->parent()); + + testWidget->expandItem(parent); + testWidget->expandItem(otherParent); + testWidget->expandItem(child); + + QVERIFY(!parent->isHidden()); + QVERIFY(!child->isHidden()); + QVERIFY(!grandChild->isHidden()); + + grandChild->setHidden(true); + + QVERIFY(grandChild->isHidden()); + parent->removeChild(child); + otherParent->addChild(child); + QVERIFY(grandChild->isHidden()); +} + QTEST_MAIN(tst_QTreeWidget) #include "tst_qtreewidget.moc"