File indexing completed on 2024-12-22 04:40:11
0001 /* 0002 SPDX-FileCopyrightText: 2007-2009 Sergio Pistone <sergio_pistone@yahoo.com.ar> 0003 SPDX-FileCopyrightText: 2010-2022 Mladen Milinkovic <max@smoothware.net> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "treeview.h" 0009 0010 #include <QTimer> 0011 #include <QScrollBar> 0012 0013 TreeView::TreeView(QWidget *parent) : 0014 QTreeView(parent), 0015 m_updateGeometriesTimer(new QTimer(this)), 0016 m_currentModelRows(-1), 0017 m_instantGeometryUpdate(0) 0018 { 0019 // NOTE: The updateGeometries() methods takes forever to execute (around 100ms 0020 // for a view with more that 1 thousand items, and more as more items are added). 0021 // The culprit is the updateGeometries() method in QHeaderView which takes a lot 0022 // of time when there are columns with ResizeToContents mode set. 0023 // To workaround this, we reimplement the updateGeometries method to (re)start a 0024 // timer that invoques the real work only on timeout (reported as BUG 234368 at Qt). 0025 // To further refine our hack, we only delay the geometries update when the model's 0026 // "has rows" (imaginary) property hasn't changed since last geometries update. 0027 // This works very well in our case because the columns with ResizeToContents enabled 0028 // have items of the same size and so their geometries only change with "has rows" state. 0029 0030 m_updateGeometriesTimer->setInterval(200); 0031 m_updateGeometriesTimer->setSingleShot(true); 0032 0033 connect(m_updateGeometriesTimer, &QTimer::timeout, this, &TreeView::onUpdateGeometriesTimeout); 0034 } 0035 0036 TreeView::~TreeView() 0037 {} 0038 0039 void 0040 TreeView::setModel(QAbstractItemModel *newModel) 0041 { 0042 if(model()) { 0043 disconnect(model(), &QAbstractItemModel::dataChanged, viewport(), QOverload<>::of(&QWidget::update)); 0044 disconnect(model(), &QAbstractItemModel::rowsAboutToBeInserted, this, &TreeView::onRowsAboutToBeInserted); 0045 disconnect(model(), &QAbstractItemModel::rowsAboutToBeRemoved, this, &TreeView::onRowsAboutToBeRemoved); 0046 } 0047 0048 QTreeView::setModel(newModel); 0049 0050 if(newModel) { 0051 m_currentModelRows = newModel->rowCount(); 0052 connect(newModel, &QAbstractItemModel::dataChanged, viewport(), QOverload<>::of(&QWidget::update)); 0053 connect(newModel, &QAbstractItemModel::rowsAboutToBeInserted, this, &TreeView::onRowsAboutToBeInserted); 0054 connect(newModel, &QAbstractItemModel::rowsAboutToBeRemoved, this, &TreeView::onRowsAboutToBeRemoved); 0055 } else { 0056 m_currentModelRows = -1; 0057 } 0058 } 0059 0060 void 0061 TreeView::onRowsAboutToBeInserted(const QModelIndex &parent, int start, int end) 0062 { 0063 if(!parent.isValid()) { 0064 m_instantGeometryUpdate = m_currentModelRows == 0 ? 1 : 0; 0065 m_currentModelRows += end - start + 1; 0066 } 0067 } 0068 0069 void 0070 TreeView::onRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) 0071 { 0072 if(!parent.isValid()) { 0073 m_currentModelRows -= end - start + 1; 0074 m_instantGeometryUpdate = m_currentModelRows == 0 ? 1 : 0; 0075 } 0076 } 0077 0078 void 0079 TreeView::updateGeometries() 0080 { 0081 if(m_instantGeometryUpdate--) 0082 QTreeView::updateGeometries(); 0083 else 0084 m_updateGeometriesTimer->start(); 0085 } 0086 0087 void 0088 TreeView::onUpdateGeometriesTimeout() 0089 { 0090 QTreeView::updateGeometries(); 0091 } 0092 0093