From 958675dccc0a308c02d490d0b246eade0123ce79 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 24 Aug 2016 13:19:37 +0900 Subject: Moved message content classes to a dedicated namespace --- events/roommessageevent.cpp | 26 +++++----- events/roommessageevent.h | 117 +++++++++++++++++++++++--------------------- 2 files changed, 74 insertions(+), 69 deletions(-) (limited to 'events') diff --git a/events/roommessageevent.cpp b/events/roommessageevent.cpp index 48f52453..03e84444 100644 --- a/events/roommessageevent.cpp +++ b/events/roommessageevent.cpp @@ -32,7 +32,7 @@ class RoomMessageEvent::Private QString userId; MessageEventType msgtype; QDateTime hsob_ts; - MessageEventContent* content; + MessageEventContent::Base* content; }; RoomMessageEvent::RoomMessageEvent() @@ -67,9 +67,9 @@ QDateTime RoomMessageEvent::hsob_ts() const return d->hsob_ts; } -MessageEventContent* RoomMessageEvent::content() const +MessageEventContent::Base* RoomMessageEvent::content() const { - return d->content; + return d->content; } RoomMessageEvent* RoomMessageEvent::fromJson(const QJsonObject& obj) @@ -84,28 +84,30 @@ RoomMessageEvent* RoomMessageEvent::fromJson(const QJsonObject& obj) } if( obj.contains("content") ) { + using namespace MessageEventContent; + QJsonObject content = obj.value("content").toObject(); QString msgtype = content.value("msgtype").toString(); if( msgtype == "m.text" ) { e->d->msgtype = MessageEventType::Text; - e->d->content = new MessageEventContent(); + e->d->content = new Base(); } else if( msgtype == "m.emote" ) { e->d->msgtype = MessageEventType::Emote; - e->d->content = new MessageEventContent(); + e->d->content = new Base(); } else if( msgtype == "m.notice" ) { e->d->msgtype = MessageEventType::Notice; - e->d->content = new MessageEventContent(); + e->d->content = new Base(); } else if( msgtype == "m.image" ) { e->d->msgtype = MessageEventType::Image; - ImageEventContent* c = new ImageEventContent; + ImageContent* c = new ImageContent; c->url = QUrl(content.value("url").toString()); QJsonObject info = content.value("info").toObject(); c->height = info.value("h").toInt(); @@ -117,7 +119,7 @@ RoomMessageEvent* RoomMessageEvent::fromJson(const QJsonObject& obj) else if( msgtype == "m.file" ) { e->d->msgtype = MessageEventType::File; - FileEventContent* c = new FileEventContent; + FileContent* c = new FileContent; c->filename = content.value("filename").toString(); c->url = QUrl(content.value("url").toString()); QJsonObject info = content.value("info").toObject(); @@ -128,7 +130,7 @@ RoomMessageEvent* RoomMessageEvent::fromJson(const QJsonObject& obj) else if( msgtype == "m.location" ) { e->d->msgtype = MessageEventType::Location; - LocationEventContent* c = new LocationEventContent; + LocationContent* c = new LocationContent; c->geoUri = content.value("geo_uri").toString(); c->thumbnailUrl = QUrl(content.value("thumbnail_url").toString()); QJsonObject info = content.value("thumbnail_info").toObject(); @@ -141,7 +143,7 @@ RoomMessageEvent* RoomMessageEvent::fromJson(const QJsonObject& obj) else if( msgtype == "m.video" ) { e->d->msgtype = MessageEventType::Video; - VideoEventContent* c = new VideoEventContent; + VideoContent* c = new VideoContent; c->url = QUrl(content.value("url").toString()); QJsonObject info = content.value("info").toObject(); c->height = info.value("h").toInt(); @@ -159,7 +161,7 @@ RoomMessageEvent* RoomMessageEvent::fromJson(const QJsonObject& obj) else if( msgtype == "m.audio" ) { e->d->msgtype = MessageEventType::Audio; - AudioEventContent* c = new AudioEventContent; + AudioContent* c = new AudioContent; c->url = QUrl(content.value("url").toString()); QJsonObject info = content.value("info").toObject(); c->duration = info.value("duration").toInt(); @@ -172,7 +174,7 @@ RoomMessageEvent* RoomMessageEvent::fromJson(const QJsonObject& obj) qDebug() << "RoomMessageEvent: unknown msgtype: " << msgtype; qDebug() << obj; e->d->msgtype = MessageEventType::Unknown; - e->d->content = new MessageEventContent; + e->d->content = new Base; } if( content.contains("body") ) diff --git a/events/roommessageevent.h b/events/roommessageevent.h index b0d5a1cb..219f74f0 100644 --- a/events/roommessageevent.h +++ b/events/roommessageevent.h @@ -30,13 +30,14 @@ namespace QMatrixClient Text, Emote, Notice, Image, File, Location, Video, Audio, Unknown }; - class MessageEventContent + namespace MessageEventContent { - public: - virtual ~MessageEventContent() {} - - QString body; - }; + class Base + { + public: + QString body; + }; + } class RoomMessageEvent: public Event { @@ -49,7 +50,7 @@ namespace QMatrixClient QString body() const; QDateTime hsob_ts() const; - MessageEventContent* content() const; + MessageEventContent::Base* content() const; static RoomMessageEvent* fromJson( const QJsonObject& obj ); @@ -58,61 +59,63 @@ namespace QMatrixClient Private* d; }; - class ImageEventContent: public MessageEventContent + namespace MessageEventContent { - public: - QUrl url; - int height; - int width; - int size; - QString mimetype; - }; - - class FileEventContent: public MessageEventContent - { - public: - QString filename; - QString mimetype; - int size; - QUrl url; - }; + class ImageContent: public Base + { + public: + QUrl url; + int height; + int width; + int size; + QString mimetype; + }; - class LocationEventContent: public MessageEventContent - { - public: - QString geoUri; - int thumbnailHeight; - int thumbnailWidth; - QString thumbnailMimetype; - int thumbnailSize; - QUrl thumbnailUrl; - }; + class FileContent: public Base + { + public: + QString filename; + QString mimetype; + int size; + QUrl url; + }; - class VideoEventContent: public MessageEventContent - { - public: - QUrl url; - int duration; - int width; - int height; - int size; - QString mimetype; - int thumbnailWidth; - int thumbnailHeight; - int thumbnailSize; - QString thumbnailMimetype; - QUrl thumbnailUrl; - }; + class LocationContent: public Base + { + public: + QString geoUri; + int thumbnailHeight; + int thumbnailWidth; + QString thumbnailMimetype; + int thumbnailSize; + QUrl thumbnailUrl; + }; - class AudioEventContent: public MessageEventContent - { - public: - QUrl url; - int size; - int duration; - QString mimetype; - }; + class VideoContent: public Base + { + public: + QUrl url; + int duration; + int width; + int height; + int size; + QString mimetype; + int thumbnailWidth; + int thumbnailHeight; + int thumbnailSize; + QString thumbnailMimetype; + QUrl thumbnailUrl; + }; + class AudioContent: public Base + { + public: + QUrl url; + int size; + int duration; + QString mimetype; + }; + } } #endif // QMATRIXCLIENT_ROOMMESSAGEEVENT_H -- cgit v1.2.3 From 581a6976eeb7c35930cb19e89eae0fd3bf11a785 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 24 Aug 2016 14:29:54 +0900 Subject: Move plain body from Base (former MessageEventContent) inside RoomMessageEvent According to the spec, this key has the same status as msgtype: both should exist in any message. Besides, it's always supposed to be a plain text so there's no polymorphism allowed here. --- events/roommessageevent.cpp | 10 ++++++++-- events/roommessageevent.h | 16 +++++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) (limited to 'events') diff --git a/events/roommessageevent.cpp b/events/roommessageevent.cpp index 03e84444..a111ef12 100644 --- a/events/roommessageevent.cpp +++ b/events/roommessageevent.cpp @@ -31,6 +31,7 @@ class RoomMessageEvent::Private QString userId; MessageEventType msgtype; + QString plainBody; QDateTime hsob_ts; MessageEventContent::Base* content; }; @@ -57,9 +58,14 @@ MessageEventType RoomMessageEvent::msgtype() const return d->msgtype; } +QString RoomMessageEvent::plainBody() const +{ + return d->plainBody; +} + QString RoomMessageEvent::body() const { - return d->content->body; + return plainBody(); } QDateTime RoomMessageEvent::hsob_ts() const @@ -179,7 +185,7 @@ RoomMessageEvent* RoomMessageEvent::fromJson(const QJsonObject& obj) if( content.contains("body") ) { - e->d->content->body = content.value("body").toString(); + e->d->plainBody = content.value("body").toString(); } else { qDebug() << "RoomMessageEvent: body not found"; } diff --git a/events/roommessageevent.h b/events/roommessageevent.h index 219f74f0..27cf5fd8 100644 --- a/events/roommessageevent.h +++ b/events/roommessageevent.h @@ -32,11 +32,7 @@ namespace QMatrixClient namespace MessageEventContent { - class Base - { - public: - QString body; - }; + class Base { }; } class RoomMessageEvent: public Event @@ -47,7 +43,17 @@ namespace QMatrixClient QString userId() const; MessageEventType msgtype() const; + + QString plainBody() const; + + /** + * Same as plainBody() for now; might change for "best-looking body" + * in the future. For richer contents, use content-specific data. + * + * @deprecated + */ QString body() const; + QDateTime hsob_ts() const; MessageEventContent::Base* content() const; -- cgit v1.2.3 From 51dfcc732301b5fe0d8b8b5966b751ff35295ef4 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 24 Aug 2016 17:09:50 +0900 Subject: Drop unused (by code and by spec) hsob_ts value --- events/roommessageevent.cpp | 11 ----------- events/roommessageevent.h | 2 -- 2 files changed, 13 deletions(-) (limited to 'events') diff --git a/events/roommessageevent.cpp b/events/roommessageevent.cpp index a111ef12..f02922b5 100644 --- a/events/roommessageevent.cpp +++ b/events/roommessageevent.cpp @@ -19,7 +19,6 @@ #include "roommessageevent.h" #include -#include #include using namespace QMatrixClient; @@ -32,7 +31,6 @@ class RoomMessageEvent::Private QString userId; MessageEventType msgtype; QString plainBody; - QDateTime hsob_ts; MessageEventContent::Base* content; }; @@ -68,11 +66,6 @@ QString RoomMessageEvent::body() const return plainBody(); } -QDateTime RoomMessageEvent::hsob_ts() const -{ - return d->hsob_ts; -} - MessageEventContent::Base* RoomMessageEvent::content() const { return d->content; @@ -189,10 +182,6 @@ RoomMessageEvent* RoomMessageEvent::fromJson(const QJsonObject& obj) } else { qDebug() << "RoomMessageEvent: body not found"; } -// e->d->hsob_ts = QDateTime::fromMSecsSinceEpoch( content.value("hsoc_ts").toInt() ); -// } else { -// qDebug() << "RoomMessageEvent: hsoc_ts not found"; -// } } return e; } diff --git a/events/roommessageevent.h b/events/roommessageevent.h index 27cf5fd8..af3b6797 100644 --- a/events/roommessageevent.h +++ b/events/roommessageevent.h @@ -54,8 +54,6 @@ namespace QMatrixClient */ QString body() const; - QDateTime hsob_ts() const; - MessageEventContent::Base* content() const; static RoomMessageEvent* fromJson( const QJsonObject& obj ); -- cgit v1.2.3 From 596533a1840961857a51652f89c3a51435794d02 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 24 Aug 2016 18:01:21 +0900 Subject: Introduce TextContent + minor cleanup TextContent is a class to deal with formatted (HTML, RTF, Markdown) text messages. Right now it only supports Vector's non-standard "formatted_body". --- events/roommessageevent.cpp | 32 +++++++++++++++++++++++++------- events/roommessageevent.h | 10 ++++++++++ 2 files changed, 35 insertions(+), 7 deletions(-) (limited to 'events') diff --git a/events/roommessageevent.cpp b/events/roommessageevent.cpp index f02922b5..0da35527 100644 --- a/events/roommessageevent.cpp +++ b/events/roommessageevent.cpp @@ -19,6 +19,7 @@ #include "roommessageevent.h" #include +#include #include using namespace QMatrixClient; @@ -26,7 +27,7 @@ using namespace QMatrixClient; class RoomMessageEvent::Private { public: - Private() {} + Private() : msgtype(MessageEventType::Unknown), content(nullptr) {} QString userId; MessageEventType msgtype; @@ -37,9 +38,7 @@ class RoomMessageEvent::Private RoomMessageEvent::RoomMessageEvent() : Event(EventType::RoomMessage) , d(new Private) -{ - d->content = nullptr; -} +{ } RoomMessageEvent::~RoomMessageEvent() { @@ -91,17 +90,17 @@ RoomMessageEvent* RoomMessageEvent::fromJson(const QJsonObject& obj) if( msgtype == "m.text" ) { e->d->msgtype = MessageEventType::Text; - e->d->content = new Base(); + e->d->content = new TextContent(obj); } else if( msgtype == "m.emote" ) { e->d->msgtype = MessageEventType::Emote; - e->d->content = new Base(); + e->d->content = new TextContent(obj); } else if( msgtype == "m.notice" ) { e->d->msgtype = MessageEventType::Notice; - e->d->content = new Base(); + e->d->content = new TextContent(obj); } else if( msgtype == "m.image" ) { @@ -185,3 +184,22 @@ RoomMessageEvent* RoomMessageEvent::fromJson(const QJsonObject& obj) } return e; } + +using namespace MessageEventContent; + +TextContent::TextContent(const QJsonObject& json) +{ + QMimeDatabase db; + + // Special-casing the custom matrix.org's (actually, Vector's) way + // of sending HTML messages. + if (json["format"].toString() == "org.matrix.custom.html") + { + mimeType = db.mimeTypeForName("text/html"); + body = json["formatted_body"].toString(); + } else { + // Best-guessing from the content + body = json["body"].toString(); + mimeType = db.mimeTypeForData(body.toUtf8()); + } +} diff --git a/events/roommessageevent.h b/events/roommessageevent.h index af3b6797..7b6394ba 100644 --- a/events/roommessageevent.h +++ b/events/roommessageevent.h @@ -20,6 +20,7 @@ #define QMATRIXCLIENT_ROOMMESSAGEEVENT_H #include +#include #include "event.h" @@ -65,6 +66,15 @@ namespace QMatrixClient namespace MessageEventContent { + class TextContent: public Base + { + public: + TextContent(const QJsonObject& json); + + QMimeType mimeType; + QString body; + }; + class ImageContent: public Base { public: -- cgit v1.2.3 From 6a288217f1279fff1867fbd4c2d2b22e44e43d59 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 24 Aug 2016 20:26:43 +0900 Subject: Structured parsing, folded repetitive initialization code --- events/roommessageevent.cpp | 181 +++++++++++++++++++++----------------------- events/roommessageevent.h | 77 +++++++++++-------- 2 files changed, 135 insertions(+), 123 deletions(-) (limited to 'events') diff --git a/events/roommessageevent.cpp b/events/roommessageevent.cpp index 0da35527..513534ad 100644 --- a/events/roommessageevent.cpp +++ b/events/roommessageevent.cpp @@ -70,6 +70,18 @@ MessageEventContent::Base* RoomMessageEvent::content() const return d->content; } +template +MessageEventContent::Base* make(const QJsonObject& json) +{ + return new ContentT(json); +} + +template +MessageEventContent::Base* make2(const QJsonObject& json) +{ + return new ContentT(json["url"].toString(), json["info"].toObject()); +}; + RoomMessageEvent* RoomMessageEvent::fromJson(const QJsonObject& obj) { RoomMessageEvent* e = new RoomMessageEvent(); @@ -82,104 +94,53 @@ RoomMessageEvent* RoomMessageEvent::fromJson(const QJsonObject& obj) } if( obj.contains("content") ) { - using namespace MessageEventContent; - - QJsonObject content = obj.value("content").toObject(); - QString msgtype = content.value("msgtype").toString(); - - if( msgtype == "m.text" ) - { - e->d->msgtype = MessageEventType::Text; - e->d->content = new TextContent(obj); - } - else if( msgtype == "m.emote" ) - { - e->d->msgtype = MessageEventType::Emote; - e->d->content = new TextContent(obj); - } - else if( msgtype == "m.notice" ) - { - e->d->msgtype = MessageEventType::Notice; - e->d->content = new TextContent(obj); - } - else if( msgtype == "m.image" ) - { - e->d->msgtype = MessageEventType::Image; - ImageContent* c = new ImageContent; - c->url = QUrl(content.value("url").toString()); - QJsonObject info = content.value("info").toObject(); - c->height = info.value("h").toInt(); - c->width = info.value("w").toInt(); - c->size = info.value("size").toInt(); - c->mimetype = info.value("mimetype").toString(); - e->d->content = c; - } - else if( msgtype == "m.file" ) - { - e->d->msgtype = MessageEventType::File; - FileContent* c = new FileContent; - c->filename = content.value("filename").toString(); - c->url = QUrl(content.value("url").toString()); - QJsonObject info = content.value("info").toObject(); - c->size = info.value("size").toInt(); - c->mimetype = info.value("mimetype").toString(); - e->d->content = c; - } - else if( msgtype == "m.location" ) + const QJsonObject content = obj["content"].toObject(); + if ( content.contains("msgtype") && content.contains("body") ) { - e->d->msgtype = MessageEventType::Location; - LocationContent* c = new LocationContent; - c->geoUri = content.value("geo_uri").toString(); - c->thumbnailUrl = QUrl(content.value("thumbnail_url").toString()); - QJsonObject info = content.value("thumbnail_info").toObject(); - c->thumbnailHeight = info.value("h").toInt(); - c->thumbnailWidth = info.value("w").toInt(); - c->thumbnailSize = info.value("size").toInt(); - c->thumbnailMimetype = info.value("mimetype").toString(); - e->d->content = c; - } - else if( msgtype == "m.video" ) - { - e->d->msgtype = MessageEventType::Video; - VideoContent* c = new VideoContent; - c->url = QUrl(content.value("url").toString()); - QJsonObject info = content.value("info").toObject(); - c->height = info.value("h").toInt(); - c->width = info.value("w").toInt(); - c->duration = info.value("duration").toInt(); - c->size = info.value("size").toInt(); - c->thumbnailUrl = QUrl(info.value("thumnail_url").toString()); - QJsonObject thumbnailInfo = content.value("thumbnail_info").toObject(); - c->thumbnailHeight = thumbnailInfo.value("h").toInt(); - c->thumbnailWidth = thumbnailInfo.value("w").toInt(); - c->thumbnailSize = thumbnailInfo.value("size").toInt(); - c->thumbnailMimetype = thumbnailInfo.value("mimetype").toString(); - e->d->content = c; - } - else if( msgtype == "m.audio" ) - { - e->d->msgtype = MessageEventType::Audio; - AudioContent* c = new AudioContent; - c->url = QUrl(content.value("url").toString()); - QJsonObject info = content.value("info").toObject(); - c->duration = info.value("duration").toInt(); - c->mimetype = info.value("mimetype").toString(); - c->size = info.value("size").toInt(); - e->d->content = c; + using namespace MessageEventContent; + + e->d->plainBody = content["body"].toString(); + + struct Factory + { + QString jsonTag; + MessageEventType enumTag; + MessageEventContent::Base*(*make)(const QJsonObject& json); + }; + + const Factory factories[] { + { "m.text", MessageEventType::Text, make }, + { "m.emote", MessageEventType::Emote, make }, + { "m.notice", MessageEventType::Notice, make }, + { "m.image", MessageEventType::Image, make }, + { "m.file", MessageEventType::File, make }, + { "m.location", MessageEventType::Location, make }, + { "m.video", MessageEventType::Video, make2 }, + { "m.audio", MessageEventType::Audio, make2 }, + // Insert new message types before this line + }; + + QString msgtype = content.value("msgtype").toString(); + for (auto f: factories) + { + if (msgtype == f.jsonTag) + { + e->d->msgtype = f.enumTag; + e->d->content = f.make(content); + break; + } + } + if (e->d->msgtype == MessageEventType::Unknown) + { + qDebug() << "RoomMessageEvent: unknown msgtype: " << msgtype; + qDebug() << obj; + e->d->content = new Base; + } } else { - qDebug() << "RoomMessageEvent: unknown msgtype: " << msgtype; + qWarning() << "RoomMessageEvent(" << e->id() << "): no body or msgtype"; qDebug() << obj; - e->d->msgtype = MessageEventType::Unknown; - e->d->content = new Base; - } - - if( content.contains("body") ) - { - e->d->plainBody = content.value("body").toString(); - } else { - qDebug() << "RoomMessageEvent: body not found"; } } return e; @@ -203,3 +164,37 @@ TextContent::TextContent(const QJsonObject& json) mimeType = db.mimeTypeForData(body.toUtf8()); } } + +FileInfo::FileInfo(QUrl u, const QJsonObject& infoJson, QString originalFilename) + : url(u) + , fileSize(infoJson["size"].toInt()) + , mimetype(QMimeDatabase().mimeTypeForName(infoJson["mimetype"].toString())) + , originalName(originalFilename) +{ + if (!mimetype.isValid()) + mimetype = QMimeDatabase().mimeTypeForData(QByteArray()); +} + +ImageInfo::ImageInfo(QUrl u, const QJsonObject& infoJson) + : FileInfo(u, infoJson) + , imageSize(infoJson["w"].toInt(), infoJson["h"].toInt()) +{ } + +LocationContent::LocationContent(const QJsonObject& json) + : geoUri(json["geo_uri"].toString()) + , thumbnail(json["thumbnail_url"].toString(), + json["thumbnail_info"].toObject()) +{ } + +VideoContent::VideoContent(QUrl u, const QJsonObject& infoJson) + : FileInfo(u, infoJson) + , duration(infoJson["duration"].toInt()) + , imageSize(infoJson["w"].toInt(), infoJson["h"].toInt()) + , thumbnail(infoJson["thumbnail_url"].toString(), + infoJson["thumbnail_info"].toObject()) +{ } + +AudioContent::AudioContent(QUrl u, const QJsonObject& infoJson) + : FileInfo(u, infoJson) + , duration(infoJson["duration"].toInt()) +{ } diff --git a/events/roommessageevent.h b/events/roommessageevent.h index 7b6394ba..83022b4d 100644 --- a/events/roommessageevent.h +++ b/events/roommessageevent.h @@ -21,6 +21,7 @@ #include #include +#include #include "event.h" @@ -66,6 +67,10 @@ namespace QMatrixClient namespace MessageEventContent { + // The below structures fairly follow CS spec 11.2.1.6. The overall + // set of attributes for each content types is a superset of the spec + // but specific aggregation structure is altered. + class TextContent: public Base { public: @@ -75,59 +80,71 @@ namespace QMatrixClient QString body; }; - class ImageContent: public Base + class FileInfo: public Base { public: + FileInfo(QUrl u, const QJsonObject& infoJson, + QString originalFilename = QString()); + QUrl url; - int height; - int width; - int size; - QString mimetype; + int fileSize; + QMimeType mimetype; + QString originalName; }; - class FileContent: public Base + class ImageInfo: public FileInfo { public: - QString filename; - QString mimetype; - int size; - QUrl url; + ImageInfo(QUrl u, const QJsonObject& infoJson); + + QSize imageSize; }; + template + class ThumbnailedContent: public ContentInfoT + { + public: + ThumbnailedContent(const QJsonObject& json) + : ContentInfoT(json["url"].toString(), json["info"].toObject()) + , thumbnail(json["thumbnail_url"].toString(), + json["thumbnail_info"].toObject()) + { } + + ImageInfo thumbnail; + }; + + using ImageContent = ThumbnailedContent; + using FileContent = ThumbnailedContent; + class LocationContent: public Base { public: + LocationContent(const QJsonObject& json); + QString geoUri; - int thumbnailHeight; - int thumbnailWidth; - QString thumbnailMimetype; - int thumbnailSize; - QUrl thumbnailUrl; + ImageInfo thumbnail; }; - class VideoContent: public Base + // The spec structures m.video messages differently for some reason - + // instead of putting a thumbnail block on the top level, as with + // file and image, it puts it inside "info" key. So instead of + // using ThumbnailContent<> base, we add the thumbnail into VideoInfo explicitly. + class VideoContent: public FileInfo { public: - QUrl url; + VideoContent(QUrl u, const QJsonObject& infoJson); + int duration; - int width; - int height; - int size; - QString mimetype; - int thumbnailWidth; - int thumbnailHeight; - int thumbnailSize; - QString thumbnailMimetype; - QUrl thumbnailUrl; + QSize imageSize; + ImageInfo thumbnail; }; - class AudioContent: public Base + class AudioContent: public FileInfo { public: - QUrl url; - int size; + AudioContent(QUrl u, const QJsonObject& infoJson); + int duration; - QString mimetype; }; } } -- cgit v1.2.3 From 32ff7cd24bda52c889fd969a43adcf1f845b6e3a Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Mon, 29 Aug 2016 09:02:59 +0900 Subject: Align AudioContent with the rest; special-case creation of VideoContent only The spec is told to allow any event to have a thumbnail in future, and the thumbnail will reside under "content" JSON key rather than "info". --- events/roommessageevent.cpp | 33 +++++++++++++++++++-------------- events/roommessageevent.h | 15 ++++++--------- 2 files changed, 25 insertions(+), 23 deletions(-) (limited to 'events') diff --git a/events/roommessageevent.cpp b/events/roommessageevent.cpp index 513534ad..09465238 100644 --- a/events/roommessageevent.cpp +++ b/events/roommessageevent.cpp @@ -65,21 +65,30 @@ QString RoomMessageEvent::body() const return plainBody(); } -MessageEventContent::Base* RoomMessageEvent::content() const +using namespace MessageEventContent; + +Base* RoomMessageEvent::content() const { return d->content; } template -MessageEventContent::Base* make(const QJsonObject& json) +Base* make(const QJsonObject& json) { return new ContentT(json); } -template -MessageEventContent::Base* make2(const QJsonObject& json) +Base* makeVideoContent(const QJsonObject& json) { - return new ContentT(json["url"].toString(), json["info"].toObject()); + auto c = new VideoContent(json); + // Only for m.video, the spec puts a thumbnail inside "info" JSON key. Once + // this is fixed, VideoContent creation will switch to make<>(). + const QJsonObject infoJson = json["info"].toObject(); + if (infoJson.contains("thumbnail_url")) + c->thumbnail = ImageInfo(infoJson["thumbnail_url"].toString(), + infoJson["thumbnail_info"].toObject()); + + return c; }; RoomMessageEvent* RoomMessageEvent::fromJson(const QJsonObject& obj) @@ -97,15 +106,13 @@ RoomMessageEvent* RoomMessageEvent::fromJson(const QJsonObject& obj) const QJsonObject content = obj["content"].toObject(); if ( content.contains("msgtype") && content.contains("body") ) { - using namespace MessageEventContent; - e->d->plainBody = content["body"].toString(); struct Factory { QString jsonTag; MessageEventType enumTag; - MessageEventContent::Base*(*make)(const QJsonObject& json); + Base*(*make)(const QJsonObject& json); }; const Factory factories[] { @@ -115,8 +122,8 @@ RoomMessageEvent* RoomMessageEvent::fromJson(const QJsonObject& obj) { "m.image", MessageEventType::Image, make }, { "m.file", MessageEventType::File, make }, { "m.location", MessageEventType::Location, make }, - { "m.video", MessageEventType::Video, make2 }, - { "m.audio", MessageEventType::Audio, make2 }, + { "m.video", MessageEventType::Video, makeVideoContent }, + { "m.audio", MessageEventType::Audio, make }, // Insert new message types before this line }; @@ -186,15 +193,13 @@ LocationContent::LocationContent(const QJsonObject& json) json["thumbnail_info"].toObject()) { } -VideoContent::VideoContent(QUrl u, const QJsonObject& infoJson) +VideoInfo::VideoInfo(QUrl u, const QJsonObject& infoJson) : FileInfo(u, infoJson) , duration(infoJson["duration"].toInt()) , imageSize(infoJson["w"].toInt(), infoJson["h"].toInt()) - , thumbnail(infoJson["thumbnail_url"].toString(), - infoJson["thumbnail_info"].toObject()) { } -AudioContent::AudioContent(QUrl u, const QJsonObject& infoJson) +AudioInfo::AudioInfo(QUrl u, const QJsonObject& infoJson) : FileInfo(u, infoJson) , duration(infoJson["duration"].toInt()) { } diff --git a/events/roommessageevent.h b/events/roommessageevent.h index 83022b4d..591b2df9 100644 --- a/events/roommessageevent.h +++ b/events/roommessageevent.h @@ -125,27 +125,24 @@ namespace QMatrixClient ImageInfo thumbnail; }; - // The spec structures m.video messages differently for some reason - - // instead of putting a thumbnail block on the top level, as with - // file and image, it puts it inside "info" key. So instead of - // using ThumbnailContent<> base, we add the thumbnail into VideoInfo explicitly. - class VideoContent: public FileInfo + class VideoInfo: public FileInfo { public: - VideoContent(QUrl u, const QJsonObject& infoJson); + VideoInfo(QUrl u, const QJsonObject& infoJson); int duration; QSize imageSize; - ImageInfo thumbnail; }; + using VideoContent = ThumbnailedContent; - class AudioContent: public FileInfo + class AudioInfo: public FileInfo { public: - AudioContent(QUrl u, const QJsonObject& infoJson); + AudioInfo(QUrl u, const QJsonObject& infoJson); int duration; }; + using AudioContent = ThumbnailedContent; } } -- cgit v1.2.3