+// ============================================================
+// QueuedEvent
+// ============================================================
+class QueuedQuasselEvent : public QEvent
+{
+public:
+ QueuedQuasselEvent(Event* event)
+ : QEvent(QEvent::User)
+ , event(event)
+ {}
+ Event* event;
+};
+
+// ============================================================
+// EventManager
+// ============================================================
+EventManager::EventManager(QObject* parent)
+ : QObject(parent)
+{}
+
+QMetaEnum EventManager::eventEnum()
+{
+ if (!_enum.isValid()) {
+ int eventEnumIndex = staticMetaObject.indexOfEnumerator("EventType");
+ Q_ASSERT(eventEnumIndex >= 0);
+ _enum = staticMetaObject.enumerator(eventEnumIndex);
+ Q_ASSERT(_enum.isValid());
+ }
+ return _enum;
+}
+
+EventManager::EventType EventManager::eventTypeByName(const QString& name)
+{
+ int val = eventEnum().keyToValue(name.toLatin1());
+ return (val == -1) ? Invalid : static_cast<EventType>(val);
+}
+
+EventManager::EventType EventManager::eventGroupByName(const QString& name)
+{
+ EventType type = eventTypeByName(name);
+ return type == Invalid ? Invalid : static_cast<EventType>(type & EventGroupMask);
+}
+
+QString EventManager::enumName(EventType type)
+{
+ return eventEnum().valueToKey(type);
+}
+
+QString EventManager::enumName(int type)
+{
+ return eventEnum().valueToKey(type);
+}
+
+Event* EventManager::createEvent(const QVariantMap& map)
+{
+ QVariantMap m = map;
+
+ Network* net = networkById(m.take("network").toInt());
+ return Event::fromVariantMap(m, net);
+}
+
+/* NOTE:
+ Registering and calling handlers works fine even if they specify a subclass of Event as their parameter.
+ However, this most probably is a result from a reinterpret_cast somewhere deep inside Qt, so there is *no*
+ type safety. If the event sent is of the wrong class type, you'll get a neat segfault!
+ Thus, we need to make sure that events are of the correct class type when sending!
+
+ We might add a registration-time check later, which will require matching the enum base name (e.g. "IrcEvent") with
+ the type the handler claims to support. This still won't protect us from someone sending an IrcEvent object
+ with an enum type "NetworkIncoming", for example.
+
+ Another way would be to add a check into the various Event subclasses, such that the ctor matches the given event type
+ with the actual class. Possibly (optionally) using rtti...
+*/
+
+int EventManager::findEventType(const QString& methodSignature_, const QString& methodPrefix) const
+{
+ if (!methodSignature_.startsWith(methodPrefix))
+ return -1;
+
+ QString methodSignature = methodSignature_;
+
+ methodSignature = methodSignature.section('(', 0, 0); // chop the attribute list
+ methodSignature = methodSignature.mid(methodPrefix.length()); // strip prefix
+
+ int eventType = -1;
+
+ // special handling for numeric IrcEvents: IrcEvent042 gets mapped to IrcEventNumeric + 42
+ if (methodSignature.length() == 8 + 3 && methodSignature.startsWith("IrcEvent")) {
+ int num = methodSignature.right(3).toUInt();
+ if (num > 0) {
+ QString numericSig = methodSignature.left(methodSignature.length() - 3) + "Numeric";
+ eventType = eventEnum().keyToValue(numericSig.toLatin1());
+ if (eventType < 0) {
+ qWarning() << Q_FUNC_INFO << "Could not find EventType" << numericSig << "for handling" << methodSignature;
+ return -1;
+ }
+ eventType += num;
+ }
+ }
+
+ if (eventType < 0)
+ eventType = eventEnum().keyToValue(methodSignature.toLatin1());
+ if (eventType < 0) {
+ qWarning() << Q_FUNC_INFO << "Could not find EventType" << methodSignature;
+ return -1;
+ }
+ return eventType;
+}
+
+void EventManager::registerObject(QObject* object, Priority priority, const QString& methodPrefix, const QString& filterPrefix)
+{
+ for (int i = object->metaObject()->methodOffset(); i < object->metaObject()->methodCount(); i++) {
+ QString methodSignature = object->metaObject()->method(i).methodSignature();
+ int eventType = findEventType(methodSignature, methodPrefix);
+ if (eventType > 0) {
+ Handler handler(object, i, priority);
+ registeredHandlers()[eventType].append(handler);
+ // qDebug() << "Registered event handler for" << methodSignature << "in" << object;
+ }
+ eventType = findEventType(methodSignature, filterPrefix);
+ if (eventType > 0) {
+ Handler handler(object, i, priority);
+ registeredFilters()[eventType].append(handler);
+ // qDebug() << "Registered event filterer for" << methodSignature << "in" << object;
+ }
+ }
+}
+
+void EventManager::registerEventFilter(EventType event, QObject* object, const char* slot)
+{
+ registerEventHandler(QList<EventType>() << event, object, slot, NormalPriority, true);