• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KDEUI

  • kdeui
  • itemviews
kwidgetitemdelegate.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the KDE project
3 * Copyright (C) 2007-2008 Rafael Fernández López <ereslibre@kde.org>
4 * Copyright (C) 2008 Kevin Ottens <ervin@kde.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22#include "kwidgetitemdelegate.h"
23#include "kwidgetitemdelegate_p.h"
24
25#include <QIcon>
26#include <QSize>
27#include <QStyle>
28#include <QEvent>
29#include <QHoverEvent>
30#include <QFocusEvent>
31#include <QCursor>
32#include <QTimer>
33#include <QBitmap>
34#include <QLayout>
35#include <QPainter>
36#include <QScrollBar>
37#include <QKeyEvent>
38#include <QApplication>
39#include <QStyleOption>
40#include <QPaintEngine>
41#include <QCoreApplication>
42#include <QAbstractItemView>
43#include <QAbstractProxyModel>
44#include <QTreeView>
45
46#include "kwidgetitemdelegatepool_p.h"
47
48Q_DECLARE_METATYPE(QList<QEvent::Type>)
49
50
54//@cond PRIVATE
55KWidgetItemDelegatePrivate::KWidgetItemDelegatePrivate(KWidgetItemDelegate *q, QObject *parent)
56 : QObject(parent)
57 , itemView(0)
58 , widgetPool(new KWidgetItemDelegatePool(q))
59 , model(0)
60 , selectionModel(0)
61 , viewDestroyed(false)
62 , q(q)
63{
64}
65
66KWidgetItemDelegatePrivate::~KWidgetItemDelegatePrivate()
67{
68 if (!viewDestroyed) {
69 widgetPool->fullClear();
70 }
71 delete widgetPool;
72}
73
74void KWidgetItemDelegatePrivate::_k_slotRowsInserted(const QModelIndex &parent, int start, int end)
75{
76 Q_UNUSED(end);
77 // We need to update the rows behind the inserted row as well because the widgets need to be
78 // moved to their new position
79 updateRowRange(parent, start, model->rowCount(parent), false);
80}
81
82void KWidgetItemDelegatePrivate::_k_slotRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
83{
84 updateRowRange(parent, start, end, true);
85}
86
87void KWidgetItemDelegatePrivate::_k_slotRowsRemoved(const QModelIndex &parent, int start, int end)
88{
89 Q_UNUSED(end);
90 // We need to update the rows that come behind the deleted rows because the widgets need to be
91 // moved to the new position
92 updateRowRange(parent, start, model->rowCount(parent), false);
93}
94
95void KWidgetItemDelegatePrivate::_k_slotDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
96{
97 for (int i = topLeft.row(); i <= bottomRight.row(); ++i) {
98 for (int j = topLeft.column(); j <= bottomRight.column(); ++j) {
99 const QModelIndex index = model->index(i, j, topLeft.parent());
100 widgetPool->findWidgets(index, optionView(index));
101 }
102 }
103}
104
105void KWidgetItemDelegatePrivate::_k_slotLayoutChanged()
106{
107 foreach (QWidget *widget, widgetPool->invalidIndexesWidgets()) {
108 widget->setVisible(false);
109 }
110 QTimer::singleShot(0, this, SLOT(initializeModel()));
111}
112
113void KWidgetItemDelegatePrivate::_k_slotModelReset()
114{
115 widgetPool->fullClear();
116 QTimer::singleShot(0, this, SLOT(initializeModel()));
117}
118
119void KWidgetItemDelegatePrivate::_k_slotSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
120{
121 foreach (const QModelIndex &index, selected.indexes()) {
122 widgetPool->findWidgets(index, optionView(index));
123 }
124 foreach (const QModelIndex &index, deselected.indexes()) {
125 widgetPool->findWidgets(index, optionView(index));
126 }
127}
128
129void KWidgetItemDelegatePrivate::updateRowRange(const QModelIndex &parent, int start, int end, bool isRemoving)
130{
131 int i = start;
132 while (i <= end) {
133 for (int j = 0; j < model->columnCount(parent); ++j) {
134 const QModelIndex index = model->index(i, j, parent);
135 QList<QWidget*> widgetList = widgetPool->findWidgets(index, optionView(index), isRemoving ? KWidgetItemDelegatePool::NotUpdateWidgets
136 : KWidgetItemDelegatePool::UpdateWidgets);
137 if (isRemoving) {
138 widgetPool->d->allocatedWidgets.removeAll(widgetList);
139 foreach (QWidget *widget, widgetList) {
140 const QModelIndex idx = widgetPool->d->widgetInIndex[widget];
141 widgetPool->d->usedWidgets.remove(idx);
142 widgetPool->d->widgetInIndex.remove(widget);
143 delete widget;
144 }
145 }
146 }
147 i++;
148 }
149}
150
151inline QStyleOptionViewItemV4 KWidgetItemDelegatePrivate::optionView(const QModelIndex &index)
152{
153 QStyleOptionViewItemV4 optionView;
154 optionView.initFrom(itemView->viewport());
155 optionView.rect = itemView->visualRect(index);
156 optionView.decorationSize = itemView->iconSize();
157 return optionView;
158}
159
160void KWidgetItemDelegatePrivate::initializeModel(const QModelIndex &parent)
161{
162 if (!model) {
163 return;
164 }
165 for (int i = 0; i < model->rowCount(parent); ++i) {
166 for (int j = 0; j < model->columnCount(parent); ++j) {
167 const QModelIndex index = model->index(i, j, parent);
168 if (index.isValid()) {
169 widgetPool->findWidgets(index, optionView(index));
170 }
171 }
172 // Check if we need to go recursively through the children of parent (if any) to initialize
173 // all possible indexes that are shown.
174 const QModelIndex index = model->index(i, 0, parent);
175 if (index.isValid() && model->hasChildren(index)) {
176 initializeModel(index);
177 }
178 }
179}
180//@endcond
181
182KWidgetItemDelegate::KWidgetItemDelegate(QAbstractItemView *itemView, QObject *parent)
183 : QAbstractItemDelegate(parent)
184 , d(new KWidgetItemDelegatePrivate(this))
185{
186 Q_ASSERT(itemView);
187
188 itemView->setMouseTracking(true);
189 itemView->viewport()->setAttribute(Qt::WA_Hover);
190
191 d->itemView = itemView;
192
193 itemView->viewport()->installEventFilter(d); // mouse events
194 itemView->installEventFilter(d); // keyboard events
195
196 if(qobject_cast<QTreeView*>(itemView)) {
197 connect(itemView, SIGNAL(collapsed(QModelIndex)),
198 d, SLOT(initializeModel()));
199 connect(itemView, SIGNAL(expanded(QModelIndex)),
200 d, SLOT(initializeModel()));
201 }
202}
203
204KWidgetItemDelegate::~KWidgetItemDelegate()
205{
206 delete d;
207}
208
209QAbstractItemView *KWidgetItemDelegate::itemView() const
210{
211 return d->itemView;
212}
213
214QPersistentModelIndex KWidgetItemDelegate::focusedIndex() const
215{
216 const QPersistentModelIndex idx = d->widgetPool->d->widgetInIndex.value(QApplication::focusWidget());
217 if (idx.isValid()) {
218 return idx;
219 }
220 // Use the mouse position, if the widget refused to take keyboard focus.
221 const QPoint pos = d->itemView->viewport()->mapFromGlobal(QCursor::pos());
222 return d->itemView->indexAt(pos);
223}
224
225#ifndef KDE_NO_DEPRECATED
226void KWidgetItemDelegate::paintWidgets(QPainter *painter, const QStyleOptionViewItem &option,
227 const QPersistentModelIndex &index) const
228{
229 Q_UNUSED(painter);
230 Q_UNUSED(option);
231 Q_UNUSED(index);
232}
233#endif
234
235//@cond PRIVATE
236bool KWidgetItemDelegatePrivate::eventFilter(QObject *watched, QEvent *event)
237{
238 if (event->type() == QEvent::Destroy) {
239 // we care for the view since it deletes the widgets (parentage).
240 // if the view hasn't been deleted, it might be that just the
241 // delegate is removed from it, in which case we need to remove the widgets
242 // manually, otherwise they still get drawn.
243 if (watched == itemView) {
244 viewDestroyed = true;
245 }
246 return false;
247 }
248
249 Q_ASSERT(itemView);
250
251 if (model != itemView->model()) {
252 if (model) {
253 disconnect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), q, SLOT(_k_slotRowsInserted(QModelIndex,int,int)));
254 disconnect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), q, SLOT(_k_slotRowsAboutToBeRemoved(QModelIndex,int,int)));
255 disconnect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), q, SLOT(_k_slotRowsRemoved(QModelIndex,int,int)));
256 disconnect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), q, SLOT(_k_slotDataChanged(QModelIndex,QModelIndex)));
257 disconnect(model, SIGNAL(layoutChanged()), q, SLOT(_k_slotLayoutChanged()));
258 disconnect(model, SIGNAL(modelReset()), q, SLOT(_k_slotModelReset()));
259 }
260 model = itemView->model();
261 connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), q, SLOT(_k_slotRowsInserted(QModelIndex,int,int)));
262 connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), q, SLOT(_k_slotRowsAboutToBeRemoved(QModelIndex,int,int)));
263 connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), q, SLOT(_k_slotRowsRemoved(QModelIndex,int,int)));
264 connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), q, SLOT(_k_slotDataChanged(QModelIndex,QModelIndex)));
265 connect(model, SIGNAL(layoutChanged()), q, SLOT(_k_slotLayoutChanged()));
266 connect(model, SIGNAL(modelReset()), q, SLOT(_k_slotModelReset()));
267 QTimer::singleShot(0, this, SLOT(initializeModel()));
268 }
269
270 if (selectionModel != itemView->selectionModel()) {
271 if (selectionModel) {
272 disconnect(selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), q, SLOT(_k_slotSelectionChanged(QItemSelection,QItemSelection)));
273 }
274 selectionModel = itemView->selectionModel();
275 connect(selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), q, SLOT(_k_slotSelectionChanged(QItemSelection,QItemSelection)));
276 QTimer::singleShot(0, this, SLOT(initializeModel()));
277 }
278
279 switch (event->type()) {
280 case QEvent::Polish:
281 case QEvent::Resize:
282 if (!qobject_cast<QAbstractItemView*>(watched)) {
283 QTimer::singleShot(0, this, SLOT(initializeModel()));
284 }
285 break;
286 case QEvent::FocusIn:
287 case QEvent::FocusOut:
288 if (qobject_cast<QAbstractItemView*>(watched)) {
289 foreach (const QModelIndex &index, selectionModel->selectedIndexes()) {
290 if (index.isValid()) {
291 widgetPool->findWidgets(index, optionView(index));
292 }
293 }
294 }
295 default:
296 break;
297 }
298
299 return QObject::eventFilter(watched, event);
300}
301//@endcond
302
303void KWidgetItemDelegate::setBlockedEventTypes(QWidget *widget, QList<QEvent::Type> types) const
304{
305 widget->setProperty("goya:blockedEventTypes", qVariantFromValue(types));
306}
307
308QList<QEvent::Type> KWidgetItemDelegate::blockedEventTypes(QWidget *widget) const
309{
310 return widget->property("goya:blockedEventTypes").value<QList<QEvent::Type> >();
311}
312
313#include "kwidgetitemdelegate.moc"
314#include "kwidgetitemdelegate_p.moc"
KWidgetItemDelegate
This class allows to create item delegates embedding simple widgets to interact with items.
Definition: kwidgetitemdelegate.h:50
KWidgetItemDelegate::itemView
QAbstractItemView * itemView() const
Retrieves the item view this delegate is monitoring.
Definition: kwidgetitemdelegate.cpp:209
KWidgetItemDelegate::setBlockedEventTypes
void setBlockedEventTypes(QWidget *widget, QList< QEvent::Type > types) const
Sets the list of event types that a widget will block.
Definition: kwidgetitemdelegate.cpp:303
KWidgetItemDelegate::paintWidgets
void paintWidgets(QPainter *painter, const QStyleOptionViewItem &option, const QPersistentModelIndex &index) const
Paint the widgets of the item.
Definition: kwidgetitemdelegate.cpp:226
KWidgetItemDelegate::~KWidgetItemDelegate
virtual ~KWidgetItemDelegate()
Destroys an ItemDelegate.
Definition: kwidgetitemdelegate.cpp:204
KWidgetItemDelegate::blockedEventTypes
QList< QEvent::Type > blockedEventTypes(QWidget *widget) const
Retrieves the list of blocked event types for the given widget.
Definition: kwidgetitemdelegate.cpp:308
KWidgetItemDelegate::KWidgetItemDelegate
KWidgetItemDelegate(QAbstractItemView *itemView, QObject *parent=0)
Creates a new ItemDelegate to be used with a given itemview.
Definition: kwidgetitemdelegate.cpp:182
KWidgetItemDelegate::focusedIndex
QPersistentModelIndex focusedIndex() const
Retrieves the currently focused index.
Definition: kwidgetitemdelegate.cpp:214
QList
QObject
QWidget
kwidgetitemdelegate.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal