They are no longer scheduled individualy but processed immediately
when they are generated. this should prohibit quassel from messing
with the space time continuum.
14 files changed:
#include "event.h"
#include "ircevent.h"
#include "event.h"
#include "ircevent.h"
-EventManager::EventManager(QObject *parent) : QObject(parent) {
-
-}
-
-EventManager::~EventManager() {
- // pending events won't be delivered anymore, but we do need to delete them
- qDeleteAll(_eventQueue);
+// ============================================================
+// 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() const {
}
QMetaEnum EventManager::eventEnum() const {
-// not threadsafe! if we should want that, we need to add a mutexed queue somewhere in this general area.
-void EventManager::sendEvent(Event *event) {
- // qDebug() << "Sending" << event;
- _eventQueue.append(event);
- if(_eventQueue.count() == 1) // we're not currently processing another event
- processEvents();
+void EventManager::postEvent(Event *event) {
+ if(sender() && sender()->thread() != this->thread()) {
+ QueuedQuasselEvent *queuedEvent = new QueuedQuasselEvent(event);
+ QCoreApplication::postEvent(this, queuedEvent);
+ } else {
+ if(_eventQueue.isEmpty())
+ // we're currently not processing events
+ processEvent(event);
+ else
+ _eventQueue.append(event);
+ }
}
void EventManager::customEvent(QEvent *event) {
if(event->type() == QEvent::User) {
}
void EventManager::customEvent(QEvent *event) {
if(event->type() == QEvent::User) {
+ QueuedQuasselEvent *queuedEvent = static_cast<QueuedQuasselEvent *>(event);
+ processEvent(queuedEvent->event);
-void EventManager::processEvents() {
- // we only process one event at a time for now, and let Qt's own event processing come in between
- if(_eventQueue.isEmpty())
- return;
- dispatchEvent(_eventQueue.first());
- _eventQueue.removeFirst();
- if(_eventQueue.count())
- QCoreApplication::postEvent(this, new QEvent(QEvent::User));
- else
- emit eventQueueEmptied();
+void EventManager::processEvent(Event *event) {
+ Q_ASSERT(_eventQueue.isEmpty());
+ dispatchEvent(event);
+ // dispatching the event might cause new events to be generated. we process those afterwards.
+ while(!_eventQueue.isEmpty()) {
+ dispatchEvent(_eventQueue.first());
+ _eventQueue.removeFirst();
+ }
}
void EventManager::dispatchEvent(Event *event) {
}
void EventManager::dispatchEvent(Event *event) {
};
EventManager(QObject *parent = 0);
};
EventManager(QObject *parent = 0);
- virtual ~EventManager();
EventType eventTypeByName(const QString &name) const;
EventType eventGroupByName(const QString &name) const;
EventType eventTypeByName(const QString &name) const;
EventType eventGroupByName(const QString &name) const;
//! Send an event to the registered handlers
/**
The EventManager takes ownership of the event and will delete it once it's processed.
//! 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
*/
@param event The event to be dispatched
*/
- void sendEvent(Event *event);
-
-signals:
- void eventQueueEmptied();
+ void postEvent(Event *event);
protected:
virtual void customEvent(QEvent *event);
protected:
virtual void customEvent(QEvent *event);
int findEventType(const QString &methodSignature, const QString &methodPrefix) const;
int findEventType(const QString &methodSignature, const QString &methodPrefix) const;
+ void processEvent(Event *event);
void dispatchEvent(Event *event);
//! @return the EventType enum
void dispatchEvent(Event *event);
//! @return the EventType enum
HandlerHash _registeredHandlers;
HandlerHash _registeredFilters;
mutable QMetaEnum _enum;
HandlerHash _registeredHandlers;
HandlerHash _registeredFilters;
mutable QMetaEnum _enum;
QList<Event *> _eventQueue;
};
QList<Event *> _eventQueue;
};
connect(&socket, SIGNAL(encrypted()), this, SLOT(socketInitialized()));
connect(&socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(sslErrors(const QList<QSslError> &)));
#endif
connect(&socket, SIGNAL(encrypted()), this, SLOT(socketInitialized()));
connect(&socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(sslErrors(const QList<QSslError> &)));
#endif
+ connect(this, SIGNAL(newEvent(Event *)), coreSession()->eventManager(), SLOT(postEvent(Event *)));
}
CoreNetwork::~CoreNetwork() {
}
CoreNetwork::~CoreNetwork() {
#else
event->setTimestamp(QDateTime::currentDateTime().toUTC());
#endif
#else
event->setTimestamp(QDateTime::currentDateTime().toUTC());
#endif
- coreSession()->eventManager()->sendEvent(event);
class CoreIdentity;
class CoreUserInputHandler;
class CoreIgnoreListManager;
class CoreIdentity;
class CoreUserInputHandler;
class CoreIgnoreListManager;
class CoreNetwork : public Network {
SYNCABLE_OBJECT
class CoreNetwork : public Network {
SYNCABLE_OBJECT
void quitRequested(NetworkId networkId);
void sslErrors(const QVariant &errorData);
void quitRequested(NetworkId networkId);
void sslErrors(const QVariant &errorData);
+ void newEvent(Event *event);
+
protected:
inline virtual IrcChannel *ircChannelFactory(const QString &channelname) { return new CoreIrcChannel(channelname, this); }
inline virtual IrcUser *ircUserFactory(const QString &hostmask) { return new CoreIrcUser(hostmask, this); }
protected:
inline virtual IrcChannel *ircChannelFactory(const QString &channelname) { return new CoreIrcChannel(channelname, this); }
inline virtual IrcUser *ircUserFactory(const QString &hostmask) { return new CoreIrcUser(hostmask, this); }
_ctcpParser(new CtcpParser(this)),
_ircParser(new IrcParser(this)),
scriptEngine(new QScriptEngine(this)),
_ctcpParser(new CtcpParser(this)),
_ircParser(new IrcParser(this)),
scriptEngine(new QScriptEngine(this)),
+ _processMessages(false),
_ignoreListManager(this)
{
SignalProxy *p = signalProxy();
_ignoreListManager(this)
{
SignalProxy *p = signalProxy();
loadSettings();
initScriptEngine();
loadSettings();
initScriptEngine();
- connect(eventManager(), SIGNAL(eventQueueEmptied()), SLOT(processMessages()));
eventManager()->registerObject(ircParser(), EventManager::NormalPriority);
eventManager()->registerObject(sessionEventProcessor(), EventManager::HighPriority); // needs to process events *before* the stringifier!
eventManager()->registerObject(ctcpParser(), EventManager::NormalPriority);
eventManager()->registerObject(ircParser(), EventManager::NormalPriority);
eventManager()->registerObject(sessionEventProcessor(), EventManager::HighPriority); // needs to process events *before* the stringifier!
eventManager()->registerObject(ctcpParser(), EventManager::NormalPriority);
CoreNetwork *net = network(bufinfo.networkId());
if(net) {
net->userInput(bufinfo, msg);
CoreNetwork *net = network(bufinfo.networkId());
if(net) {
net->userInput(bufinfo, msg);
- // FIXME as soon as user input is event-based
- // until then, user input doesn't trigger a message queue flush!
- processMessages();
} else {
qWarning() << "Trying to send to unconnected network:" << msg;
}
} else {
qWarning() << "Trying to send to unconnected network:" << msg;
}
return;
_messageQueue << rawMsg;
return;
_messageQueue << rawMsg;
+ if(!_processMessages) {
+ _processMessages = true;
+ QCoreApplication::postEvent(this, new ProcessMessagesEvent());
+ }
}
void CoreSession::recvStatusMsgFromServer(QString msg) {
}
void CoreSession::recvStatusMsgFromServer(QString msg) {
return Core::requestBuffers(user());
}
return Core::requestBuffers(user());
}
-void CoreSession::processMessages() {
- if(_messageQueue.isEmpty())
+void CoreSession::customEvent(QEvent *event) {
+ if(event->type() != QEvent::User)
+ processMessages();
+ event->accept();
+}
+
+void CoreSession::processMessages() {
if(_messageQueue.count() == 1) {
const RawMessage &rawMsg = _messageQueue.first();
bool createBuffer = !(rawMsg.flags & Message::Redirected);
if(_messageQueue.count() == 1) {
const RawMessage &rawMsg = _messageQueue.first();
bool createBuffer = !(rawMsg.flags & Message::Redirected);
emit displayMsg(messages[i]);
}
}
emit displayMsg(messages[i]);
}
}
+ _processMessages = false;
void networkRemoved(NetworkId);
void networkDisconnected(NetworkId);
void networkRemoved(NetworkId);
void networkDisconnected(NetworkId);
+protected:
+ virtual void customEvent(QEvent *event);
+
private slots:
void removeClient(QIODevice *dev);
void recvStatusMsgFromServer(QString msg);
void recvMessageFromServer(NetworkId networkId, Message::Type, BufferInfo::Type, const QString &target, const QString &text, const QString &sender = "", Message::Flags flags = Message::None);
private slots:
void removeClient(QIODevice *dev);
void recvStatusMsgFromServer(QString msg);
void recvMessageFromServer(NetworkId networkId, Message::Type, BufferInfo::Type, const QString &target, const QString &text, const QString &sender = "", Message::Flags flags = Message::None);
- void processMessages();
void destroyNetwork(NetworkId);
void destroyNetwork(NetworkId);
void saveSessionState() const;
private:
void saveSessionState() const;
private:
+ void processMessages();
+
void loadSettings();
void initScriptEngine();
void loadSettings();
void initScriptEngine();
QScriptEngine *scriptEngine;
QList<RawMessage> _messageQueue;
QScriptEngine *scriptEngine;
QList<RawMessage> _messageQueue;
CoreIgnoreListManager _ignoreListManager;
};
CoreIgnoreListManager _ignoreListManager;
};
_coreSession(session)
{
connect(coreSession(), SIGNAL(networkDisconnected(NetworkId)), this, SLOT(destroyNetsplits(NetworkId)));
_coreSession(session)
{
connect(coreSession(), SIGNAL(networkDisconnected(NetworkId)), this, SLOT(destroyNetsplits(NetworkId)));
+ connect(this, SIGNAL(newEvent(Event *)), coreSession()->eventManager(), SLOT(postEvent(Event *)));
}
bool CoreSessionEventProcessor::checkParamCount(IrcEvent *e, int minParams) {
}
bool CoreSessionEventProcessor::checkParamCount(IrcEvent *e, int minParams) {
MessageEvent *msgEvent = new MessageEvent(Message::Error, e->network(),
tr("No free and valid nicks in nicklist found. use: /nick <othernick> to continue"),
QString(), QString(), Message::None, e->timestamp());
MessageEvent *msgEvent = new MessageEvent(Message::Error, e->network(),
tr("No free and valid nicks in nicklist found. use: /nick <othernick> to continue"),
QString(), QString(), Message::None, e->timestamp());
- coreSession()->eventManager()->sendEvent(msgEvent);
+ emit newEvent(msgEvent);
return;
} else {
nextNick = errnick + "_";
return;
} else {
nextNick = errnick + "_";
ircChannel->joinIrcUsers(ircUsers, newModes);
NetworkSplitEvent *event = new NetworkSplitEvent(EventManager::NetworkSplitJoin, net, channel, newUsers, quitMessage);
ircChannel->joinIrcUsers(ircUsers, newModes);
NetworkSplitEvent *event = new NetworkSplitEvent(EventManager::NetworkSplitJoin, net, channel, newUsers, quitMessage);
- coreSession()->eventManager()->sendEvent(event);
}
void CoreSessionEventProcessor::handleNetsplitQuit(Network *net, const QString &channel, const QStringList &users, const QString& quitMessage) {
NetworkSplitEvent *event = new NetworkSplitEvent(EventManager::NetworkSplitQuit, net, channel, users, quitMessage);
}
void CoreSessionEventProcessor::handleNetsplitQuit(Network *net, const QString &channel, const QStringList &users, const QString& quitMessage) {
NetworkSplitEvent *event = new NetworkSplitEvent(EventManager::NetworkSplitQuit, net, channel, users, quitMessage);
- coreSession()->eventManager()->sendEvent(event);
foreach(QString user, users) {
IrcUser *iu = net->ircUser(nickFromMask(user));
if(iu)
foreach(QString user, users) {
IrcUser *iu = net->ircUser(nickFromMask(user));
if(iu)
ircChannel->joinIrcUsers(ircUsers, newModes);
foreach(NetworkEvent *event, events) {
event->setFlag(EventManager::Fake); // ignore this in here!
ircChannel->joinIrcUsers(ircUsers, newModes);
foreach(NetworkEvent *event, events) {
event->setFlag(EventManager::Fake); // ignore this in here!
- coreSession()->eventManager()->sendEvent(event);
Q_INVOKABLE void handleCtcpVersion(CtcpEvent *event);
Q_INVOKABLE void defaultHandler(const QString &ctcpCmd, CtcpEvent *event);
Q_INVOKABLE void handleCtcpVersion(CtcpEvent *event);
Q_INVOKABLE void defaultHandler(const QString &ctcpCmd, CtcpEvent *event);
+signals:
+ void newEvent(Event *event);
+
protected:
bool checkParamCount(IrcEvent *event, int minParams);
inline CoreNetwork *coreNetwork(NetworkEvent *e) const { return qobject_cast<CoreNetwork *>(e->network()); }
protected:
bool checkParamCount(IrcEvent *event, int minParams);
inline CoreNetwork *coreNetwork(NetworkEvent *e) const { return qobject_cast<CoreNetwork *>(e->network()); }
QByteArray XQUOTE = QByteArray("\134");
_ctcpXDelimDequoteHash[XQUOTE + XQUOTE] = XQUOTE;
_ctcpXDelimDequoteHash[XQUOTE + QByteArray("a")] = XDELIM;
QByteArray XQUOTE = QByteArray("\134");
_ctcpXDelimDequoteHash[XQUOTE + XQUOTE] = XQUOTE;
_ctcpXDelimDequoteHash[XQUOTE + QByteArray("a")] = XDELIM;
+
+ connect(this, SIGNAL(newEvent(Event *)), _coreSession->eventManager(), SLOT(postEvent(Event *)));
}
void CtcpParser::displayMsg(NetworkEvent *event, Message::Type msgType, const QString &msg, const QString &sender,
}
void CtcpParser::displayMsg(NetworkEvent *event, Message::Type msgType, const QString &msg, const QString &sender,
MessageEvent *msgEvent = new MessageEvent(msgType, event->network(), msg, sender, target, msgFlags);
msgEvent->setTimestamp(event->timestamp());
MessageEvent *msgEvent = new MessageEvent(msgType, event->network(), msg, sender, target, msgFlags);
msgEvent->setTimestamp(event->timestamp());
- coreSession()->eventManager()->sendEvent(msgEvent);
+ emit newEvent(msgEvent);
}
QByteArray CtcpParser::lowLevelQuote(const QByteArray &message) {
}
QByteArray CtcpParser::lowLevelQuote(const QByteArray &message) {
ctcptype, "INVALID", QString(), e->timestamp(), uuid);
ctcpEvents << flushEvent;
foreach(CtcpEvent *event, ctcpEvents) {
ctcptype, "INVALID", QString(), e->timestamp(), uuid);
ctcpEvents << flushEvent;
foreach(CtcpEvent *event, ctcpEvents) {
- coreSession()->eventManager()->sendEvent(event);
Q_INVOKABLE void sendCtcpEvent(CtcpEvent *event);
Q_INVOKABLE void sendCtcpEvent(CtcpEvent *event);
+signals:
+ void newEvent(Event *event);
+
protected:
inline CoreNetwork *coreNetwork(NetworkEvent *e) const { return qobject_cast<CoreNetwork *>(e->network()); }
protected:
inline CoreNetwork *coreNetwork(NetworkEvent *e) const { return qobject_cast<CoreNetwork *>(e->network()); }
_coreSession(parent),
_whois(false)
{
_coreSession(parent),
_whois(false)
{
+ connect(this, SIGNAL(newMessageEvent(Event *)), coreSession()->eventManager(), SLOT(postEvent(Event *)));
}
void EventStringifier::displayMsg(NetworkEvent *event, Message::Type msgType, const QString &msg, const QString &sender,
}
void EventStringifier::displayMsg(NetworkEvent *event, Message::Type msgType, const QString &msg, const QString &sender,
return;
MessageEvent *msgEvent = createMessageEvent(event, msgType, msg, sender, target, msgFlags);
return;
MessageEvent *msgEvent = createMessageEvent(event, msgType, msg, sender, target, msgFlags);
- sendMessageEvent(msgEvent);
+ //sendMessageEvent(msgEvent);
+ emit newMessageEvent(msgEvent);
}
MessageEvent *EventStringifier::createMessageEvent(NetworkEvent *event, Message::Type msgType, const QString &msg, const QString &sender,
}
MessageEvent *EventStringifier::createMessageEvent(NetworkEvent *event, Message::Type msgType, const QString &msg, const QString &sender,
-void EventStringifier::sendMessageEvent(MessageEvent *event) {
- coreSession()->eventManager()->sendEvent(event);
-}
-
bool EventStringifier::checkParamCount(IrcEvent *e, int minParams) {
if(e->params().count() < minParams) {
if(e->type() == EventManager::IrcEventNumeric) {
bool EventStringifier::checkParamCount(IrcEvent *e, int minParams) {
if(e->params().count() < minParams) {
if(e->type() == EventManager::IrcEventNumeric) {
const QString &target = QString(),
Message::Flags msgFlags = Message::None);
const QString &target = QString(),
Message::Flags msgFlags = Message::None);
+signals:
+ void newMessageEvent(Event *event);
+
private:
bool checkParamCount(IrcEvent *event, int minParams);
private:
bool checkParamCount(IrcEvent *event, int minParams);
- void sendMessageEvent(MessageEvent *event);
CoreSession *_coreSession;
bool _whois;
CoreSession *_coreSession;
bool _whois;
QObject(session),
_coreSession(session)
{
QObject(session),
_coreSession(session)
{
+ connect(this, SIGNAL(newEvent(Event *)), coreSession()->eventManager(), SLOT(postEvent(Event *)));
}
bool IrcParser::checkParamCount(const QString &cmd, const QList<QByteArray> ¶ms, int minParams) {
}
bool IrcParser::checkParamCount(const QString &cmd, const QList<QByteArray> ¶ms, int minParams) {
QList<Event *> events;
EventManager::EventType type = EventManager::Invalid;
QList<Event *> events;
EventManager::EventType type = EventManager::Invalid;
- // numeric replies have the target as first param (RFC 2812 - 2.4). this is usually our own nick. Remove this!
uint num = cmd.toUInt();
if(num > 0) {
uint num = cmd.toUInt();
if(num > 0) {
if(params.count() == 0) {
qWarning() << "Message received from server violates RFC and is ignored!" << msg;
return;
}
if(params.count() == 0) {
qWarning() << "Message received from server violates RFC and is ignored!" << msg;
return;
}
+ // numeric replies have the target as first param (RFC 2812 - 2.4). this is usually our own nick. Remove this!
target = net->serverDecode(params.takeFirst());
type = EventManager::IrcEventNumeric;
} else {
target = net->serverDecode(params.takeFirst());
type = EventManager::IrcEventNumeric;
} else {
+ // any other irc command
QString typeName = QLatin1String("IrcEvent") + cmd.at(0).toUpper() + cmd.mid(1).toLower();
type = eventManager()->eventTypeByName(typeName);
if(type == EventManager::Invalid) {
QString typeName = QLatin1String("IrcEvent") + cmd.at(0).toUpper() + cmd.mid(1).toLower();
type = eventManager()->eventTypeByName(typeName);
if(type == EventManager::Invalid) {
}
foreach(Event *event, events) {
}
foreach(Event *event, events) {
- coreSession()->eventManager()->sendEvent(event);
inline CoreSession *coreSession() const { return _coreSession; }
inline EventManager *eventManager() const { return coreSession()->eventManager(); }
inline CoreSession *coreSession() const { return _coreSession; }
inline EventManager *eventManager() const { return coreSession()->eventManager(); }
+signals:
+ void newEvent(Event *);
+
protected:
Q_INVOKABLE void processNetworkIncoming(NetworkDataEvent *e);
protected:
Q_INVOKABLE void processNetworkIncoming(NetworkDataEvent *e);