From 86f4119a0502ffefd60abd5963f0d52628ba4e78 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sun, 8 Sep 2019 12:44:46 +0200 Subject: [PATCH] Implement basic ImageMessages in qml timeline I suck at sizing so the images in the message are currently hardcoded to 300 pixels in width... --- resources/qml/TimelineView.qml | 6 ++- resources/qml/delegates/ImageMessage.qml | 14 +++++ resources/res.qrc | 1 + src/MxcImageProvider.h | 1 - src/timeline2/TimelineModel.cpp | 66 ++++++++++++++++++++++++ src/timeline2/TimelineModel.h | 4 ++ 6 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 resources/qml/delegates/ImageMessage.qml diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index 0151686a..399e85eb 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -23,6 +23,8 @@ Rectangle { ListView { id: chat + cacheBuffer: 4*parent.height + visible: timelineManager.timeline != null anchors.fill: parent @@ -40,12 +42,14 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.rightMargin: scrollbar.width + height: loader.height Loader { id: loader + asynchronous: false Layout.fillWidth: true - height: item.height Layout.alignment: Qt.AlignTop + height: item.height source: switch(model.type) { case MtxEvent.Aliases: return "delegates/Aliases.qml" diff --git a/resources/qml/delegates/ImageMessage.qml b/resources/qml/delegates/ImageMessage.qml new file mode 100644 index 00000000..a3bc78e5 --- /dev/null +++ b/resources/qml/delegates/ImageMessage.qml @@ -0,0 +1,14 @@ +import QtQuick 2.6 + +Item { + width: 300 + height: 300 * eventData.proportionalHeight + + Image { + anchors.fill: parent + + source: eventData.url.replace("mxc://", "image://MxcImage/") + asynchronous: true + fillMode: Image.PreserveAspectFit + } +} diff --git a/resources/res.qrc b/resources/res.qrc index 6f6d480a..62ed53e5 100644 --- a/resources/res.qrc +++ b/resources/res.qrc @@ -119,5 +119,6 @@ qml/Avatar.qml qml/delegates/TextMessage.qml qml/delegates/NoticeMessage.qml + qml/delegates/ImageMessage.qml diff --git a/src/MxcImageProvider.h b/src/MxcImageProvider.h index 8710171c..19d8a74e 100644 --- a/src/MxcImageProvider.h +++ b/src/MxcImageProvider.h @@ -45,4 +45,3 @@ public: private: QThreadPool pool; }; - diff --git a/src/timeline2/TimelineModel.cpp b/src/timeline2/TimelineModel.cpp index 310494b4..16f1dfe6 100644 --- a/src/timeline2/TimelineModel.cpp +++ b/src/timeline2/TimelineModel.cpp @@ -58,6 +58,20 @@ eventFormattedBody(const mtx::events::RoomEvent &e) return QString::fromStdString(e.content.body); } +template +QString +eventUrl(const T &) +{ + return ""; +} +template +auto +eventUrl(const mtx::events::RoomEvent &e) + -> std::enable_if_t::value, QString> +{ + return QString::fromStdString(e.content.url); +} + template qml_mtx_events::EventType toRoomEventType(const mtx::events::Event &e) @@ -146,6 +160,41 @@ toRoomEventType(const mtx::events::Event &) } // ::EventType::Type toRoomEventType(const Event &e) { return // ::EventType::LocationMessage; } + +template +uint64_t +eventHeight(const mtx::events::Event &) +{ + return -1; +} +template +auto +eventHeight(const mtx::events::RoomEvent &e) -> decltype(e.content.info.h) +{ + return e.content.info.h; +} +template +uint64_t +eventWidth(const mtx::events::Event &) +{ + return -1; +} +template +auto +eventWidth(const mtx::events::RoomEvent &e) -> decltype(e.content.info.w) +{ + return e.content.info.w; +} + +template +double +eventPropHeight(const mtx::events::RoomEvent &e) +{ + auto w = eventWidth(e); + if (w == 0) + w = 1; + return eventHeight(e) / (double)w; +} } TimelineModel::TimelineModel(QString room_id, QObject *parent) @@ -167,6 +216,10 @@ TimelineModel::roleNames() const {UserId, "userId"}, {UserName, "userName"}, {Timestamp, "timestamp"}, + {Url, "url"}, + {Height, "height"}, + {Width, "width"}, + {ProportionalHeight, "proportionalHeight"}, }; } int @@ -228,6 +281,19 @@ TimelineModel::data(const QModelIndex &index, int role) const return QVariant(utils::replaceEmoji(boost::apply_visitor( [](const auto &e) -> QString { return eventFormattedBody(e); }, events.value(id)))); + case Url: + return QVariant(boost::apply_visitor( + [](const auto &e) -> QString { return eventUrl(e); }, events.value(id))); + case Height: + return QVariant(boost::apply_visitor( + [](const auto &e) -> qulonglong { return eventHeight(e); }, events.value(id))); + case Width: + return QVariant(boost::apply_visitor( + [](const auto &e) -> qulonglong { return eventWidth(e); }, events.value(id))); + case ProportionalHeight: + return QVariant(boost::apply_visitor( + [](const auto &e) -> double { return eventPropHeight(e); }, events.value(id))); + default: return QVariant(); } diff --git a/src/timeline2/TimelineModel.h b/src/timeline2/TimelineModel.h index 954da5eb..66d03cf5 100644 --- a/src/timeline2/TimelineModel.h +++ b/src/timeline2/TimelineModel.h @@ -82,6 +82,10 @@ public: UserId, UserName, Timestamp, + Url, + Height, + Width, + ProportionalHeight, }; QHash roleNames() const override;