Use templates for the TimelineItem generation

This commit is contained in:
Konstantinos Sideris 2017-11-30 13:19:34 +02:00
parent deb1a6e292
commit 5663c58dd9
2 changed files with 90 additions and 139 deletions

View file

@ -18,6 +18,7 @@
#pragma once #pragma once
#include <QApplication> #include <QApplication>
#include <QDebug>
#include <QLayout> #include <QLayout>
#include <QList> #include <QList>
#include <QQueue> #include <QQueue>
@ -90,15 +91,6 @@ public:
const QString &room_id, const QString &room_id,
QWidget *parent = 0); QWidget *parent = 0);
// For events with custom display widgets.
template<class Event, class Widget>
TimelineItem *createTimelineItem(const Event &event, bool withSender);
// For events without custom display widgets.
// TODO: All events should have custom widgets.
template<class Event>
TimelineItem *createTimelineItem(const Event &event, bool withSender);
// Add new events at the end of the timeline. // Add new events at the end of the timeline.
int addEvents(const Timeline &timeline); int addEvents(const Timeline &timeline);
void addUserMessage(matrix::events::MessageEventType ty, const QString &msg); void addUserMessage(matrix::events::MessageEventType ty, const QString &msg);
@ -141,6 +133,22 @@ private:
void readLastEvent() const; void readLastEvent() const;
QString getLastEventId() const; QString getLastEventId() const;
template<class Event, class Widget>
TimelineItem *processMessageEvent(const QJsonObject &event, TimelineDirection direction);
// TODO: Remove this eventually.
template<class Event>
TimelineItem *processMessageEvent(const QJsonObject &event, TimelineDirection direction);
// For events with custom display widgets.
template<class Event, class Widget>
TimelineItem *createTimelineItem(const Event &event, bool withSender);
// For events without custom display widgets.
// TODO: All events should have custom widgets.
template<class Event>
TimelineItem *createTimelineItem(const Event &event, bool withSender);
// Used to determine whether or not we should prefix a message with the // Used to determine whether or not we should prefix a message with the
// sender's name. // sender's name.
bool isSenderRendered(const QString &user_id, TimelineDirection direction); bool isSenderRendered(const QString &user_id, TimelineDirection direction);
@ -238,3 +246,65 @@ TimelineView::createTimelineItem(const Event &event, bool withSender)
return item; return item;
} }
template<class Event>
TimelineItem *
TimelineView::processMessageEvent(const QJsonObject &data, TimelineDirection direction)
{
Event event;
try {
event.deserialize(data);
} catch (const DeserializationException &e) {
qWarning() << e.what() << data;
return nullptr;
}
if (isDuplicate(event.eventId()))
return nullptr;
eventIds_[event.eventId()] = true;
QString txnid = event.unsignedData().transactionId();
if (!txnid.isEmpty() && isPendingMessage(txnid, event.sender(), local_user_)) {
removePendingMessage(txnid);
return nullptr;
}
auto with_sender = isSenderRendered(event.sender(), direction);
updateLastSender(event.sender(), direction);
return createTimelineItem<Event>(event, with_sender);
}
template<class Event, class Widget>
TimelineItem *
TimelineView::processMessageEvent(const QJsonObject &data, TimelineDirection direction)
{
Event event;
try {
event.deserialize(data);
} catch (const DeserializationException &e) {
qWarning() << e.what() << data;
return nullptr;
}
if (isDuplicate(event.eventId()))
return nullptr;
eventIds_[event.eventId()] = true;
QString txnid = event.unsignedData().transactionId();
if (!txnid.isEmpty() && isPendingMessage(txnid, event.sender(), local_user_)) {
removePendingMessage(txnid);
return nullptr;
}
auto with_sender = isSenderRendered(event.sender(), direction);
updateLastSender(event.sender(), direction);
return createTimelineItem<Event, Widget>(event, with_sender);
}

View file

