diff --git a/src/timeline/TimelineView.cc b/src/timeline/TimelineView.cc
index e9c5b017..35140df0 100644
--- a/src/timeline/TimelineView.cc
+++ b/src/timeline/TimelineView.cc
@@ -23,6 +23,7 @@
#include "ChatPage.h"
#include "Config.h"
#include "FloatingButton.h"
+#include "InfoMessage.hpp"
#include "Logging.hpp"
#include "Olm.hpp"
#include "UserSettingsPage.h"
@@ -36,55 +37,19 @@
using TimelineEvent = mtx::events::collections::TimelineEvents;
-DateSeparator::DateSeparator(QDateTime datetime, QWidget *parent)
- : QWidget{parent}
+//! Retrieve the timestamp of the event represented by the given widget.
+QDateTime
+getDate(QWidget *widget)
{
- auto now = QDateTime::currentDateTime();
- auto days = now.daysTo(datetime);
+ auto item = qobject_cast<TimelineItem *>(widget);
+ if (item)
+ return item->descriptionMessage().datetime;
- font_.setWeight(60);
- font_.setPixelSize(conf::timeline::fonts::dateSeparator);
+ auto infoMsg = qobject_cast<InfoMessage *>(widget);
+ if (infoMsg)
+ return infoMsg->datetime();
- QString fmt;
-
- if (now.date().year() != datetime.date().year())
- fmt = QString("ddd d MMMM yy");
- else
- fmt = QString("ddd d MMMM");
-
- if (days == 0)
- msg_ = tr("Today");
- else if (std::abs(days) == 1)
- msg_ = tr("Yesterday");
- else
- msg_ = datetime.toString(fmt);
-
- QFontMetrics fm{font_};
- width_ = fm.width(msg_) + HPadding * 2;
- height_ = fm.ascent() + 2 * VPadding;
-
- setFixedHeight(height_ + 2 * HMargin);
-}
-
-void
-DateSeparator::paintEvent(QPaintEvent *)
-{
- QPainter p(this);
- p.setRenderHint(QPainter::Antialiasing);
- p.setFont(font_);
-
- // Center the box horizontally & vertically.
- auto textRegion = QRectF(width() / 2 - width_ / 2, HMargin, width_, height_);
-
- QPainterPath ppath;
- ppath.addRoundedRect(textRegion, height_ / 2, height_ / 2);
-
- p.setPen(Qt::NoPen);
- p.fillPath(ppath, boxColor());
- p.drawPath(ppath);
-
- p.setPen(QPen(textColor()));
- p.drawText(textRegion, Qt::AlignCenter, msg_);
+ return QDateTime();
}
TimelineView::TimelineView(const mtx::responses::Timeline &timeline,
@@ -231,7 +196,7 @@ TimelineView::addBackwardsEvents(const mtx::responses::Messages &msgs)
isPaginationInProgress_ = false;
}
-TimelineItem *
+QWidget *
TimelineView::parseMessageEvent(const mtx::events::collections::TimelineEvents &event,
TimelineDirection direction)
{
@@ -255,6 +220,12 @@ TimelineView::parseMessageEvent(const mtx::events::collections::TimelineEvents &
});
return nullptr;
+ } else if (mpark::holds_alternative<StateEvent<state::Encryption>>(event)) {
+ auto msg = mpark::get<StateEvent<state::Encryption>>(event);
+ auto item = new InfoMessage(tr("Encryption is enabled"), this);
+ item->saveDatetime(QDateTime::fromMSecsSinceEpoch(msg.origin_server_ts));
+
+ return item;
} else if (mpark::holds_alternative<RoomEvent<msg::Audio>>(event)) {
auto audio = mpark::get<RoomEvent<msg::Audio>>(event);
return processMessageEvent<AudioEvent, AudioItem>(audio, direction);
@@ -280,13 +251,18 @@ TimelineView::parseMessageEvent(const mtx::events::collections::TimelineEvents &
return processMessageEvent<Sticker, StickerItem>(mpark::get<Sticker>(event),
direction);
} else if (mpark::holds_alternative<EncryptedEvent<msg::Encrypted>>(event)) {
- auto res = parseEncryptedEvent(mpark::get<EncryptedEvent<msg::Encrypted>>(event));
- auto item = parseMessageEvent(res.event, direction);
+ auto res = parseEncryptedEvent(mpark::get<EncryptedEvent<msg::Encrypted>>(event));
+ auto widget = parseMessageEvent(res.event, direction);
- if (item != nullptr && res.isDecrypted)
+ if (widget == nullptr)
+ return nullptr;
+
+ auto item = qobject_cast<TimelineItem *>(widget);
+
+ if (item && res.isDecrypted)
item->markReceived(true);
- return item;
+ return widget;
}
return nullptr;
@@ -374,7 +350,7 @@ TimelineView::renderBottomEvents(const std::vector<TimelineEvent> &events)
int counter = 0;
for (const auto &event : events) {
- TimelineItem *item = parseMessageEvent(event, TimelineDirection::Bottom);
+ QWidget *item = parseMessageEvent(event, TimelineDirection::Bottom);
if (item != nullptr) {
addTimelineItem(item, TimelineDirection::Bottom);
@@ -395,7 +371,7 @@ TimelineView::renderBottomEvents(const std::vector<TimelineEvent> &events)
void
TimelineView::renderTopEvents(const std::vector<TimelineEvent> &events)
{
- std::vector<TimelineItem *> items;
+ std::vector<QWidget *> items;
// Reset the sender of the first message in the timeline
// cause we're about to insert a new one.
@@ -408,7 +384,7 @@ TimelineView::renderTopEvents(const std::vector<TimelineEvent> &events)
while (ii != 0) {
--ii;
- TimelineItem *item = parseMessageEvent(events[ii], TimelineDirection::Top);
+ auto item = parseMessageEvent(events[ii], TimelineDirection::Top);
if (item != nullptr)
items.push_back(item);
@@ -429,9 +405,16 @@ TimelineView::renderTopEvents(const std::vector<TimelineEvent> &events)
// If this batch is the first being rendered (i.e the first and the last
// events originate from this batch), set the last sender.
- if (lastSender_.isEmpty() && !items.empty())
- saveLastMessageInfo(items.at(0)->descriptionMessage().userid,
- items.at(0)->descriptionMessage().datetime);
+ if (lastSender_.isEmpty() && !items.empty()) {
+ for (const auto &w : items) {
+ auto timelineItem = qobject_cast<TimelineItem *>(w);
+ if (timelineItem) {
+ saveLastMessageInfo(timelineItem->descriptionMessage().userid,
+ timelineItem->descriptionMessage().datetime);
+ break;
+ }
+ }
+ }
}
void
@@ -569,17 +552,16 @@ TimelineView::isSenderRendered(const QString &user_id,
}
void
-TimelineView::addTimelineItem(TimelineItem *item, TimelineDirection direction)
+TimelineView::addTimelineItem(QWidget *item, TimelineDirection direction)
{
- const auto newDate = item->descriptionMessage().datetime;
+ const auto newDate = getDate(item);
if (direction == TimelineDirection::Bottom) {
const auto lastItemPosition = scroll_layout_->count() - 1;
- auto lastItem =
- qobject_cast<TimelineItem *>(scroll_layout_->itemAt(lastItemPosition)->widget());
+ const auto lastItem = scroll_layout_->itemAt(lastItemPosition)->widget();
if (lastItem) {
- auto oldDate = lastItem->descriptionMessage().datetime;
+ const auto oldDate = getDate(lastItem);
if (oldDate.daysTo(newDate) != 0) {
auto separator = new DateSeparator(newDate, this);
@@ -594,11 +576,10 @@ TimelineView::addTimelineItem(TimelineItem *item, TimelineDirection direction)
// The first item (position 0) is a stretch widget that pushes
// the widgets to the bottom of the page.
if (scroll_layout_->count() > 1) {
- auto firstItem =
- qobject_cast<TimelineItem *>(scroll_layout_->itemAt(1)->widget());
+ const auto firstItem = scroll_layout_->itemAt(1)->widget();
if (firstItem) {
- auto oldDate = firstItem->descriptionMessage().datetime;
+ const auto oldDate = getDate(firstItem);
if (newDate.daysTo(oldDate) != 0) {
auto separator = new DateSeparator(oldDate);
diff --git a/src/ui/InfoMessage.cpp b/src/ui/InfoMessage.cpp
new file mode 100644
index 00000000..b150e61b
--- /dev/null
+++ b/src/ui/InfoMessage.cpp
@@ -0,0 +1,79 @@
+#include "Config.h"
+#include "InfoMessage.hpp"
+
+#include <QDateTime>
+#include <QPainter>
+#include <QPen>
+
+constexpr int VPadding = 6;
+constexpr int HPadding = 12;
+constexpr int HMargin = 20;
+
+InfoMessage::InfoMessage(QWidget *parent)
+ : QWidget{parent}
+{
+ font_.setWeight(60);
+ font_.setPixelSize(conf::timeline::fonts::dateSeparator);
+}
+
+InfoMessage::InfoMessage(QString msg, QWidget *parent)
+ : QWidget{parent}
+ , msg_{msg}
+{
+ font_.setWeight(60);
+ font_.setPixelSize(conf::timeline::fonts::dateSeparator);
+
+ QFontMetrics fm{font_};
+ width_ = fm.width(msg_) + HPadding * 2;
+ height_ = fm.ascent() + 2 * VPadding;
+
+ setFixedHeight(height_ + 2 * HMargin);
+}
+
+void
+InfoMessage::paintEvent(QPaintEvent *)
+{
+ QPainter p(this);
+ p.setRenderHint(QPainter::Antialiasing);
+ p.setFont(font_);
+
+ // Center the box horizontally & vertically.
+ auto textRegion = QRectF(width() / 2 - width_ / 2, HMargin, width_, height_);
+
+ QPainterPath ppath;
+ ppath.addRoundedRect(textRegion, height_ / 2, height_ / 2);
+
+ p.setPen(Qt::NoPen);
+ p.fillPath(ppath, boxColor());
+ p.drawPath(ppath);
+
+ p.setPen(QPen(textColor()));
+ p.drawText(textRegion, Qt::AlignCenter, msg_);
+}
+
+DateSeparator::DateSeparator(QDateTime datetime, QWidget *parent)
+ : InfoMessage{parent}
+{
+ auto now = QDateTime::currentDateTime();
+ auto days = now.daysTo(datetime);
+
+ QString fmt;
+
+ if (now.date().year() != datetime.date().year())
+ fmt = QString("ddd d MMMM yy");
+ else
+ fmt = QString("ddd d MMMM");
+
+ if (days == 0)
+ msg_ = tr("Today");
+ else if (std::abs(days) == 1)
+ msg_ = tr("Yesterday");
+ else
+ msg_ = datetime.toString(fmt);
+
+ QFontMetrics fm{font_};
+ width_ = fm.width(msg_) + HPadding * 2;
+ height_ = fm.ascent() + 2 * VPadding;
+
+ setFixedHeight(height_ + 2 * HMargin);
+}
|