/** * @file Common/eventqueue.cpp * @brief Event queue interface implementation * @author Enar Vaikene * * Copyright (c) 2011-2019 Enar Vaikene * * This file is part of the eVaf C++ cross-platform application development framework. * * This file can be used under the terms of the GNU General Public License * version 3.0 as published by the Free Software Foundation and appearing in * the file LICENSE included in the packaging of this file. Please review the * the following information to ensure the GNU General Public License version * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. * * Alternatively, this file may be used in accordance with the Commercial License * Agreement provided with the Software. */ #include "eventqueue.h" #include "event.h" #include "globals.h" #include "iregistry.h" #include "version.h" #include //------------------------------------------------------------------- using namespace eVaf::Common; iEventQueue * iEventQueue::instance() { static Internal::EventQueue singleton; return &singleton; } //------------------------------------------------------------------- using namespace eVaf::Common::Internal; EventQueue::EventQueue() : iEventQueue() , mNextEventId(1) { iRegistry::instance()->registerInterface("iEventQueue", this); } EventQueue::~EventQueue() { } bool EventQueue::event(QEvent * e) { // Is it an eVaf event? if (e->type() == Event::eVafEvent) { Event * event = static_cast(e); uint const id = event->id(); // Verify that this event is registered Events::const_iterator eventsIt = mEvents.constFind(id); if (eventsIt == mEvents.constEnd()) { return true; // We don't know it, but it is an eVaf event and we should handle it } // Send the event to all the subscribers Subscribers::const_iterator subscribersIt = mSubscribers.constFind(id); if (subscribersIt != mSubscribers.constEnd()) { QVector subscribers = *subscribersIt; int const sz = subscribers.size(); for (int i = 0; i < sz; ++i) { // Notify the subscriber bool const rval = QCoreApplication::sendEvent(subscribers.at(i), e); if (rval) { // The event was consumed and should be sent to any other subscribers break; } } } return true; } else return iEventQueue::event(e); } uint EventQueue::registerEvent(QString const & name) { uint id = queryEvent(name); if (id == 0) { mEvents.insert(mNextEventId, name); id = mNextEventId++; } return id; } uint EventQueue::queryEvent(QString const & name) const { return mEvents.key(name, 0); } void EventQueue::unregisterEvent(uint id) { mEvents.remove(id); mSubscribers.remove(id); } uint EventQueue::subscribeEvent(uint id, QObject * obj) { if (id == 0) return 0; // Only registered events please if (mEvents.constFind(id) == mEvents.constEnd()) { return 0; } // Check for duplicates if (mSubscribers[id].indexOf(obj) != -1) return id; // Add to the list of subscribers and connect to the destroyed() signal mSubscribers[id].append(obj); connect(obj, SIGNAL(destroyed(QObject *)), this, SLOT(subscriberDestroyed(QObject *))); return id; } void EventQueue::unsubscribeEvent(uint id, QObject * obj) { if (id == 0) return; // Is the event registered? if (mEvents.constFind(id) == mEvents.constEnd()) return; // Remove from the list of subscribers QVector::iterator it = mSubscribers[id].begin(); QVector::const_iterator e = mSubscribers[id].end(); while (it != e) { if (*it == obj) { it = mSubscribers[id].erase(it); disconnect(*it, SIGNAL(destroyed(QObject *)), this, SLOT(subscriberDestroyed(QObject*))); } else { ++it; } } } void EventQueue::broadcastEvent(Event * event) { QCoreApplication::postEvent(this, event); } void EventQueue::subscriberDestroyed(QObject * obj) { // Remove the subscriber from all the subscriber lists Subscribers::iterator it = mSubscribers.begin(); Subscribers::const_iterator e = mSubscribers.end(); for (; it != e; ++it) { int const idx = it->indexOf(obj); if (idx != -1) { it->remove(idx); } } }