@ -16,7 +16,6 @@
*/ */
#include <QApplication> #include <QApplication>
#include <QDebug>
#include <QFileInfo> #include <QFileInfo>
#include <QTimer> #include <QTimer>
@ -229,140 +228,22 @@ TimelineView::parseMessageEvent(const QJsonObject &event, TimelineDirection dire
if (ty == events::EventType::RoomMessage) { if (ty == events::EventType::RoomMessage) {
events::MessageEventType msg_type = events::extractMessageEventType(event); events::MessageEventType msg_type = events::extractMessageEventType(event);
if (msg_type == events::MessageEventType::Text) {
events::MessageEvent<msgs::Text> text;
try {
text.deserialize(event);
} catch (const DeserializationException &e) {
qWarning() << e.what() << event;
return nullptr;
}
if (isDuplicate(text.eventId()))
return nullptr;
eventIds_[text.eventId()] = true;
QString txnid = text.unsignedData().transactionId();
if (!txnid.isEmpty() &&
isPendingMessage(txnid, text.sender(), local_user_)) {
removePendingMessage(txnid);
return nullptr;
}
auto with_sender = isSenderRendered(text.sender(), direction);
updateLastSender(text.sender(), direction);
using Text = events::MessageEvent<msgs::Text>;
return createTimelineItem<Text>(text, with_sender);
} else if (msg_type == events::MessageEventType::Notice) {
events::MessageEvent<msgs::Notice> notice;
try {
notice.deserialize(event);
} catch (const DeserializationException &e) {
qWarning() << e.what() << event;
return nullptr;
}
if (isDuplicate(notice.eventId()))
return nullptr;
eventIds_[notice.eventId()] = true;
auto with_sender = isSenderRendered(notice.sender(), direction);
updateLastSender(notice.sender(), direction);
using Notice = events::MessageEvent<msgs::Notice>;
return createTimelineItem<Notice>(notice, with_sender);
} else if (msg_type == events::MessageEventType::Image) {
events::MessageEvent<msgs::Image> img;
try {
img.deserialize(event);
} catch (const DeserializationException &e) {
qWarning() << e.what() << event;
return nullptr;
}
if (isDuplicate(img.eventId()))
return nullptr;
eventIds_[img.eventId()] = true;
QString txnid = img.unsignedData().transactionId();
if (!txnid.isEmpty() &&
isPendingMessage(txnid, img.sender(), local_user_)) {
removePendingMessage(txnid);
return nullptr;
}
auto with_sender = isSenderRendered(img.sender(), direction);
updateLastSender(img.sender(), direction);
using Image = events::MessageEvent<msgs::Image>;
return createTimelineItem<Image, ImageItem>(img, with_sender);
} else if (msg_type == events::MessageEventType::Emote) {
events::MessageEvent<msgs::Emote> emote;
try {
emote.deserialize(event);
} catch (const DeserializationException &e) {
qWarning() << e.what() << event;
return nullptr;
}
if (isDuplicate(emote.eventId()))
return nullptr;
eventIds_[emote.eventId()] = true;
QString txnid = emote.unsignedData().transactionId();
if (!txnid.isEmpty() &&
isPendingMessage(txnid, emote.sender(), local_user_)) {
removePendingMessage(txnid);
return nullptr;
}
auto with_sender = isSenderRendered(emote.sender(), direction);
updateLastSender(emote.sender(), direction);
using Emote = events::MessageEvent<msgs::Emote>; using Emote = events::MessageEvent<msgs::Emote>;
return createTimelineItem<Emote>(emote, with_sender);
} else if (msg_type == events::MessageEventType::File) {
events::MessageEvent<msgs::File> file;
try {
file.deserialize(event);
} catch (const DeserializationException &e) {
qWarning() << e.what() << event;
return nullptr;
}
if (isDuplicate(file.eventId()))
return nullptr;
eventIds_[file.eventId()] = true;
QString txnid = file.unsignedData().transactionId();
if (!txnid.isEmpty() &&
isPendingMessage(txnid, file.sender(), local_user_)) {
removePendingMessage(txnid);
return nullptr;
}
auto withSender = isSenderRendered(file.sender(), direction);
updateLastSender(file.sender(), direction);
using File = events::MessageEvent<msgs::File>; using File = events::MessageEvent<msgs::File>;
return createTimelineItem<File, FileItem>(file, withSender); using Image = events::MessageEvent<msgs::Image>;
using Notice = events::MessageEvent<msgs::Notice>;
using Text = events::MessageEvent<msgs::Text>;
if (msg_type == events::MessageEventType::Text) {
return processMessageEvent<Text>(event, direction);
} else if (msg_type == events::MessageEventType::Notice) {
return processMessageEvent<Notice>(event, direction);
} else if (msg_type == events::MessageEventType::Image) {
return processMessageEvent<Image, ImageItem>(event, direction);
} else if (msg_type == events::MessageEventType::Emote) {
return processMessageEvent<Emote>(event, direction);
} else if (msg_type == events::MessageEventType::File) {
return processMessageEvent<File, FileItem>(event, direction);
} else if (msg_type == events::MessageEventType::Unknown) { } else if (msg_type == events::MessageEventType::Unknown) {
// TODO Handle redacted messages. // TODO Handle redacted messages.
// Silenced for now. // Silenced for now.