ed12462d8590e95fd99bb342e65413548f28c104
[quassel.git] / src / common / event.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2020 by the Quassel Project                        *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) version 3.                                           *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
19  ***************************************************************************/
20
21 #include "ctcpevent.h"
22 #include "ircevent.h"
23 #include "messageevent.h"
24 #include "networkevent.h"
25 #include "peer.h"
26 #include "signalproxy.h"
27
28 Event::Event(EventManager::EventType type)
29     : _type(type)
30 {}
31
32 Event::Event(EventManager::EventType type, QVariantMap& map)
33     : _type(type)
34 {
35     if (!map.contains("flags") || !map.contains("timestamp")) {
36         qWarning() << "Received invalid serialized event:" << map;
37         setValid(false);
38         return;
39     }
40
41     Q_ASSERT(SignalProxy::current());
42     Q_ASSERT(SignalProxy::current()->sourcePeer());
43
44     setFlags(static_cast<EventManager::EventFlags>(map.take("flags").toInt()));  // TODO sanity check?
45
46     if (SignalProxy::current()->sourcePeer()->hasFeature(Quassel::Feature::LongTime)) {
47         // timestamp is a qint64, signed rather than unsigned
48         setTimestamp(QDateTime::fromMSecsSinceEpoch(map.take("timestamp").toLongLong()));
49     }
50     else {
51         setTimestamp(QDateTime::fromTime_t(map.take("timestamp").toUInt()));
52     }
53 }
54
55 void Event::toVariantMap(QVariantMap& map) const
56 {
57     Q_ASSERT(SignalProxy::current());
58     Q_ASSERT(SignalProxy::current()->targetPeer());
59
60     map["type"] = static_cast<int>(type());
61     map["flags"] = static_cast<int>(flags());
62     if (SignalProxy::current()->targetPeer()->hasFeature(Quassel::Feature::LongTime)) {
63         // toMSecs returns a qint64, signed rather than unsigned
64         map["timestamp"] = timestamp().toMSecsSinceEpoch();
65     }
66     else {
67         map["timestamp"] = timestamp().toTime_t();
68     }
69 }
70
71 QVariantMap Event::toVariantMap() const
72 {
73     QVariantMap map;
74     toVariantMap(map);
75     return map;
76 }
77
78 Event* Event::fromVariantMap(QVariantMap& map, Network* network)
79 {
80     int inttype = map.take("type").toInt();
81     // sanity check if we have a valid enum value
82     if (EventManager::enumName(inttype).isEmpty()) {
83         qWarning() << "Received a serialized event with unknown type" << inttype;
84         return nullptr;
85     }
86
87     auto type = static_cast<EventManager::EventType>(inttype);
88     if (type == EventManager::Invalid || type == EventManager::GenericEvent)
89         return nullptr;
90
91     auto group = static_cast<EventManager::EventType>(type & EventManager::EventGroupMask);
92
93     Event* e = nullptr;
94
95     // we use static create() functions to keep group-specific special cases in the files they belong
96     // e.g. IrcEventRawMessage
97     switch (group) {
98     case EventManager::NetworkEvent:
99         e = NetworkEvent::create(type, map, network);
100         break;
101     case EventManager::IrcServerEvent:
102         // not in use!
103         break;
104     case EventManager::IrcEvent:
105         e = IrcEvent::create(type, map, network);
106         break;
107     case EventManager::MessageEvent:
108         e = MessageEvent::create(type, map, network);
109         break;
110     case EventManager::CtcpEvent:
111         e = CtcpEvent::create(type, map, network);
112         break;
113     default:
114         break;
115     }
116
117     if (!e) {
118         qWarning() << "Can't create event of type" << type;
119         return nullptr;
120     }
121
122     if (!map.isEmpty()) {
123         qWarning() << "Event creation from map did not consume all data:" << map;
124     }
125
126     return e;
127 }
128
129 QDebug operator<<(QDebug dbg, Event* e)
130 {
131     dbg.nospace() << qPrintable(e->className()) << "("
132                   << "type = 0x" << qPrintable(QString::number(e->type(), 16));
133     e->debugInfo(dbg);
134     //<< ", data = " << e->data(); // we don't use data anywhere yet
135     dbg.nospace() << ", flags = 0x" << qPrintable(QString::number(e->flags(), 16)) << ")";
136     return dbg.space();
137 }