aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKitsune Ral <Kitsune-Ral@users.sf.net>2018-05-01 21:01:33 +0900
committerKitsune Ral <Kitsune-Ral@users.sf.net>2018-05-01 21:01:33 +0900
commit1e42eca5c3d864750609eacd4996794c901c6c37 (patch)
tree88a2ca014bfd38bdbd2c30cd3918fc49dd7a7255
parent38934c2310b426be640988dc10f48de88a3d92bc (diff)
parent2a341e30ef2db74b331a8870ceb2f182af68f194 (diff)
downloadlibquotient-1e42eca5c3d864750609eacd4996794c901c6c37.tar.gz
libquotient-1e42eca5c3d864750609eacd4996794c901c6c37.zip
Merge branch 'master' into kitsune-gtad
-rw-r--r--lib/connection.cpp5
-rw-r--r--lib/converters.h21
-rw-r--r--lib/events/event.cpp20
-rw-r--r--lib/events/event.h51
-rw-r--r--lib/events/redactionevent.h2
-rw-r--r--lib/jobs/generated/notifications.cpp2
-rw-r--r--lib/jobs/generated/notifications.h4
-rw-r--r--lib/room.cpp56
-rw-r--r--lib/room.h16
-rw-r--r--lib/user.cpp2
-rw-r--r--lib/user.h3
11 files changed, 110 insertions, 72 deletions
diff --git a/lib/connection.cpp b/lib/connection.cpp
index 5f930d57..adeb7929 100644
--- a/lib/connection.cpp
+++ b/lib/connection.cpp
@@ -306,9 +306,8 @@ void Connection::onSyncSuccess(SyncData &&data) {
{
if (accountEvent->type() == EventType::DirectChat)
{
- const auto usersToDCs =
- unique_ptr_cast<DirectChatEvent>(accountEvent)
- ->usersToDirectChats();
+ const auto usersToDCs = ptrCast<DirectChatEvent>(move(accountEvent))
+ ->usersToDirectChats();
DirectChatsMap removals =
erase_if(d->directChats, [&usersToDCs] (auto it) {
return !usersToDCs.contains(it.key()->id(), it.value());
diff --git a/lib/converters.h b/lib/converters.h
index 22b22f25..cfe9c01c 100644
--- a/lib/converters.h
+++ b/lib/converters.h
@@ -34,6 +34,15 @@ namespace QMatrixClient
#endif
template <typename T>
+ inline QJsonArray toJson(const std::vector<T>& vals)
+ {
+ QJsonArray ar;
+ for (const auto& v: vals)
+ ar.push_back(toJson(v));
+ return ar;
+ }
+
+ template <typename T>
inline QJsonArray toJson(const QVector<T>& vals)
{
QJsonArray ar;
@@ -142,6 +151,18 @@ namespace QMatrixClient
}
};
+ template <typename T> struct FromJson<std::vector<T>>
+ {
+ std::vector<T> operator()(const QJsonValue& jv) const
+ {
+ const auto jsonArray = jv.toArray();
+ std::vector<T> vect; vect.resize(size_t(jsonArray.size()));
+ std::transform(jsonArray.begin(), jsonArray.end(),
+ vect.begin(), FromJson<T>());
+ return vect;
+ }
+ };
+
template <typename T> struct FromJson<QVector<T>>
{
QVector<T> operator()(const QJsonValue& jv) const
diff --git a/lib/events/event.cpp b/lib/events/event.cpp
index 8ddf3945..193250de 100644
--- a/lib/events/event.cpp
+++ b/lib/events/event.cpp
@@ -67,16 +67,17 @@ const QJsonObject Event::contentJson() const
}
template <typename BaseEventT>
-inline BaseEventT* makeIfMatches(const QJsonObject&, const QString&)
+inline event_ptr_tt<BaseEventT> makeIfMatches(const QJsonObject&, const QString&)
{
return nullptr;
}
template <typename BaseEventT, typename EventT, typename... EventTs>
-inline BaseEventT* makeIfMatches(const QJsonObject& o, const QString& selector)
+inline event_ptr_tt<BaseEventT> makeIfMatches(const QJsonObject& o,
+ const QString& selector)
{
if (selector == EventT::TypeId)
- return new EventT(o);
+ return _impl::create<EventT>(o);
return makeIfMatches<BaseEventT, EventTs...>(o, selector);
}
@@ -86,11 +87,11 @@ EventPtr _impl::doMakeEvent<Event>(const QJsonObject& obj)
{
// Check more specific event types first
if (auto e = doMakeEvent<RoomEvent>(obj))
- return EventPtr(move(e));
+ return e;
- return EventPtr { makeIfMatches<Event,
+ return makeIfMatches<Event,
TypingEvent, ReceiptEvent, TagEvent, ReadMarkerEvent, DirectChatEvent>(
- obj, obj["type"].toString()) };
+ obj, obj["type"].toString());
}
RoomEvent::RoomEvent(Event::Type type) : Event(type) { }
@@ -98,10 +99,6 @@ RoomEvent::RoomEvent(Event::Type type) : Event(type) { }
RoomEvent::RoomEvent(Type type, const QJsonObject& rep)
: Event(type, rep)
, _id(rep["event_id"].toString())
-// , _roomId(rep["room_id"].toString())
-// , _senderId(rep["sender"].toString())
-// , _serverTimestamp(
-// QMatrixClient::fromJson<QDateTime>(rep["origin_server_ts"]))
{
// if (_id.isEmpty())
// {
@@ -122,8 +119,7 @@ RoomEvent::RoomEvent(Type type, const QJsonObject& rep)
auto redaction = unsignedData.value("redacted_because");
if (redaction.isObject())
{
- _redactedBecause =
- std::make_unique<RedactionEvent>(redaction.toObject());
+ _redactedBecause = _impl::create<RedactionEvent>(redaction.toObject());
return;
}
diff --git a/lib/events/event.h b/lib/events/event.h
index d614115a..396406f1 100644
--- a/lib/events/event.h
+++ b/lib/events/event.h
@@ -18,22 +18,40 @@
#pragma once
-#include <QtCore/QString>
-#include <QtCore/QDateTime>
-#include <QtCore/QJsonObject>
-#include <QtCore/QJsonArray>
-
+#include "converters.h"
#include "util.h"
-#include <memory>
-
namespace QMatrixClient
{
template <typename EventT>
using event_ptr_tt = std::unique_ptr<EventT>;
+ template <typename EventT>
+ inline EventT* rawPtr(const event_ptr_tt<EventT>& ptr)
+ {
+ return ptr.get();
+ }
+
+ template <typename TargetEventT, typename EventT>
+ inline TargetEventT* weakPtr(const event_ptr_tt<EventT>& ptr)
+ {
+ return static_cast<TargetEventT*>(rawPtr(ptr));
+ }
+
+ template <typename TargetT, typename SourceT>
+ inline event_ptr_tt<TargetT> ptrCast(event_ptr_tt<SourceT>&& ptr)
+ {
+ return unique_ptr_cast<TargetT>(ptr);
+ }
+
namespace _impl
{
+ template <typename EventT, typename... ArgTs>
+ inline event_ptr_tt<EventT> create(ArgTs&&... args)
+ {
+ return std::make_unique<EventT>(std::forward<ArgTs>(args)...);
+ }
+
template <typename EventT>
event_ptr_tt<EventT> doMakeEvent(const QJsonObject& obj);
}
@@ -100,7 +118,7 @@ namespace QMatrixClient
{
auto e = _impl::doMakeEvent<EventT>(obj);
if (!e)
- e = std::make_unique<EventT>(EventType::Unknown, obj);
+ e = _impl::create<EventT>(EventType::Unknown, obj);
return e;
}
@@ -110,6 +128,14 @@ namespace QMatrixClient
EventPtr doMakeEvent<Event>(const QJsonObject& obj);
}
+ template <> struct FromJson<EventPtr>
+ {
+ EventPtr operator()(const QJsonValue& jv) const
+ {
+ return makeEvent<Event>(jv.toObject());
+ }
+ };
+
/**
* \brief A vector of pointers to events with deserialisation capabilities
*
@@ -165,16 +191,16 @@ namespace QMatrixClient
// constructors and destructors
explicit RoomEvent(Type type);
RoomEvent(Type type, const QJsonObject& rep);
- ~RoomEvent();
+ ~RoomEvent() override;
QString id() const { return _id; }
QDateTime timestamp() const;
QString roomId() const;
QString senderId() const;
bool isRedacted() const { return bool(_redactedBecause); }
- const RedactionEvent* redactedBecause() const
+ const event_ptr_tt<RedactionEvent>& redactedBecause() const
{
- return _redactedBecause.get();
+ return _redactedBecause;
}
QString redactionReason() const;
const QString& transactionId() const { return _txnId; }
@@ -202,9 +228,6 @@ namespace QMatrixClient
private:
QString _id;
-// QString _roomId;
-// QString _senderId;
-// QDateTime _serverTimestamp;
event_ptr_tt<RedactionEvent> _redactedBecause;
QString _txnId;
};
diff --git a/lib/events/redactionevent.h b/lib/events/redactionevent.h
index fa6902ab..829b9085 100644
--- a/lib/events/redactionevent.h
+++ b/lib/events/redactionevent.h
@@ -27,7 +27,7 @@ namespace QMatrixClient
public:
static constexpr const char* const TypeId = "m.room.redaction";
- RedactionEvent(const QJsonObject& obj)
+ explicit RedactionEvent(const QJsonObject& obj)
: RoomEvent(Type::Redaction, obj)
, _redactedEvent(obj.value("redacts").toString())
, _reason(contentJson().value("reason").toString())
diff --git a/lib/jobs/generated/notifications.cpp b/lib/jobs/generated/notifications.cpp
index ffd17b8a..df6b10ba 100644
--- a/lib/jobs/generated/notifications.cpp
+++ b/lib/jobs/generated/notifications.cpp
@@ -21,7 +21,7 @@ namespace QMatrixClient
result.actions =
fromJson<QVector<QJsonObject>>(o.value("actions"));
result.event =
- fromJson<GetNotificationsJob::Event>(o.value("event"));
+ fromJson<EventPtr>(o.value("event"));
result.profileTag =
fromJson<QString>(o.value("profile_tag"));
result.read =
diff --git a/lib/jobs/generated/notifications.h b/lib/jobs/generated/notifications.h
index 72318f69..798b9576 100644
--- a/lib/jobs/generated/notifications.h
+++ b/lib/jobs/generated/notifications.h
@@ -22,12 +22,10 @@ namespace QMatrixClient
public:
// Inner data structures
- using Event = EventPtr;
-
struct Notification
{
QVector<QJsonObject> actions;
- Event event;
+ EventPtr event;
QString profileTag;
bool read;
QString roomId;
diff --git a/lib/room.cpp b/lib/room.cpp
index 1fa9212e..a4cfadb4 100644
--- a/lib/room.cpp
+++ b/lib/room.cpp
@@ -55,6 +55,7 @@
using namespace QMatrixClient;
using namespace std::placeholders;
+using std::move;
#if !(defined __GLIBCXX__ && __GLIBCXX__ <= 20150123)
using std::llround;
#endif
@@ -74,7 +75,7 @@ class Room::Private
typedef QMultiHash<QString, User*> members_map_t;
Private(Connection* c, QString id_, JoinState initialJoinState)
- : q(nullptr), connection(c), id(std::move(id_))
+ : q(nullptr), connection(c), id(move(id_))
, joinState(initialJoinState)
{ }
@@ -204,7 +205,7 @@ class Room::Private
* Tries to find an event in the timeline and redact it; deletes the
* redaction event whether the redacted event was found or not.
*/
- void processRedaction(RoomEventPtr redactionEvent);
+ void processRedaction(RoomEventPtr&& redactionEvent);
void broadcastTagUpdates()
{
@@ -228,7 +229,7 @@ class Room::Private
RoomEventPtr TimelineItem::replaceEvent(RoomEventPtr&& other)
{
- return std::exchange(evt, std::move(other));
+ return std::exchange(evt, move(other));
}
Room::Room(Connection* connection, QString id, JoinState initialJoinState)
@@ -711,7 +712,7 @@ Room::Private::getEventWithFile(const QString& eventId) const
if (evtIt != timeline.rend() &&
evtIt->event()->type() == EventType::RoomMessage)
{
- auto* event = static_cast<const RoomMessageEvent*>(evtIt->event());
+ auto* event = evtIt->viewAs<RoomMessageEvent>();
if (event->hasFileContent())
return event;
}
@@ -1286,11 +1287,10 @@ inline bool isRedaction(const RoomEventPtr& e)
return e->type() == EventType::Redaction;
}
-void Room::Private::processRedaction(RoomEventPtr redactionEvent)
+void Room::Private::processRedaction(RoomEventPtr&& redactionEvent)
{
Q_ASSERT(redactionEvent && isRedaction(redactionEvent));
- const auto& redaction =
- static_cast<const RedactionEvent*>(redactionEvent.get());
+ const auto& redaction = ptrCast<RedactionEvent>(move(redactionEvent));
const auto pIdx = eventsIndex.find(redaction->redactedEvent());
if (pIdx == eventsIndex.end())
@@ -1359,9 +1359,9 @@ void Room::Private::processRedaction(RoomEventPtr redactionEvent)
// notify everyone and delete the old event
RoomEventPtr oldEvent
{ ti.replaceEvent(makeEvent<RoomEvent>(originalJson)) };
- q->onRedaction(oldEvent.get(), ti.event());
+ q->onRedaction(*oldEvent, *ti.event());
qCDebug(MAIN) << "Redacted" << oldEvent->id() << "with" << redaction->id();
- emit q->replacedEvent(ti.event(), oldEvent.get());
+ emit q->replacedEvent(ti.event(), rawPtr(oldEvent));
}
Connection* Room::connection() const
@@ -1389,7 +1389,7 @@ void Room::Private::addNewMessageEvents(RoomEvents&& events)
if (!normalEvents.empty())
emit q->aboutToAddNewMessages(normalEvents);
- const auto insertedSize = insertEvents(std::move(normalEvents), Newer);
+ const auto insertedSize = insertEvents(move(normalEvents), Newer);
const auto from = timeline.cend() - insertedSize;
if (insertedSize > 0)
{
@@ -1436,7 +1436,7 @@ void Room::Private::addHistoricalMessageEvents(RoomEvents&& events)
return;
emit q->aboutToAddHistoricalMessages(normalEvents);
- const auto insertedSize = insertEvents(std::move(normalEvents), Older);
+ const auto insertedSize = insertEvents(move(normalEvents), Older);
const auto from = timeline.crend() - insertedSize;
qCDebug(MAIN) << "Room" << displayname << "received" << insertedSize
@@ -1455,25 +1455,24 @@ void Room::processStateEvents(const RoomEvents& events)
bool emitNamesChanged = false;
for (const auto& e: events)
{
- auto* event = e.get();
- switch (event->type())
+ switch (e->type())
{
case EventType::RoomName: {
- auto nameEvent = static_cast<RoomNameEvent*>(event);
+ auto* nameEvent = weakPtr<const RoomNameEvent>(e);
d->name = nameEvent->name();
qCDebug(MAIN) << "Room name updated:" << d->name;
emitNamesChanged = true;
break;
}
case EventType::RoomAliases: {
- auto aliasesEvent = static_cast<RoomAliasesEvent*>(event);
+ auto* aliasesEvent = weakPtr<const RoomAliasesEvent>(e);
d->aliases = aliasesEvent->aliases();
qCDebug(MAIN) << "Room aliases updated:" << d->aliases;
emitNamesChanged = true;
break;
}
case EventType::RoomCanonicalAlias: {
- auto aliasEvent = static_cast<RoomCanonicalAliasEvent*>(event);
+ auto* aliasEvent = weakPtr<const RoomCanonicalAliasEvent>(e);
d->canonicalAlias = aliasEvent->alias();
setObjectName(d->canonicalAlias);
qCDebug(MAIN) << "Room canonical alias updated:" << d->canonicalAlias;
@@ -1481,7 +1480,7 @@ void Room::processStateEvents(const RoomEvents& events)
break;
}
case EventType::RoomTopic: {
- auto topicEvent = static_cast<RoomTopicEvent*>(event);
+ auto* topicEvent = weakPtr<const RoomTopicEvent>(e);
d->topic = topicEvent->topic();
qCDebug(MAIN) << "Room topic updated:" << d->topic;
emit topicChanged();
@@ -1489,7 +1488,7 @@ void Room::processStateEvents(const RoomEvents& events)
}
case EventType::RoomAvatar: {
const auto& avatarEventContent =
- static_cast<RoomAvatarEvent*>(event)->content();
+ weakPtr<const RoomAvatarEvent>(e)->content();
if (d->avatar.updateUrl(avatarEventContent.url))
{
qCDebug(MAIN) << "Room avatar URL updated:"
@@ -1499,7 +1498,7 @@ void Room::processStateEvents(const RoomEvents& events)
break;
}
case EventType::RoomMember: {
- auto memberEvent = static_cast<RoomMemberEvent*>(event);
+ auto* memberEvent = weakPtr<const RoomMemberEvent>(e);
auto u = user(memberEvent->userId());
u->processEvent(memberEvent, this);
if (u == localUser() && memberJoinState(u) == JoinState::Invite
@@ -1540,7 +1539,7 @@ void Room::processStateEvents(const RoomEvents& events)
case EventType::RoomEncryption:
{
d->encryptionAlgorithm =
- static_cast<EncryptionEvent*>(event)->algorithm();
+ weakPtr<const EncryptionEvent>(e)->algorithm();
qCDebug(MAIN) << "Encryption switched on in" << displayName();
emit encryption();
break;
@@ -1554,13 +1553,13 @@ void Room::processStateEvents(const RoomEvents& events)
d->updateDisplayname();
}
-void Room::processEphemeralEvent(EventPtr event)
+void Room::processEphemeralEvent(EventPtr&& event)
{
QElapsedTimer et; et.start();
switch (event->type())
{
case EventType::Typing: {
- auto typingEvent = static_cast<TypingEvent*>(event.get());
+ auto typingEvent = ptrCast<TypingEvent>(move(event));
d->usersTyping.clear();
for( const QString& userId: typingEvent->users() )
{
@@ -1575,7 +1574,7 @@ void Room::processEphemeralEvent(EventPtr event)
break;
}
case EventType::Receipt: {
- auto receiptEvent = static_cast<ReceiptEvent*>(event.get());
+ auto receiptEvent = ptrCast<ReceiptEvent>(move(event));
for( const auto &p: receiptEvent->eventsWithReceipts() )
{
{
@@ -1629,13 +1628,13 @@ void Room::processEphemeralEvent(EventPtr event)
}
}
-void Room::processAccountDataEvent(EventPtr event)
+void Room::processAccountDataEvent(EventPtr&& event)
{
switch (event->type())
{
case EventType::Tag:
{
- auto newTags = static_cast<TagEvent*>(event.get())->tags();
+ auto newTags = ptrCast<const TagEvent>(move(event))->tags();
if (newTags == d->tags)
break;
d->tags = newTags;
@@ -1646,16 +1645,15 @@ void Room::processAccountDataEvent(EventPtr event)
}
case EventType::ReadMarker:
{
- const auto* rmEvent = static_cast<ReadMarkerEvent*>(event.get());
- const auto& readEventId = rmEvent->event_id();
+ auto readEventId =
+ ptrCast<const ReadMarkerEvent>(move(event))->event_id();
qCDebug(MAIN) << "Server-side read marker at" << readEventId;
d->serverReadMarker = readEventId;
const auto newMarker = findInTimeline(readEventId);
if (newMarker != timelineEdge())
d->markMessagesAsRead(newMarker);
- else {
+ else
d->setLastReadEvent(localUser(), readEventId);
- }
break;
}
default:
diff --git a/lib/room.h b/lib/room.h
index 86a7b245..288db5fb 100644
--- a/lib/room.h
+++ b/lib/room.h
@@ -46,10 +46,12 @@ namespace QMatrixClient
using index_t = int;
TimelineItem(RoomEventPtr&& e, index_t number)
- : evt(move(e)), idx(number) { }
+ : evt(std::move(e)), idx(number) { }
- RoomEvent* event() const { return evt.get(); }
- RoomEvent* operator->() const { return evt.operator->(); }
+ const RoomEvent* event() const { return rawPtr(evt); }
+ template <typename EventT>
+ const EventT* viewAs() const { return weakPtr<const EventT>(evt); }
+ const RoomEventPtr& operator->() const { return evt; }
index_t index() const { return idx; }
// Used for event redaction
@@ -407,12 +409,12 @@ namespace QMatrixClient
protected:
virtual void processStateEvents(const RoomEvents& events);
- virtual void processEphemeralEvent(EventPtr event);
- virtual void processAccountDataEvent(EventPtr event);
+ virtual void processEphemeralEvent(EventPtr&& event);
+ virtual void processAccountDataEvent(EventPtr&& event);
virtual void onAddNewTimelineEvents(timeline_iter_t from) { }
virtual void onAddHistoricalTimelineEvents(rev_iter_t from) { }
- virtual void onRedaction(const RoomEvent* prevEvent,
- const RoomEvent* after) { }
+ virtual void onRedaction(const RoomEvent& prevEvent,
+ const RoomEvent& after) { }
private:
class Private;
diff --git a/lib/user.cpp b/lib/user.cpp
index c4fbfe35..91b340d5 100644
--- a/lib/user.cpp
+++ b/lib/user.cpp
@@ -358,7 +358,7 @@ QUrl User::avatarUrl(const Room* room) const
return avatarObject(room).url();
}
-void User::processEvent(RoomMemberEvent* event, const Room* room)
+void User::processEvent(const RoomMemberEvent* event, const Room* room)
{
if (event->membership() != MembershipType::Invite &&
event->membership() != MembershipType::Join)
diff --git a/lib/user.h b/lib/user.h
index f94fbee4..8ac96539 100644
--- a/lib/user.h
+++ b/lib/user.h
@@ -103,7 +103,8 @@ namespace QMatrixClient
QString avatarMediaId(const Room* room = nullptr) const;
QUrl avatarUrl(const Room* room = nullptr) const;
- void processEvent(RoomMemberEvent* event, const Room* r = nullptr);
+ void processEvent(const RoomMemberEvent* event,
+ const Room* r = nullptr);
public slots:
void rename(const QString& newName);