1// Copyright (C) 2015 Paul Lemire (paul.lemire350@gmail.com)
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qeventfilterservice_p.h"
5
6#include <QtCore/QObject>
7#include <QtGui/QHoverEvent>
8
9#include <Qt3DCore/private/qabstractserviceprovider_p.h>
10
11#include <algorithm>
12#include <vector>
13
14QT_BEGIN_NAMESPACE
15
16namespace {
17 struct FilterPriorityPair
18 {
19 QObject *filter;
20 int priority;
21 };
22
23 const auto byPriority = [](const FilterPriorityPair &a, const FilterPriorityPair &b) noexcept
24 {
25 return a.priority < b.priority;
26 };
27}
28
29Q_DECLARE_TYPEINFO(FilterPriorityPair, Q_PRIMITIVE_TYPE);
30
31namespace Qt3DCore {
32
33namespace {
34
35class InternalEventListener : public QObject
36{
37 Q_OBJECT
38public:
39 explicit InternalEventListener(QEventFilterServicePrivate *filterService, QObject *parent = nullptr);
40 bool eventFilter(QObject *obj, QEvent *e) final;
41 QEventFilterServicePrivate* m_filterService;
42};
43
44} // anonymous
45
46
47class QEventFilterServicePrivate : public QAbstractServiceProviderPrivate
48{
49public:
50 QEventFilterServicePrivate()
51 : QAbstractServiceProviderPrivate(QServiceLocator::EventFilterService, QStringLiteral("Default event filter service implementation"))
52 {}
53
54 Q_DECLARE_PUBLIC(QEventFilterService)
55
56 void registerEventFilter(QObject *eventFilter, int priority)
57 {
58 FilterPriorityPair fpPair;
59 fpPair.filter = eventFilter;
60 fpPair.priority = priority;
61 const auto it = std::lower_bound(first: m_eventFilters.begin(), last: m_eventFilters.end(), val: fpPair, comp: byPriority);
62 if (it == m_eventFilters.end() || it->priority != priority)
63 m_eventFilters.insert(position: it, x: std::move(fpPair));
64 }
65
66 void unregisterEventFilter(QObject *eventFilter)
67 {
68 for (auto it = m_eventFilters.begin(), end = m_eventFilters.end(); it != end; ++it) {
69 if (it->filter == eventFilter) {
70 m_eventFilters.erase(position: it);
71 return;
72 }
73 }
74 }
75
76 std::unique_ptr<InternalEventListener> m_eventDispatcher;
77 std::vector<FilterPriorityPair> m_eventFilters;
78};
79
80/* !\internal
81 \class Qt3DCore::QEventFilterService
82 \inmodule Qt3DCore
83
84 \brief Allows to register event filters with a priority.
85
86 The QEventFilterService class allows registering prioritized event filters.
87 Events are dispatched to the event filter with the highest priority first,
88 and then propagates to lower priority event filters if the event wasn't
89 accepted.
90 */
91
92QEventFilterService::QEventFilterService()
93 : QAbstractServiceProvider(*new QEventFilterServicePrivate())
94{
95}
96
97QEventFilterService::~QEventFilterService()
98{
99}
100
101// Note: event filters can only be registered to QObject in the same thread
102void QEventFilterService::initialize(QObject *eventSource)
103{
104 Q_D(QEventFilterService);
105 if (eventSource == nullptr) {
106 d->m_eventDispatcher.reset();
107 } else {
108 d->m_eventDispatcher.reset(p: new InternalEventListener(d));
109 eventSource->installEventFilter(filterObj: d->m_eventDispatcher.get());
110 }
111}
112
113void QEventFilterService::shutdown(QObject *eventSource)
114{
115 Q_D(QEventFilterService);
116 if (eventSource && d->m_eventDispatcher.get())
117 eventSource->removeEventFilter(obj: d->m_eventDispatcher.get());
118}
119
120void QEventFilterService::registerEventFilter(QObject *eventFilter, int priority)
121{
122 Q_D(QEventFilterService);
123 d->registerEventFilter(eventFilter, priority);
124}
125
126void QEventFilterService::unregisterEventFilter(QObject *eventFilter)
127{
128 Q_D(QEventFilterService);
129 d->unregisterEventFilter(eventFilter);
130}
131
132namespace {
133
134InternalEventListener::InternalEventListener(QEventFilterServicePrivate *filterService, QObject *parent)
135 : QObject(parent)
136 , m_filterService(filterService)
137{
138}
139
140bool InternalEventListener::eventFilter(QObject *obj, QEvent *e)
141{
142 for (auto i = m_filterService->m_eventFilters.size(); i > 0; --i) {
143 const FilterPriorityPair &fPPair = m_filterService->m_eventFilters[i - 1];
144 if (fPPair.filter->eventFilter(watched: obj, event: e))
145 return true;
146 }
147 return false;
148}
149
150} // namespace
151
152} // Qt3DCore
153
154QT_END_NAMESPACE
155
156#include "moc_qeventfilterservice_p.cpp"
157
158#include "qeventfilterservice.moc"
159

source code of qt3d/src/core/services/qeventfilterservice.cpp