KItemViews

kwidgetitemdelegatepool.cpp
1/*
2 This file is part of the KDE project
3 SPDX-FileCopyrightText: 2008 Rafael Fernández López <ereslibre@kde.org>
4 SPDX-FileCopyrightText: 2008 Kevin Ottens <ervin@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8
9#include "kwidgetitemdelegatepool_p.h"
10
11#include <QAbstractItemView>
12#include <QAbstractProxyModel>
13#include <QApplication>
14#include <QHash>
15#include <QInputEvent>
16#include <QList>
17#include <QMetaMethod>
18#include <QWidget>
19#include <qobjectdefs.h>
20
21#include "kwidgetitemdelegate.h"
22#include "kwidgetitemdelegate_p.h"
23#include <kitemviews_debug.h>
24
25/**
26 Private class that helps to provide binary compatibility between releases.
27 @internal
28*/
29//@cond PRIVATE
30class KWidgetItemDelegateEventListener : public QObject
31{
32public:
33 KWidgetItemDelegateEventListener(KWidgetItemDelegatePoolPrivate *poolPrivate, QObject *parent = nullptr)
34 : QObject(parent)
35 , poolPrivate(poolPrivate)
36 {
37 }
38
39 bool eventFilter(QObject *watched, QEvent *event) override;
40
41private:
42 KWidgetItemDelegatePoolPrivate *const poolPrivate;
43};
44
45KWidgetItemDelegatePoolPrivate::KWidgetItemDelegatePoolPrivate(KWidgetItemDelegate *d)
46 : delegate(d)
47 , eventListener(new KWidgetItemDelegateEventListener(this))
48{
49}
50
51KWidgetItemDelegatePool::KWidgetItemDelegatePool(KWidgetItemDelegate *delegate)
52 : d(new KWidgetItemDelegatePoolPrivate(delegate))
53{
54}
55
56KWidgetItemDelegatePool::~KWidgetItemDelegatePool()
57{
58 delete d->eventListener;
59 delete d;
60}
61
63KWidgetItemDelegatePool::findWidgets(const QPersistentModelIndex &idx, const QStyleOptionViewItem &option, UpdateWidgetsEnum updateWidgets) const
64{
65 QList<QWidget *> result;
66
67 if (!idx.isValid()) {
68 return result;
69 }
70
71 QModelIndex index;
72 if (const QAbstractProxyModel *proxyModel = qobject_cast<const QAbstractProxyModel *>(idx.model())) {
73 index = proxyModel->mapToSource(idx);
74 } else {
75 index = idx;
76 }
77
78 if (!index.isValid()) {
79 return result;
80 }
81
82 if (d->usedWidgets.contains(index)) {
83 result = d->usedWidgets[index];
84 } else {
85 result = d->delegate->createItemWidgets(index);
86 d->allocatedWidgets << result;
87 d->usedWidgets[index] = result;
88 for (QWidget *widget : std::as_const(result)) {
89 d->widgetInIndex[widget] = index;
90 widget->setParent(d->delegate->d->itemView->viewport());
91 widget->installEventFilter(d->eventListener);
92 widget->setVisible(true);
93 }
94 }
95
96 if (updateWidgets == UpdateWidgets) {
97 for (QWidget *widget : std::as_const(result)) {
98 widget->setVisible(true);
99 }
100
101 d->delegate->updateItemWidgets(result, option, idx);
102
103 for (QWidget *widget : std::as_const(result)) {
104 widget->move(widget->x() + option.rect.left(), widget->y() + option.rect.top());
105 }
106 }
107
108 return result;
109}
110
111QList<QWidget *> KWidgetItemDelegatePool::invalidIndexesWidgets() const
112{
113 QList<QWidget *> result;
115 while (i.hasNext()) {
116 i.next();
117 const QAbstractProxyModel *proxyModel = qobject_cast<const QAbstractProxyModel *>(d->delegate->d->model);
118 QModelIndex index;
119 if (proxyModel) {
120 index = proxyModel->mapFromSource(i.value());
121 } else {
122 index = i.value();
123 }
124 if (!index.isValid()) {
125 result << i.key();
126 }
127 }
128 return result;
129}
130
131void KWidgetItemDelegatePool::fullClear()
132{
133 d->clearing = true;
134 qDeleteAll(d->widgetInIndex.keys());
135 d->clearing = false;
136 d->allocatedWidgets.clear();
137 d->usedWidgets.clear();
138 d->widgetInIndex.clear();
139}
140
141bool KWidgetItemDelegateEventListener::eventFilter(QObject *watched, QEvent *event)
142{
143 QWidget *widget = static_cast<QWidget *>(watched);
144
145 if (event->type() == QEvent::Destroy && !poolPrivate->clearing) {
146 qCWarning(KITEMVIEWS_LOG) << "User of KWidgetItemDelegate should not delete widgets created by createItemWidgets!";
147 // assume the application has kept a list of widgets and tries to delete them manually
148 // they have been reparented to the view in any case, so no leaking occurs
149 poolPrivate->widgetInIndex.remove(widget);
150 QWidget *viewport = poolPrivate->delegate->d->itemView->viewport();
151 QApplication::sendEvent(viewport, event);
152 }
153 if (dynamic_cast<QInputEvent *>(event) && !poolPrivate->delegate->blockedEventTypes(widget).contains(event->type())) {
154 QWidget *viewport = poolPrivate->delegate->d->itemView->viewport();
155 switch (event->type()) {
160 QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
161 QMouseEvent evt(event->type(),
162 mouseEvent->position(),
163 viewport->mapFromGlobal(mouseEvent->globalPosition()),
164 mouseEvent->button(),
165 mouseEvent->buttons(),
166 mouseEvent->modifiers());
167 QApplication::sendEvent(viewport, &evt);
168 } break;
169 case QEvent::Wheel: {
170 QWheelEvent *wheelEvent = static_cast<QWheelEvent *>(event);
171 QWheelEvent evt(viewport->mapFromGlobal(wheelEvent->position().toPoint()),
172 viewport->mapFromGlobal(wheelEvent->globalPosition().toPoint()),
173 wheelEvent->pixelDelta(),
174 wheelEvent->angleDelta(),
175 wheelEvent->buttons(),
176 wheelEvent->modifiers(),
177 wheelEvent->phase(),
178 wheelEvent->inverted(),
179 wheelEvent->source());
180 QApplication::sendEvent(viewport, &evt);
181 } break;
187 QTabletEvent *tabletEvent = static_cast<QTabletEvent *>(event);
188 QTabletEvent evt(event->type(),
189 tabletEvent->pointingDevice(),
190 viewport->mapFromGlobal(tabletEvent->globalPosition()),
191 tabletEvent->globalPosition(),
192 tabletEvent->pressure(),
193 tabletEvent->xTilt(),
194 tabletEvent->yTilt(),
195 tabletEvent->tangentialPressure(),
196 tabletEvent->rotation(),
197 tabletEvent->z(),
198 tabletEvent->modifiers(),
199 tabletEvent->button(),
200 tabletEvent->buttons());
201 QApplication::sendEvent(viewport, &evt);
202 break;
203 }
204 default:
205 QApplication::sendEvent(viewport, event);
206 break;
207 }
208 }
209
210 return QObject::eventFilter(watched, event);
211}
212//@endcond
This class allows to create item delegates embedding simple widgets to interact with items.
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const const=0
bool sendEvent(QObject *receiver, QEvent *event)
Qt::KeyboardModifiers modifiers() const const
bool isValid() const const
virtual bool eventFilter(QObject *watched, QEvent *event)
bool isValid() const const
const QAbstractItemModel * model() const const
const QPointingDevice * pointingDevice() const const
QPoint toPoint() const const
Qt::MouseButton button() const const
Qt::MouseButtons buttons() const const
QPointF globalPosition() const const
QPointF position() const const
qreal pressure() const const
qreal rotation() const const
qreal tangentialPressure() const const
qreal xTilt() const const
qreal yTilt() const const
qreal z() const const
Qt::MouseEventSource source() const const
QPoint angleDelta() const const
bool inverted() const const
Qt::ScrollPhase phase() const const
QPoint pixelDelta() const const
QPoint mapFromGlobal(const QPoint &pos) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:17:32 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.