From d9588ab4fff449eeb77ebb03a6cb1c5c91d1449d Mon Sep 17 00:00:00 2001 From: Manuel Nickschas Date: Sun, 17 Oct 2010 21:11:58 +0200 Subject: [PATCH 1/1] Fix event propagation It sometimes makes sense to deliver the same event to the same object (but different event handlers), so we shouldn't prevent that. Instead, make sure that generic handlers are not called if at least one specialized handler is registered. --- src/common/eventmanager.cpp | 33 ++++++++++++++++++++++----------- src/common/eventmanager.h | 2 +- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/common/eventmanager.cpp b/src/common/eventmanager.cpp index 7303ea5a..fd3cf9bd 100644 --- a/src/common/eventmanager.cpp +++ b/src/common/eventmanager.cpp @@ -193,6 +193,8 @@ void EventManager::dispatchEvent(Event *event) { QSet ignored; uint type = event->type(); + bool checkDupes = false; + // special handling for numeric IrcEvents if((type & ~IrcEventNumericMask) == IrcEventNumeric) { ::IrcEventNumeric *numEvent = static_cast< ::IrcEventNumeric *>(event); @@ -201,19 +203,20 @@ void EventManager::dispatchEvent(Event *event) { else { int num = numEvent->number(); if(num > 0) { - insertHandlers(registeredHandlers().value(type + num), handlers); + insertHandlers(registeredHandlers().value(type + num), handlers, false); insertFilters(registeredFilters().value(type + num), filters); + checkDupes = true; } } } // exact type - insertHandlers(registeredHandlers().value(type), handlers); + insertHandlers(registeredHandlers().value(type), handlers, checkDupes); insertFilters(registeredFilters().value(type), filters); // check if we have a generic handler for the event group if((type & EventGroupMask) != type) { - insertHandlers(registeredHandlers().value(type & EventGroupMask), handlers); + insertHandlers(registeredHandlers().value(type & EventGroupMask), handlers, true); insertFilters(registeredFilters().value(type & EventGroupMask), filters); } @@ -222,18 +225,18 @@ void EventManager::dispatchEvent(Event *event) { for(it = handlers.begin(); it != handlers.end() && !event->isStopped(); ++it) { QObject *obj = it->object; - if(ignored.contains(obj)) // we only deliver an event once to any given object + if(ignored.contains(obj)) // object has filtered the event continue; - ignored.insert(obj); - if(filters.contains(obj)) { // we have a filter, so let's check if we want to deliver the event Handler filter = filters.value(obj); bool result = false; void *param[] = {Q_RETURN_ARG(bool, result).data(), Q_ARG(Event *, event).data() }; obj->qt_metacall(QMetaObject::InvokeMetaMethod, filter.methodIndex, param); - if(!result) + if(!result) { + ignored.insert(obj); continue; // mmmh, event filter told us to not accept + } } // finally, deliverance! @@ -245,19 +248,27 @@ void EventManager::dispatchEvent(Event *event) { delete event; } -void EventManager::insertHandlers(const QList &newHandlers, QList &existing) { +void EventManager::insertHandlers(const QList &newHandlers, QList &existing, bool checkDupes) { foreach(const Handler &handler, newHandlers) { if(existing.isEmpty()) existing.append(handler); else { - // need to insert it at the proper position + // need to insert it at the proper position, but only if we don't yet have a handler for this event and object! + bool insert = true; + QList::iterator insertpos = existing.end(); QList::iterator it = existing.begin(); while(it != existing.end()) { - if(handler.priority > it->priority) + if(checkDupes && handler.object == it->object) { + insert = false; break; + } + if(insertpos == existing.end() && handler.priority > it->priority) + insertpos = it; + ++it; } - existing.insert(it, handler); + if(insert) + existing.insert(it, handler); } } } diff --git a/src/common/eventmanager.h b/src/common/eventmanager.h index d4f49c75..bc0a1d40 100644 --- a/src/common/eventmanager.h +++ b/src/common/eventmanager.h @@ -158,7 +158,7 @@ private: inline HandlerHash ®isteredFilters() { return _registeredFilters; } //! Add handlers to an existing sorted (by priority) handler list - void insertHandlers(const QList &newHandlers, QList &existing); + void insertHandlers(const QList &newHandlers, QList &existing, bool checkDupes = false); //! Add filters to an existing filter hash void insertFilters(const QList &newFilters, QHash &existing); -- 2.20.1