File indexing completed on 2025-01-19 03:59:42
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2007-11-15 0007 * Description : widget item delegate for setup collection view 0008 * 0009 * SPDX-FileCopyrightText: 2015-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * SPDX-FileCopyrightText: 2007-2008 by Rafael Fernández López <ereslibre at kde dot org> 0011 * SPDX-FileCopyrightText: 2008 by Kevin Ottens <ervin at kde dot org> 0012 * 0013 * SPDX-License-Identifier: GPL-2.0-or-later 0014 * 0015 * ============================================================ */ 0016 0017 #include "dwitemdelegate_p.h" 0018 0019 // Qt includes 0020 0021 #include <QSize> 0022 #include <QStyle> 0023 #include <QEvent> 0024 #include <QTimer> 0025 #include <QTreeView> 0026 #include <QApplication> 0027 #include <QStyleOption> 0028 #include <QAbstractItemView> 0029 0030 // Local includes 0031 0032 #include "dwitemdelegatepool.h" 0033 0034 namespace Digikam 0035 { 0036 0037 DWItemDelegatePrivate::DWItemDelegatePrivate(DWItemDelegate* const q, QObject* const parent) 0038 : QObject (parent), 0039 itemView (nullptr), 0040 widgetPool (new DWItemDelegatePool(q)), 0041 model (nullptr), 0042 selectionModel(nullptr), 0043 q (q) 0044 { 0045 } 0046 0047 DWItemDelegatePrivate::~DWItemDelegatePrivate() 0048 { 0049 delete widgetPool; 0050 } 0051 0052 void DWItemDelegatePrivate::slotDWRowsInserted(const QModelIndex& parent, int start, int end) 0053 { 0054 Q_UNUSED(end); 0055 0056 // We need to update the rows behind the inserted row as well because the widgets need to be 0057 // moved to their new position 0058 0059 updateRowRange(parent, start, model->rowCount(parent), false); 0060 } 0061 0062 void DWItemDelegatePrivate::slotDWRowsAboutToBeRemoved(const QModelIndex& parent, int start, int end) 0063 { 0064 updateRowRange(parent, start, end, true); 0065 } 0066 0067 void DWItemDelegatePrivate::slotDWRowsRemoved(const QModelIndex& parent, int start, int end) 0068 { 0069 Q_UNUSED(end); 0070 0071 // We need to update the rows that come behind the deleted rows because the widgets need to be 0072 // moved to the new position 0073 0074 updateRowRange(parent, start, model->rowCount(parent), false); 0075 } 0076 0077 void DWItemDelegatePrivate::slotDWDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight) 0078 { 0079 for (int i = topLeft.row() ; i <= bottomRight.row() ; ++i) 0080 { 0081 for (int j = topLeft.column() ; j <= bottomRight.column() ; ++j) 0082 { 0083 const QModelIndex index = model->index(i, j, topLeft.parent()); 0084 widgetPool->findWidgets(index, optionView(index)); 0085 } 0086 } 0087 } 0088 0089 void DWItemDelegatePrivate::slotDWLayoutChanged() 0090 { 0091 Q_FOREACH (QWidget* const widget, widgetPool->invalidIndexesWidgets()) 0092 { 0093 widget->setVisible(false); 0094 } 0095 0096 QTimer::singleShot(0, this, SLOT(initializeModel())); 0097 } 0098 0099 void DWItemDelegatePrivate::slotDWModelReset() 0100 { 0101 widgetPool->fullClear(); 0102 QTimer::singleShot(0, this, SLOT(initializeModel())); 0103 } 0104 0105 void DWItemDelegatePrivate::slotDWSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected) 0106 { 0107 Q_FOREACH (const QModelIndex& index, selected.indexes()) 0108 { 0109 widgetPool->findWidgets(index, optionView(index)); 0110 } 0111 0112 Q_FOREACH (const QModelIndex& index, deselected.indexes()) 0113 { 0114 widgetPool->findWidgets(index, optionView(index)); 0115 } 0116 } 0117 0118 void DWItemDelegatePrivate::updateRowRange(const QModelIndex& parent, int start, int end, bool isRemoving) 0119 { 0120 int i = start; 0121 0122 while (i <= end) 0123 { 0124 for (int j = 0 ; j < model->columnCount(parent) ; ++j) 0125 { 0126 const QModelIndex index = model->index(i, j, parent); 0127 QList<QWidget*> widgetList = widgetPool->findWidgets(index, optionView(index), isRemoving ? DWItemDelegatePool::NotUpdateWidgets 0128 : DWItemDelegatePool::UpdateWidgets); 0129 if (isRemoving) 0130 { 0131 Q_FOREACH (QWidget* const widget, widgetList) 0132 { 0133 const QModelIndex idx = widgetPool->d->widgetInIndex[widget]; 0134 widgetPool->d->usedWidgets.remove(idx); 0135 widgetPool->d->widgetInIndex.remove(widget); 0136 delete widget; 0137 } 0138 } 0139 } 0140 0141 i++; 0142 } 0143 } 0144 0145 inline QStyleOptionViewItem DWItemDelegatePrivate::optionView(const QModelIndex& index) 0146 { 0147 QStyleOptionViewItem optionView; 0148 optionView.initFrom(itemView->viewport()); 0149 optionView.rect = itemView->visualRect(index); 0150 optionView.decorationSize = itemView->iconSize(); 0151 0152 return optionView; 0153 } 0154 0155 void DWItemDelegatePrivate::initializeModel(const QModelIndex& parent) 0156 { 0157 if (!model) 0158 { 0159 return; 0160 } 0161 0162 for (int i = 0 ; i < model->rowCount(parent) ; ++i) 0163 { 0164 for (int j = 0 ; j < model->columnCount(parent) ; ++j) 0165 { 0166 const QModelIndex index = model->index(i, j, parent); 0167 0168 if (index.isValid()) 0169 { 0170 widgetPool->findWidgets(index, optionView(index)); 0171 } 0172 } 0173 0174 // Check if we need to go recursively through the children of parent (if any) to initialize 0175 // all possible indexes that are shown. 0176 0177 const QModelIndex index = model->index(i, 0, parent); 0178 0179 if (index.isValid() && model->hasChildren(index)) 0180 { 0181 initializeModel(index); 0182 } 0183 } 0184 } 0185 0186 bool DWItemDelegatePrivate::eventFilter(QObject* watched, QEvent* event) 0187 { 0188 Q_ASSERT(itemView); 0189 0190 if (model != itemView->model()) 0191 { 0192 if (model) 0193 { 0194 disconnect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), 0195 q, SLOT(slotDWRowsInserted(QModelIndex,int,int))); 0196 0197 disconnect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), 0198 q, SLOT(slotDWRowsAboutToBeRemoved(QModelIndex,int,int))); 0199 0200 disconnect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), 0201 q, SLOT(slotDWRowsRemoved(QModelIndex,int,int))); 0202 0203 disconnect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), 0204 q, SLOT(slotDWDataChanged(QModelIndex,QModelIndex))); 0205 0206 disconnect(model, SIGNAL(layoutChanged()), 0207 q, SLOT(slotDWLayoutChanged())); 0208 0209 disconnect(model, SIGNAL(modelReset()), 0210 q, SLOT(slotDWModelReset())); 0211 } 0212 0213 model = itemView->model(); 0214 0215 connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), 0216 q, SLOT(slotDWRowsInserted(QModelIndex,int,int))); 0217 0218 connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), 0219 q, SLOT(slotDWRowsAboutToBeRemoved(QModelIndex,int,int))); 0220 0221 connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), 0222 q, SLOT(slotDWRowsRemoved(QModelIndex,int,int))); 0223 0224 connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), 0225 q, SLOT(slotDWDataChanged(QModelIndex,QModelIndex))); 0226 0227 connect(model, SIGNAL(layoutChanged()), 0228 q, SLOT(slotDWLayoutChanged())); 0229 0230 connect(model, SIGNAL(modelReset()), 0231 q, SLOT(slotDWModelReset())); 0232 0233 QTimer::singleShot(0, this, SLOT(initializeModel())); 0234 } 0235 0236 if (selectionModel != itemView->selectionModel()) 0237 { 0238 if (selectionModel) 0239 { 0240 disconnect(selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), 0241 q, SLOT(slotDWSelectionChanged(QItemSelection,QItemSelection))); 0242 } 0243 0244 selectionModel = itemView->selectionModel(); 0245 0246 connect(selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), 0247 q, SLOT(slotDWSelectionChanged(QItemSelection,QItemSelection))); 0248 0249 QTimer::singleShot(0, this, SLOT(initializeModel())); 0250 } 0251 0252 switch (event->type()) 0253 { 0254 case QEvent::Polish: 0255 case QEvent::Resize: 0256 { 0257 if (!qobject_cast<QAbstractItemView*>(watched)) 0258 { 0259 QTimer::singleShot(0, this, SLOT(initializeModel())); 0260 } 0261 0262 break; 0263 } 0264 0265 case QEvent::FocusIn: 0266 case QEvent::FocusOut: 0267 { 0268 if (qobject_cast<QAbstractItemView*>(watched)) 0269 { 0270 Q_FOREACH (const QModelIndex& index, selectionModel->selectedIndexes()) 0271 { 0272 if (index.isValid()) 0273 { 0274 widgetPool->findWidgets(index, optionView(index)); 0275 } 0276 } 0277 } 0278 0279 break; 0280 } 0281 0282 default: 0283 { 0284 break; 0285 } 0286 } 0287 0288 return QObject::eventFilter(watched, event); 0289 } 0290 0291 } // namespace Digikam 0292 0293 #include "moc_dwitemdelegate_p.cpp"