]> vaikene.ee Git - evaf/blob - src/libs/Common/eventqueue.cpp
91539a4b1698b7e600816df45fc365bbde57855b
[evaf] / src / libs / Common / eventqueue.cpp
1 /**
2 * @file Common/eventqueue.cpp
3 * @brief Event queue interface implementation
4 * @author Enar Vaikene
5 *
6 * Copyright (c) 2011-2019 Enar Vaikene
7 *
8 * This file is part of the eVaf C++ cross-platform application development framework.
9 *
10 * This file can be used under the terms of the GNU General Public License
11 * version 3.0 as published by the Free Software Foundation and appearing in
12 * the file LICENSE included in the packaging of this file. Please review the
13 * the following information to ensure the GNU General Public License version
14 * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
15 *
16 * Alternatively, this file may be used in accordance with the Commercial License
17 * Agreement provided with the Software.
18 */
19
20 #include "eventqueue.h"
21 #include "event.h"
22 #include "globals.h"
23 #include "iregistry.h"
24 #include "version.h"
25
26 #include <QtCore>
27
28
29 //-------------------------------------------------------------------
30
31 using namespace eVaf::Common;
32
33 iEventQueue * iEventQueue::instance()
34 {
35 static Internal::EventQueue singleton;
36 return &singleton;
37 }
38
39
40 //-------------------------------------------------------------------
41
42 using namespace eVaf::Common::Internal;
43
44 EventQueue::EventQueue()
45 : iEventQueue()
46 , mNextEventId(1)
47 {
48 iRegistry::instance()->registerInterface("iEventQueue", this);
49 }
50
51 EventQueue::~EventQueue()
52 {
53 }
54
55 bool EventQueue::event(QEvent * e)
56 {
57 // Is it an eVaf event?
58 if (e->type() == Event::eVafEvent) {
59
60 Event * event = static_cast<Event *>(e);
61
62 uint const id = event->id();
63
64 // Verify that this event is registered
65 Events::const_iterator eventsIt = mEvents.constFind(id);
66 if (eventsIt == mEvents.constEnd()) {
67 return true; // We don't know it, but it is an eVaf event and we should handle it
68 }
69
70 // Send the event to all the subscribers
71 Subscribers::const_iterator subscribersIt = mSubscribers.constFind(id);
72 if (subscribersIt != mSubscribers.constEnd()) {
73 QVector<QObject *> subscribers = *subscribersIt;
74 int const sz = subscribers.size();
75 for (int i = 0; i < sz; ++i) {
76
77 // Notify the subscriber
78 bool const rval = QCoreApplication::sendEvent(subscribers.at(i), e);
79
80 if (rval) {
81 // The event was consumed and should be sent to any other subscribers
82 break;
83 }
84 }
85 }
86
87 return true;
88 }
89 else
90 return iEventQueue::event(e);
91 }
92
93 uint EventQueue::registerEvent(QString const & name)
94 {
95 uint id = queryEvent(name);
96
97 if (id == 0) {
98 mEvents.insert(mNextEventId, name);
99 id = mNextEventId++;
100 }
101
102 return id;
103 }
104
105 uint EventQueue::queryEvent(QString const & name) const
106 {
107 return mEvents.key(name, 0);
108 }
109
110 void EventQueue::unregisterEvent(uint id)
111 {
112 mEvents.remove(id);
113 mSubscribers.remove(id);
114 }
115
116 uint EventQueue::subscribeEvent(uint id, QObject * obj)
117 {
118 if (id == 0)
119 return 0;
120
121 // Only registered events please
122 if (mEvents.constFind(id) == mEvents.constEnd()) {
123 return 0;
124 }
125
126 // Check for duplicates
127 if (mSubscribers[id].indexOf(obj) != -1)
128 return id;
129
130 // Add to the list of subscribers and connect to the destroyed() signal
131 mSubscribers[id].append(obj);
132 connect(obj, SIGNAL(destroyed(QObject *)), this, SLOT(subscriberDestroyed(QObject *)));
133
134 return id;
135 }
136
137 void EventQueue::unsubscribeEvent(uint id, QObject * obj)
138 {
139 if (id == 0)
140 return;
141
142 // Is the event registered?
143 if (mEvents.constFind(id) == mEvents.constEnd())
144 return;
145
146 // Remove from the list of subscribers
147 QVector<QObject *>::iterator it = mSubscribers[id].begin();
148 QVector<QObject *>::const_iterator e = mSubscribers[id].end();
149 while (it != e) {
150 if (*it == obj) {
151 it = mSubscribers[id].erase(it);
152 disconnect(*it, SIGNAL(destroyed(QObject *)), this, SLOT(subscriberDestroyed(QObject*)));
153 }
154 else {
155 ++it;
156 }
157 }
158 }
159
160 void EventQueue::broadcastEvent(Event * event)
161 {
162 QCoreApplication::postEvent(this, event);
163 }
164
165 void EventQueue::subscriberDestroyed(QObject * obj)
166 {
167 // Remove the subscriber from all the subscriber lists
168 Subscribers::iterator it = mSubscribers.begin();
169 Subscribers::const_iterator e = mSubscribers.end();
170 for (; it != e; ++it) {
171 int const idx = it->indexOf(obj);
172 if (idx != -1) {
173 it->remove(idx);
174 }
175 }
176 }