From 3ecf762f497a4d4b6ea7583689c0b9b284300201 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 28 Dec 2018 12:47:02 +0900 Subject: EventContent: use qint64 for the payload size --- lib/events/eventcontent.cpp | 8 +++++--- lib/events/eventcontent.h | 6 +++--- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'lib/events') diff --git a/lib/events/eventcontent.cpp b/lib/events/eventcontent.cpp index a6b1c763..bac2b72f 100644 --- a/lib/events/eventcontent.cpp +++ b/lib/events/eventcontent.cpp @@ -17,6 +17,8 @@ */ #include "eventcontent.h" + +#include "converters.h" #include "util.h" #include @@ -30,7 +32,7 @@ QJsonObject Base::toJson() const return o; } -FileInfo::FileInfo(const QUrl& u, int payloadSize, const QMimeType& mimeType, +FileInfo::FileInfo(const QUrl& u, qint64 payloadSize, const QMimeType& mimeType, const QString& originalFilename) : mimeType(mimeType), url(u), payloadSize(payloadSize) , originalName(originalFilename) @@ -41,7 +43,7 @@ FileInfo::FileInfo(const QUrl& u, const QJsonObject& infoJson, : originalInfoJson(infoJson) , mimeType(QMimeDatabase().mimeTypeForName(infoJson["mimetype"_ls].toString())) , url(u) - , payloadSize(infoJson["size"_ls].toInt()) + , payloadSize(fromJson(infoJson["size"_ls])) , originalName(originalFilename) { if (!mimeType.isValid()) @@ -55,7 +57,7 @@ void FileInfo::fillInfoJson(QJsonObject* infoJson) const infoJson->insert(QStringLiteral("mimetype"), mimeType.name()); } -ImageInfo::ImageInfo(const QUrl& u, int fileSize, QMimeType mimeType, +ImageInfo::ImageInfo(const QUrl& u, qint64 fileSize, QMimeType mimeType, const QSize& imageSize) : FileInfo(u, fileSize, mimeType), imageSize(imageSize) { } diff --git a/lib/events/eventcontent.h b/lib/events/eventcontent.h index ea321fb6..2a48e910 100644 --- a/lib/events/eventcontent.h +++ b/lib/events/eventcontent.h @@ -88,7 +88,7 @@ namespace QMatrixClient class FileInfo { public: - explicit FileInfo(const QUrl& u, int payloadSize = -1, + explicit FileInfo(const QUrl& u, qint64 payloadSize = -1, const QMimeType& mimeType = {}, const QString& originalFilename = {}); FileInfo(const QUrl& u, const QJsonObject& infoJson, @@ -109,7 +109,7 @@ namespace QMatrixClient QJsonObject originalInfoJson; QMimeType mimeType; QUrl url; - int payloadSize; + qint64 payloadSize; QString originalName; }; @@ -127,7 +127,7 @@ namespace QMatrixClient class ImageInfo : public FileInfo { public: - explicit ImageInfo(const QUrl& u, int fileSize = -1, + explicit ImageInfo(const QUrl& u, qint64 fileSize = -1, QMimeType mimeType = {}, const QSize& imageSize = {}); ImageInfo(const QUrl& u, const QJsonObject& infoJson, -- cgit v1.2.3 From 4ec3dd92d2cb5af4cf4893770e29db51d23e0e67 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 26 Dec 2018 19:31:11 +0900 Subject: Make content in events editable --- lib/events/eventcontent.h | 2 ++ lib/events/roommessageevent.cpp | 6 +++--- lib/events/roommessageevent.h | 10 ++++++++++ lib/events/stateevent.h | 6 ++++++ 4 files changed, 21 insertions(+), 3 deletions(-) (limited to 'lib/events') diff --git a/lib/events/eventcontent.h b/lib/events/eventcontent.h index 2a48e910..2e61276b 100644 --- a/lib/events/eventcontent.h +++ b/lib/events/eventcontent.h @@ -167,6 +167,7 @@ namespace QMatrixClient explicit TypedBase(const QJsonObject& o = {}) : Base(o) { } virtual QMimeType type() const = 0; virtual const FileInfo* fileInfo() const { return nullptr; } + virtual FileInfo* fileInfo() { return nullptr; } virtual const Thumbnail* thumbnailInfo() const { return nullptr; } }; @@ -196,6 +197,7 @@ namespace QMatrixClient QMimeType type() const override { return InfoT::mimeType; } const FileInfo* fileInfo() const override { return this; } + FileInfo* fileInfo() override { return this; } protected: void fillJson(QJsonObject* json) const override diff --git a/lib/events/roommessageevent.cpp b/lib/events/roommessageevent.cpp index 1c5cf058..572c7173 100644 --- a/lib/events/roommessageevent.cpp +++ b/lib/events/roommessageevent.cpp @@ -71,8 +71,8 @@ MsgType jsonToMsgType(const QString& matrixType) return MsgType::Unknown; } -inline QJsonObject toMsgJson(const QString& plainBody, const QString& jsonMsgType, - TypedBase* content) +QJsonObject RoomMessageEvent::assembleContentJson(const QString& plainBody, + const QString& jsonMsgType, TypedBase* content) { auto json = content ? content->toJson() : QJsonObject(); json.insert(QStringLiteral("msgtype"), jsonMsgType); @@ -86,7 +86,7 @@ static const auto BodyKey = "body"_ls; RoomMessageEvent::RoomMessageEvent(const QString& plainBody, const QString& jsonMsgType, TypedBase* content) : RoomEvent(typeId(), matrixTypeId(), - toMsgJson(plainBody, jsonMsgType, content)) + assembleContentJson(plainBody, jsonMsgType, content)) , _content(content) { } diff --git a/lib/events/roommessageevent.h b/lib/events/roommessageevent.h index 4c29a93e..a4ba6e65 100644 --- a/lib/events/roommessageevent.h +++ b/lib/events/roommessageevent.h @@ -56,6 +56,13 @@ namespace QMatrixClient QString plainBody() const; EventContent::TypedBase* content() const { return _content.data(); } + template + void editContent(VisitorT visitor) + { + visitor(*_content); + editJson()[ContentKeyL] = + assembleContentJson(plainBody(), rawMsgtype(), content()); + } QMimeType mimeType() const; bool hasTextContent() const; bool hasFileContent() const; @@ -64,6 +71,9 @@ namespace QMatrixClient private: QScopedPointer _content; + static QJsonObject assembleContentJson(const QString& plainBody, + const QString& jsonMsgType, EventContent::TypedBase* content); + REGISTER_ENUM(MsgType) }; REGISTER_EVENT_TYPE(RoomMessageEvent) diff --git a/lib/events/stateevent.h b/lib/events/stateevent.h index d82de7e1..d488c0a0 100644 --- a/lib/events/stateevent.h +++ b/lib/events/stateevent.h @@ -88,6 +88,12 @@ namespace QMatrixClient { } const ContentT& content() const { return _content; } + template + void editContent(VisitorT&& visitor) + { + visitor(_content); + editJson()[ContentKeyL] = _content.toJson(); + } [[deprecated("Use prevContent instead")]] const ContentT* prev_content() const { return prevContent(); } const ContentT* prevContent() const -- cgit v1.2.3 From 77830a97e524a4bd27d8cbcd3830cbe450a5755a Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 28 Dec 2018 12:46:13 +0900 Subject: EventContent: only dump to json non-empty/valid values --- lib/events/eventcontent.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'lib/events') diff --git a/lib/events/eventcontent.cpp b/lib/events/eventcontent.cpp index bac2b72f..03880885 100644 --- a/lib/events/eventcontent.cpp +++ b/lib/events/eventcontent.cpp @@ -53,8 +53,10 @@ FileInfo::FileInfo(const QUrl& u, const QJsonObject& infoJson, void FileInfo::fillInfoJson(QJsonObject* infoJson) const { Q_ASSERT(infoJson); - infoJson->insert(QStringLiteral("size"), payloadSize); - infoJson->insert(QStringLiteral("mimetype"), mimeType.name()); + if (payloadSize != -1) + infoJson->insert(QStringLiteral("size"), payloadSize); + if (mimeType.isValid()) + infoJson->insert(QStringLiteral("mimetype"), mimeType.name()); } ImageInfo::ImageInfo(const QUrl& u, qint64 fileSize, QMimeType mimeType, @@ -71,8 +73,10 @@ ImageInfo::ImageInfo(const QUrl& u, const QJsonObject& infoJson, void ImageInfo::fillInfoJson(QJsonObject* infoJson) const { FileInfo::fillInfoJson(infoJson); - infoJson->insert(QStringLiteral("w"), imageSize.width()); - infoJson->insert(QStringLiteral("h"), imageSize.height()); + if (imageSize.width() != -1) + infoJson->insert(QStringLiteral("w"), imageSize.width()); + if (imageSize.height() != -1) + infoJson->insert(QStringLiteral("h"), imageSize.height()); } Thumbnail::Thumbnail(const QJsonObject& infoJson) @@ -82,7 +86,9 @@ Thumbnail::Thumbnail(const QJsonObject& infoJson) void Thumbnail::fillInfoJson(QJsonObject* infoJson) const { - infoJson->insert(QStringLiteral("thumbnail_url"), url.toString()); - infoJson->insert(QStringLiteral("thumbnail_info"), - toInfoJson(*this)); + if (url.isValid()) + infoJson->insert(QStringLiteral("thumbnail_url"), url.toString()); + if (!imageSize.isEmpty()) + infoJson->insert(QStringLiteral("thumbnail_info"), + toInfoJson(*this)); } -- cgit v1.2.3 From 816377ea3c204f22698e1458b815fdd3c3837adc Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 3 Jan 2019 17:57:42 +0900 Subject: More defaults to construct LocationContent and PlayableContent --- lib/events/roommessageevent.cpp | 3 ++- lib/events/roommessageevent.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'lib/events') diff --git a/lib/events/roommessageevent.cpp b/lib/events/roommessageevent.cpp index 572c7173..69969c0f 100644 --- a/lib/events/roommessageevent.cpp +++ b/lib/events/roommessageevent.cpp @@ -200,7 +200,8 @@ void TextContent::fillJson(QJsonObject* json) const } } -LocationContent::LocationContent(const QString& geoUri, const ImageInfo& thumbnail) +LocationContent::LocationContent(const QString& geoUri, + const Thumbnail& thumbnail) : geoUri(geoUri), thumbnail(thumbnail) { } diff --git a/lib/events/roommessageevent.h b/lib/events/roommessageevent.h index a4ba6e65..5657135b 100644 --- a/lib/events/roommessageevent.h +++ b/lib/events/roommessageevent.h @@ -122,7 +122,7 @@ namespace QMatrixClient { public: LocationContent(const QString& geoUri, - const ImageInfo& thumbnail); + const Thumbnail& thumbnail = {}); explicit LocationContent(const QJsonObject& json); QMimeType type() const override; @@ -142,6 +142,7 @@ namespace QMatrixClient class PlayableContent : public ContentT { public: + using ContentT::ContentT; PlayableContent(const QJsonObject& json) : ContentT(json) , duration(ContentT::originalInfoJson["duration"_ls].toInt()) -- cgit v1.2.3 From 2a6cbbff8246dd2f682624d1551facb2813394ad Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 3 Jan 2019 21:08:40 +0900 Subject: RoomMessageEvent: easier creation of file-based events --- lib/events/roommessageevent.cpp | 53 +++++++++++++++++++++++++++++++++++++++++ lib/events/roommessageevent.h | 8 +++++++ 2 files changed, 61 insertions(+) (limited to 'lib/events') diff --git a/lib/events/roommessageevent.cpp b/lib/events/roommessageevent.cpp index 69969c0f..d63ae2fe 100644 --- a/lib/events/roommessageevent.cpp +++ b/lib/events/roommessageevent.cpp @@ -21,6 +21,8 @@ #include "logging.h" #include +#include +#include using namespace QMatrixClient; using namespace EventContent; @@ -95,6 +97,38 @@ RoomMessageEvent::RoomMessageEvent(const QString& plainBody, : RoomMessageEvent(plainBody, msgTypeToJson(msgType), content) { } +TypedBase* contentFromFile(const QFileInfo& file, bool asGenericFile) +{ + auto filePath = file.absoluteFilePath(); + auto localUrl = QUrl::fromLocalFile(filePath); + auto mimeType = QMimeDatabase().mimeTypeForFile(file); + auto payloadSize = file.size(); + if (!asGenericFile) + { + auto mimeTypeName = mimeType.name(); + if (mimeTypeName.startsWith("image/")) + return new ImageContent(localUrl, payloadSize, mimeType, + QImageReader(filePath).size()); + + // duration can only be obtained asynchronously and can only be reliably + // done by starting to play the file. Left for a future implementation. + if (mimeTypeName.startsWith("video/")) + return new VideoContent(localUrl, payloadSize, mimeType); + + if (mimeTypeName.startsWith("audio/")) + return new AudioContent(localUrl, payloadSize, mimeType); + + } + return new FileContent(localUrl, payloadSize, mimeType); +} + +RoomMessageEvent::RoomMessageEvent(const QString& plainBody, + const QFileInfo& file, bool asGenericFile) + : RoomMessageEvent(plainBody, + asGenericFile ? QStringLiteral("m.file") : rawMsgTypeForFile(file), + contentFromFile(file, asGenericFile)) +{ } + RoomMessageEvent::RoomMessageEvent(const QJsonObject& obj) : RoomEvent(typeId(), obj), _content(nullptr) { @@ -162,6 +196,25 @@ bool RoomMessageEvent::hasThumbnail() const return content() && content()->thumbnailInfo(); } +QString rawMsgTypeForMimeType(const QMimeType& mimeType) +{ + auto name = mimeType.name(); + return name.startsWith("image/") ? QStringLiteral("m.image") : + name.startsWith("video/") ? QStringLiteral("m.video") : + name.startsWith("audio/") ? QStringLiteral("m.audio") : + QStringLiteral("m.file"); +} + +QString RoomMessageEvent::rawMsgTypeForUrl(const QUrl& url) +{ + return rawMsgTypeForMimeType(QMimeDatabase().mimeTypeForUrl(url)); +} + +QString RoomMessageEvent::rawMsgTypeForFile(const QFileInfo& fi) +{ + return rawMsgTypeForMimeType(QMimeDatabase().mimeTypeForFile(fi)); +} + TextContent::TextContent(const QString& text, const QString& contentType) : mimeType(QMimeDatabase().mimeTypeForName(contentType)), body(text) { diff --git a/lib/events/roommessageevent.h b/lib/events/roommessageevent.h index 5657135b..d5b570f5 100644 --- a/lib/events/roommessageevent.h +++ b/lib/events/roommessageevent.h @@ -21,6 +21,8 @@ #include "roomevent.h" #include "eventcontent.h" +class QFileInfo; + namespace QMatrixClient { namespace MessageEventContent = EventContent; // Back-compatibility @@ -49,6 +51,9 @@ namespace QMatrixClient explicit RoomMessageEvent(const QString& plainBody, MsgType msgType = MsgType::Text, EventContent::TypedBase* content = nullptr); + explicit RoomMessageEvent(const QString& plainBody, + const QFileInfo& file, + bool asGenericFile = false); explicit RoomMessageEvent(const QJsonObject& obj); MsgType msgtype() const; @@ -68,6 +73,9 @@ namespace QMatrixClient bool hasFileContent() const; bool hasThumbnail() const; + static QString rawMsgTypeForUrl(const QUrl& url); + static QString rawMsgTypeForFile(const QFileInfo& fi); + private: QScopedPointer _content; -- cgit v1.2.3 From e3578b3cc6b978db1c04a1f684e1a03676c33f3b Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sat, 5 Jan 2019 19:59:48 +0900 Subject: EventContent::ImageInfo: support originalFilename in POD constructor It's not mandated by the spec for anything except m.file but hey it's convenient. --- lib/events/eventcontent.cpp | 4 ++-- lib/events/eventcontent.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'lib/events') diff --git a/lib/events/eventcontent.cpp b/lib/events/eventcontent.cpp index 03880885..9a5e872c 100644 --- a/lib/events/eventcontent.cpp +++ b/lib/events/eventcontent.cpp @@ -60,8 +60,8 @@ void FileInfo::fillInfoJson(QJsonObject* infoJson) const } ImageInfo::ImageInfo(const QUrl& u, qint64 fileSize, QMimeType mimeType, - const QSize& imageSize) - : FileInfo(u, fileSize, mimeType), imageSize(imageSize) + const QSize& imageSize, const QString& originalFilename) + : FileInfo(u, fileSize, mimeType, originalFilename), imageSize(imageSize) { } ImageInfo::ImageInfo(const QUrl& u, const QJsonObject& infoJson, diff --git a/lib/events/eventcontent.h b/lib/events/eventcontent.h index 2e61276b..0588c0e2 100644 --- a/lib/events/eventcontent.h +++ b/lib/events/eventcontent.h @@ -129,7 +129,8 @@ namespace QMatrixClient public: explicit ImageInfo(const QUrl& u, qint64 fileSize = -1, QMimeType mimeType = {}, - const QSize& imageSize = {}); + const QSize& imageSize = {}, + const QString& originalFilename = {}); ImageInfo(const QUrl& u, const QJsonObject& infoJson, const QString& originalFilename = {}); -- cgit v1.2.3 From 24c80a57fe1a79289f3028a81d6f8e0ac5f505fe Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sat, 5 Jan 2019 20:06:09 +0900 Subject: API version++; use QMediaResource from QtMultimedia (new dep) to detect m.video resolution The API version number should have been bumped long ago. --- .travis.yml | 1 + CMakeLists.txt | 8 +++++--- lib/events/roommessageevent.cpp | 17 ++++++++++------- libqmatrixclient.pri | 2 +- 4 files changed, 17 insertions(+), 11 deletions(-) (limited to 'lib/events') diff --git a/.travis.yml b/.travis.yml index 0b2967cf..c0e8c097 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,7 @@ addons: packages: - g++-5 - qt57base + - qt57multimedia - valgrind matrix: diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a3193a4..c48a7ba9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,9 @@ foreach (FLAG all "" pedantic extra error=return-type no-unused-parameter no-gnu endif () endforeach () -find_package(Qt5 5.4.1 REQUIRED Network Gui) +# Qt 5.6+ is the formal requirement but for the sake of supporting UBPorts +# upstream Qt 5.4 is required. +find_package(Qt5 5.4.1 REQUIRED Network Gui Multimedia) get_filename_component(Qt5_Prefix "${Qt5_DIR}/../../../.." ABSOLUTE) if (GTAD_PATH) @@ -140,7 +142,7 @@ add_library(QMatrixClient ${libqmatrixclient_SRCS} ${libqmatrixclient_job_SRCS} ${libqmatrixclient_csdef_SRCS} ${libqmatrixclient_cswellknown_SRCS} ${libqmatrixclient_asdef_SRCS} ${libqmatrixclient_isdef_SRCS}) -set(API_VERSION "0.4") +set(API_VERSION "0.5") set_property(TARGET QMatrixClient PROPERTY VERSION "${API_VERSION}.0") set_property(TARGET QMatrixClient PROPERTY SOVERSION ${API_VERSION} ) set_property(TARGET QMatrixClient PROPERTY @@ -152,7 +154,7 @@ target_include_directories(QMatrixClient PUBLIC $ $ ) -target_link_libraries(QMatrixClient Qt5::Core Qt5::Network Qt5::Gui) +target_link_libraries(QMatrixClient Qt5::Core Qt5::Network Qt5::Gui Qt5::Multimedia) add_executable(qmc-example ${example_SRCS}) target_link_libraries(qmc-example Qt5::Core QMatrixClient) diff --git a/lib/events/roommessageevent.cpp b/lib/events/roommessageevent.cpp index d63ae2fe..c3007fa0 100644 --- a/lib/events/roommessageevent.cpp +++ b/lib/events/roommessageevent.cpp @@ -23,6 +23,7 @@ #include #include #include +#include using namespace QMatrixClient; using namespace EventContent; @@ -102,24 +103,26 @@ TypedBase* contentFromFile(const QFileInfo& file, bool asGenericFile) auto filePath = file.absoluteFilePath(); auto localUrl = QUrl::fromLocalFile(filePath); auto mimeType = QMimeDatabase().mimeTypeForFile(file); - auto payloadSize = file.size(); if (!asGenericFile) { auto mimeTypeName = mimeType.name(); if (mimeTypeName.startsWith("image/")) - return new ImageContent(localUrl, payloadSize, mimeType, - QImageReader(filePath).size()); + return new ImageContent(localUrl, file.size(), mimeType, + QImageReader(filePath).size(), + file.fileName()); // duration can only be obtained asynchronously and can only be reliably // done by starting to play the file. Left for a future implementation. if (mimeTypeName.startsWith("video/")) - return new VideoContent(localUrl, payloadSize, mimeType); + return new VideoContent(localUrl, file.size(), mimeType, + QMediaResource(localUrl).resolution(), + file.fileName()); if (mimeTypeName.startsWith("audio/")) - return new AudioContent(localUrl, payloadSize, mimeType); - + return new AudioContent(localUrl, file.size(), mimeType, + file.fileName()); } - return new FileContent(localUrl, payloadSize, mimeType); + return new FileContent(localUrl, file.size(), mimeType, file.fileName()); } RoomMessageEvent::RoomMessageEvent(const QString& plainBody, diff --git a/libqmatrixclient.pri b/libqmatrixclient.pri index 8ca43e56..eefaec67 100644 --- a/libqmatrixclient.pri +++ b/libqmatrixclient.pri @@ -1,4 +1,4 @@ -QT += network +QT += network multimedia CONFIG += c++14 warn_on rtti_off create_prl object_parallel_to_source win32-msvc* { -- cgit v1.2.3