Introduce CtcpParser for CTCP-related event processing
[quassel.git] / src / common / eventmanager.h
index 78a72ac..025493b 100644 (file)
 #ifndef EVENTMANAGER_H
 #define EVENTMANAGER_H
 
-#include <QHash>
-#include <QObject>
+#include <QMetaEnum>
 
 class Event;
 
 class EventManager : public QObject {
   Q_OBJECT
+  Q_FLAGS(EventFlag EventFlags)
   Q_ENUMS(EventType)
 
 public:
@@ -37,71 +37,151 @@ public:
     Append
   };
 
+  enum Priority {
+    VeryLowPriority,
+    LowPriority,
+    NormalPriority,
+    HighPriority,
+    HighestPriority
+  };
+
+  enum EventFlag {
+    Self     = 0x01, ///< Self-generated (user input) event
+    Fake     = 0x08, ///< Ignore this in CoreSessionEventProcessor
+    Netsplit = 0x10, ///< Netsplit join/part, ignore on display
+    Backlog  = 0x20,
+    Silent   = 0x40, ///< Don't generate a MessageEvent
+    Stopped  = 0x80
+  };
+  Q_DECLARE_FLAGS(EventFlags, EventFlag);
+
   /*
 
   */
+  /* These values make sense! Don't change without knowing what you do! */
   enum EventType {
     Invalid                     = 0xffffffff,
-    GenericEvent                  = 0x000000,
-
-    IrcServerEvent                = 0x010000,
-    IrcServerLooking              = 0x010001,
-    IrcServerConnecting           = 0x010002,
-    IrcServerConnected            = 0x010003,
-    IrcServerConnectionFailure    = 0x010004,
-    IrcServerDisconnected         = 0x010005,
-    IrcServerQuit                 = 0x010006,
-
-    IrcServerIncoming             = 0x010007,
-
-    IrcEvent                      = 0x020000,
-    IrcEventCap                   = 0x020001,
-    IrcEventCapAuthenticate       = 0x020002,
-    IrcEventInvite                = 0x020003,
-    IrcEventJoin                  = 0x020004,
-    IrcEventKick                  = 0x020005,
-    IrcEventMode                  = 0x020006,
-    IrcEventNick                  = 0x020007,
-    IrcEventNotice                = 0x020008,
-    IrcEventPart                  = 0x020009,
-    IrcEventPing                  = 0x02000a,
-    IrcEventPong                  = 0x02000b,
-    IrcEventPrivmsg               = 0x02000c,
-    IrcEventQuit                  = 0x02000d,
-    IrcEventTopic                 = 0x02000e,
-
-    IrcEventNumeric               = 0x021000 /* needs 1000 (0x03e8) consecutive free values! */
+    GenericEvent                = 0x00000000,
+
+    // for event group handlers (handleIrcEvent() will handle all IrcEvent* enums)
+    // event groups are specified by bits 20-24
+    EventGroupMask              = 0x00ff0000,
+
+    NetworkEvent                = 0x00010000,
+    NetworkConnecting,
+    NetworkInitializing,
+    NetworkInitialized,
+    NetworkReconnecting,
+    NetworkDisconnecting,
+    NetworkDisconnected,
+    NetworkSplitJoin,
+    NetworkSplitQuit,
+    NetworkIncoming,
+
+    IrcServerEvent              = 0x00020000,
+    IrcServerIncoming,
+    IrcServerParseError,
+
+    IrcEvent                    = 0x00030000,
+    IrcEventAuthenticate,
+    IrcEventCap,
+    IrcEventInvite,
+    IrcEventJoin,
+    IrcEventKick,
+    IrcEventMode,
+    IrcEventNick,
+    IrcEventNotice,
+    IrcEventPart,
+    IrcEventPing,
+    IrcEventPong,
+    IrcEventPrivmsg,
+    IrcEventQuit,
+    IrcEventTopic,
+    IrcEventRawPrivmsg, ///< Undecoded privmsg (still needs CTCP parsing)
+    IrcEventRawNotice,  ///< Undecoded notice (still needs CTCP parsing)
+    IrcEventUnknown,    ///< Unknown non-numeric cmd
+
+    IrcEventNumeric             = 0x00031000, /* needs 1000 (0x03e8) consecutive free values! */
+    IrcEventNumericMask         = 0x00000fff, /* for checking if an event is numeric */
+
+    MessageEvent                = 0x00040000, ///< Stringified event suitable for converting to Message
+
+    CtcpEvent                   = 0x00050000,
+    CtcpEventFlush,
   };
 
   EventManager(QObject *parent = 0);
