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->usedWidgets[index] = result;
87 for (QWidget *widget : std::as_const(result)) {
88 d->widgetInIndex[widget] = index;
89 widget->setParent(d->delegate->d->itemView->viewport());
90 widget->installEventFilter(d->eventListener);
91 widget->setVisible(true);
92 }
93 }
94
95 if (updateWidgets == UpdateWidgets) {
96 for (QWidget *widget : std::as_const(result)) {
97 widget->setVisible(true);
98 }
99
100 d->delegate->updateItemWidgets(result, option, idx);
101
102 for (QWidget *widget : std::as_const(result)) {
103 widget->move(widget->x() + option.rect.left(), widget->y() + option.rect.top());
104 }
105 }
106
107 return result;
108}
109
110QList<QWidget *> KWidgetItemDelegatePool::invalidIndexesWidgets() const
111{
112 QList<QWidget *> result;
114 while (i.hasNext()) {
115 i.next();
116 const QAbstractProxyModel *proxyModel = qobject_cast<const QAbstractProxyModel *>(d->delegate->d->model);
117 QModelIndex index;
118 if (proxyModel) {
119 index = proxyModel->mapFromSource(i.value());
120 } else {
121 index = i.value();
122 }
123 if (!index.isValid()) {
124 result << i.key();
125 }
126 }
127 return result;
128}
129
130void KWidgetItemDelegatePool::fullClear()
131{
132 d->clearing = true;
133 qDeleteAll(d->widgetInIndex.keys());
134 d->clearing = false;
135 d->usedWidgets.clear();
136 d->widgetInIndex.clear();
137}
138
139bool KWidgetItemDelegateEventListener::eventFilter(QObject *watched, QEvent *event)
140{
141 QWidget *widget = static_cast<QWidget *>(watched);
142
143 if (event->type() == QEvent::Destroy && !poolPrivate->clearing) {
144 qCWarning(KITEMVIEWS_LOG) << "User of KWidgetItemDelegate should not delete widgets created by createItemWidgets!";
145 // assume the application has kept a list of widgets and tries to delete them manually
146 // they have been reparented to the view in any case, so no leaking occurs
147 poolPrivate->widgetInIndex.remove(widget);
148 }
149 if (dynamic_cast<QInputEvent *>(event) && !poolPrivate->delegate->blockedEventTypes(widget).contains(event->type())) {
150 QWidget *viewport = poolPrivate->delegate->d->itemView->viewport();
151 switch (event->type()) {
156 QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
157 QMouseEvent evt(event->type(),
158 mouseEvent->position(),
159 viewport->mapFromGlobal(mouseEvent->globalPosition()),
160 mouseEvent->button(),
161 mouseEvent->buttons(),
162 mouseEvent->modifiers());
163 QApplication::sendEvent(viewport, &evt);
164 } break;
165 case QEvent::Wheel: {
166 QWheelEvent *wheelEvent = static_cast<QWheelEvent *>(event);
167 QWheelEvent evt(viewport->mapFromGlobal(wheelEvent->position().toPoint()),
168 viewport->mapFromGlobal(wheelEvent->globalPosition().toPoint()),
169 wheelEvent->pixelDelta(),
170 wheelEvent->angleDelta(),
171 wheelEvent->buttons(),
172 wheelEvent->modifiers(),
173 wheelEvent->phase(),
174 wheelEvent->inverted(),
175 wheelEvent->source());
176 QApplication::sendEvent(viewport, &evt);
177 } break;
183 QTabletEvent *tabletEvent = static_cast<QTabletEvent *>(event);
184 QTabletEvent evt(event->type(),
185 tabletEvent->pointingDevice(),
186 viewport->mapFromGlobal(tabletEvent->globalPosition()),
187 tabletEvent->globalPosition(),
188 tabletEvent->pressure(),
189 tabletEvent->xTilt(),
190 tabletEvent->yTilt(),
191 tabletEvent->tangentialPressure(),
192 tabletEvent->rotation(),
193 tabletEvent->z(),
194 tabletEvent->modifiers(),
195 tabletEvent->button(),
196 tabletEvent->buttons());
197 QApplication::sendEvent(viewport, &evt);
198 break;
199 }
200 default:
201 QApplication::sendEvent(viewport, event);
202 break;
203 }
204 }
205
206 return QObject::eventFilter(watched, event);
207}
208//@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 Fri Oct 11 2024 12:18:22 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.