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

KDEUI

  • sources
  • kde-4.14
  • kdelibs
  • 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 
48 Q_DECLARE_METATYPE(QList<QEvent::Type>)
49 
50 
54 //@cond PRIVATE
55 KWidgetItemDelegatePrivate::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 
66 KWidgetItemDelegatePrivate::~KWidgetItemDelegatePrivate()
67 {
68  if (!viewDestroyed) {
69  widgetPool->fullClear();
70  }
71  delete widgetPool;
72 }
73 
74 void 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 
82 void KWidgetItemDelegatePrivate::_k_slotRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
83 {
84  updateRowRange(parent, start, end, true);
85 }
86 
87 void 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 
95 void 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 
105 void KWidgetItemDelegatePrivate::_k_slotLayoutChanged()
106 {
107  foreach (QWidget *widget, widgetPool->invalidIndexesWidgets()) {
108  widget->setVisible(false);
109  }
110  QTimer::singleShot(0, this, SLOT(initializeModel()));
111 }
112 
113 void KWidgetItemDelegatePrivate::_k_slotModelReset()
114 {
115  widgetPool->fullClear();
116  QTimer::singleShot(0, this, SLOT(initializeModel()));
117 }
118 
119 void 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 
129 void 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 
151 inline 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 
160 void 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 
182 KWidgetItemDelegate::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 
204 KWidgetItemDelegate::~KWidgetItemDelegate()
205 {
206  delete d;
207 }
208 
209 QAbstractItemView *KWidgetItemDelegate::itemView() const
210 {
211  return d->itemView;
212 }
213 
214 QPersistentModelIndex 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
226 void 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
236 bool 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 
303 void KWidgetItemDelegate::setBlockedEventTypes(QWidget *widget, QList<QEvent::Type> types) const
304 {
305  widget->setProperty("goya:blockedEventTypes", qVariantFromValue(types));
306 }
307 
308 QList<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"
QItemSelection::indexes
QModelIndexList indexes() const
QModelIndex
QEvent
QWidget
QEvent::type
Type type() const
KWidgetItemDelegate::focusedIndex
QPersistentModelIndex focusedIndex() const
Retrieves the currently focused index.
Definition: kwidgetitemdelegate.cpp:214
KWidgetItemDelegate::blockedEventTypes
QList< QEvent::Type > blockedEventTypes(QWidget *widget) const
Retrieves the list of blocked event types for the given widget.
Definition: kwidgetitemdelegate.cpp:308
QAbstractItemView
KWidgetItemDelegate::~KWidgetItemDelegate
virtual ~KWidgetItemDelegate()
Destroys an ItemDelegate.
Definition: kwidgetitemdelegate.cpp:204
KWidgetItemDelegate::itemView
QAbstractItemView * itemView() const
Retrieves the item view this delegate is monitoring.
Definition: kwidgetitemdelegate.cpp:209
QWidget::setVisible
virtual void setVisible(bool visible)
QWidget::setAttribute
void setAttribute(Qt::WidgetAttribute attribute, bool on)
QVariant::value
T value() const
QAbstractScrollArea::viewport
QWidget * viewport() const
QPoint
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
QStyleOption::initFrom
void initFrom(const QWidget *widget)
KWidgetItemDelegate
This class allows to create item delegates embedding simple widgets to interact with items...
Definition: kwidgetitemdelegate.h:49
QModelIndex::isValid
bool isValid() const
QPersistentModelIndex::isValid
bool isValid() const
QObject::property
QVariant property(const char *name) const
QObject::installEventFilter
void installEventFilter(QObject *filterObj)
KWidgetItemDelegate::KWidgetItemDelegate
KWidgetItemDelegate(QAbstractItemView *itemView, QObject *parent=0)
Creates a new ItemDelegate to be used with a given itemview.
Definition: kwidgetitemdelegate.cpp:182
QStyleOptionViewItem
QObject
QPainter
QApplication::focusWidget
QWidget * focusWidget()
QList::removeAll
int removeAll(const T &value)
QModelIndex::row
int row() const
QObject::eventFilter
virtual bool eventFilter(QObject *watched, QEvent *event)
QList
QModelIndex::parent
QModelIndex parent() const
KWidgetItemDelegate::paintWidgets
void paintWidgets(QPainter *painter, const QStyleOptionViewItem &option, const QPersistentModelIndex &index) const
Paint the widgets of the item.
Definition: kwidgetitemdelegate.cpp:226
QItemSelection
kwidgetitemdelegate.h
QPersistentModelIndex
QCursor::pos
QPoint pos()
QModelIndex::column
int column() const
QWidget::setMouseTracking
void setMouseTracking(bool enable)
QObject::setProperty
bool setProperty(const char *name, const QVariant &value)
QStyleOptionViewItemV4
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
KStandardShortcut::end
const KShortcut & end()
Goto end of the document.
Definition: kstandardshortcut.cpp:348
QTimer::singleShot
singleShot
QAbstractItemDelegate
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:24:00 by doxygen 1.8.7 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 API Reference

Skip menu "kdelibs 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

Search



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