-  //virtual ~EventManager();
+  virtual ~EventManager();
 
-  QStringList providesEnums();
+  EventType eventTypeByName(const QString &name) const;
+  EventType eventGroupByName(const QString &name) const;
 
-public slots:
-  void registerObject(QObject *object, RegistrationMode mode = Append, const QString &methodPrefix = "handle");
-  void registerEventHandler(EventType event, QObject *object, const char *slot, RegistrationMode mode = Append);
-  void registerEventHandler(QList<EventType> events, QObject *object, const char *slot, RegistrationMode mode = Append);
+  QString enumName(EventType type) const;
 
-  //void sendEvent(Event *event);
+public slots:
+  void registerObject(QObject *object, Priority priority = NormalPriority,
+                      const QString &methodPrefix = "process",
+                      const QString &filterPrefix = "filter");
+  void registerEventHandler(EventType event, QObject *object, const char *slot,
+                            Priority priority = NormalPriority, bool isFilter = false);
+  void registerEventHandler(QList<EventType> events, QObject *object, const char *slot,
+                            Priority priority = NormalPriority, bool isFilter = false);
+
+  void registerEventFilter(EventType event, QObject *object, const char *slot);
+  void registerEventFilter(QList<EventType> events, QObject *object, const char *slot);
+
+  //! Send an event to the registered handlers
+  /**
+    The EventManager takes ownership of the event and will delete it once it's processed.
+    NOTE: This method is not threadsafe!
+    @param event The event to be dispatched
+   */
+  void sendEvent(Event *event);
+
+protected:
+  virtual void customEvent(QEvent *event);
 
 private:
   struct Handler {
     QObject *object;
     int methodIndex;
+    Priority priority;
 
-    explicit Handler(QObject *obj = 0, int method = 0) {
+    explicit Handler(QObject *obj = 0, int method = 0, Priority prio = NormalPriority) {
       object = obj;
       methodIndex = method;
+      priority = prio;
     }
   };
 
-  typedef QHash<EventType, QList<Handler> > HandlerHash;
+  typedef QHash<uint, QList<Handler> > HandlerHash;
 
   inline const HandlerHash &registeredHandlers() const { return _registeredHandlers; }
   inline HandlerHash &registeredHandlers() { return _registeredHandlers; }
+
+  inline const HandlerHash &registeredFilters() const { return _registeredFilters; }
+  inline HandlerHash &registeredFilters() { return _registeredFilters; }
+
+  //! Add handlers to an existing sorted (by priority) handler list
+  void insertHandlers(const QList<Handler> &newHandlers, QList<Handler> &existing, bool checkDupes = false);
+  //! Add filters to an existing filter hash
+  void insertFilters(const QList<Handler> &newFilters, QHash<QObject *, Handler> &existing);
+
+  int findEventType(const QString &methodSignature, const QString &methodPrefix) const;
+
+  void processEvents();
+  void dispatchEvent(Event *event);
+
+  //! @return the EventType enum
+  QMetaEnum eventEnum() const;
+
   HandlerHash _registeredHandlers;
+  HandlerHash _registeredFilters;
+  mutable QMetaEnum _enum;
 
+  QList<Event *> _eventQueue;
 };
 
+Q_DECLARE_OPERATORS_FOR_FLAGS(EventManager::EventFlags);
+
 #endif