diff --git a/src/TimelineView.cc b/src/TimelineView.cc
index 80afcfa2..114e5fda 100644
--- a/src/TimelineView.cc
+++ b/src/TimelineView.cc
@@ -32,455 +32,457 @@
#include "TimelineViewManager.h"
namespace events = matrix::events;
-namespace msgs = matrix::events::messages;
+namespace msgs = matrix::events::messages;
TimelineView::TimelineView(const Timeline &timeline,
- QSharedPointer<MatrixClient> client,
- const QString &room_id,
- QWidget *parent)
+ QSharedPointer<MatrixClient> client,
+ const QString &room_id,
+ QWidget *parent)
: QWidget(parent)
, room_id_{ room_id }
, client_{ client }
{
- QSettings settings;
- local_user_ = settings.value("auth/user_id").toString();
+ QSettings settings;
+ local_user_ = settings.value("auth/user_id").toString();
- init();
- addEvents(timeline);
+ init();
+ addEvents(timeline);
}
-TimelineView::TimelineView(QSharedPointer<MatrixClient> client, const QString &room_id, QWidget *parent)
+TimelineView::TimelineView(QSharedPointer<MatrixClient> client,
+ const QString &room_id,
+ QWidget *parent)
: QWidget(parent)
, room_id_{ room_id }
, client_{ client }
{
- QSettings settings;
- local_user_ = settings.value("auth/user_id").toString();
+ QSettings settings;
+ local_user_ = settings.value("auth/user_id").toString();
- init();
- client_->messages(room_id_, "");
+ init();
+ client_->messages(room_id_, "");
}
void
TimelineView::sliderRangeChanged(int min, int max)
{
- Q_UNUSED(min);
+ Q_UNUSED(min);
- if (!scroll_area_->verticalScrollBar()->isVisible()) {
- scroll_area_->verticalScrollBar()->setValue(max);
- return;
- }
+ if (!scroll_area_->verticalScrollBar()->isVisible()) {
+ scroll_area_->verticalScrollBar()->setValue(max);
+ return;
+ }
- if (max - scroll_area_->verticalScrollBar()->value() < SCROLL_BAR_GAP)
- scroll_area_->verticalScrollBar()->setValue(max);
+ if (max - scroll_area_->verticalScrollBar()->value() < SCROLL_BAR_GAP)
+ scroll_area_->verticalScrollBar()->setValue(max);
- if (isPaginationScrollPending_) {
- isPaginationScrollPending_ = false;
+ if (isPaginationScrollPending_) {
+ isPaginationScrollPending_ = false;
- int currentHeight = scroll_widget_->size().height();
- int diff = currentHeight - oldHeight_;
- int newPosition = oldPosition_ + diff;
+ int currentHeight = scroll_widget_->size().height();
+ int diff = currentHeight - oldHeight_;
+ int newPosition = oldPosition_ + diff;
- // Keep the scroll bar to the bottom if we are coming from
- // an scrollbar without height i.e scrollbar->value() == 0
- if (oldPosition_ == 0)
- newPosition = max;
+ // Keep the scroll bar to the bottom if we are coming from
+ // an scrollbar without height i.e scrollbar->value() == 0
+ if (oldPosition_ == 0)
+ newPosition = max;
- scroll_area_->verticalScrollBar()->setValue(newPosition);
- }
+ scroll_area_->verticalScrollBar()->setValue(newPosition);
+ }
}
void
TimelineView::fetchHistory()
{
- bool hasEnoughMessages = scroll_area_->verticalScrollBar()->value() != 0;
+ bool hasEnoughMessages = scroll_area_->verticalScrollBar()->value() != 0;
- if (!hasEnoughMessages && !isTimelineFinished) {
- isPaginationInProgress_ = true;
- client_->messages(room_id_, prev_batch_token_);
- paginationTimer_->start(500);
- return;
- }
+ if (!hasEnoughMessages && !isTimelineFinished) {
+ isPaginationInProgress_ = true;
+ client_->messages(room_id_, prev_batch_token_);
+ paginationTimer_->start(500);
+ return;
+ }
- paginationTimer_->stop();
+ paginationTimer_->stop();
}
void
TimelineView::scrollDown()
{
- int current = scroll_area_->verticalScrollBar()->value();
- int max = scroll_area_->verticalScrollBar()->maximum();
-
- // The first time we enter the room move the scroll bar to the bottom.
- if (!isInitialized) {
- scroll_area_->verticalScrollBar()->setValue(max);
- isInitialized = true;
- return;
- }
-
- // If the gap is small enough move the scroll bar down. e.g when a new message appears.
- if (max - current < SCROLL_BAR_GAP)
- scroll_area_->verticalScrollBar()->setValue(max);
+ int current = scroll_area_->verticalScrollBar()->value();
+ int max = scroll_area_->verticalScrollBar()->maximum();
+
+ // The first time we enter the room move the scroll bar to the bottom.
+ if (!isInitialized) {
+ scroll_area_->verticalScrollBar()->setValue(max);
+ isInitialized = true;
+ return;
+ }
+
+ // If the gap is small enough move the scroll bar down. e.g when a new
+ // message appears.
+ if (max - current < SCROLL_BAR_GAP)
+ scroll_area_->verticalScrollBar()->setValue(max);
}
void
TimelineView::sliderMoved(int position)
{
- if (!scroll_area_->verticalScrollBar()->isVisible())
- return;
-
- // The scrollbar is high enough so we can start retrieving old events.
- if (position < SCROLL_BAR_GAP) {
- if (isTimelineFinished)
- return;
-
- // Prevent user from moving up when there is pagination in progress.
- // TODO: Keep a map of the event ids to filter out duplicates.
- if (isPaginationInProgress_)
- return;
-
- isPaginationInProgress_ = true;
-
- // FIXME: Maybe move this to TimelineViewManager to remove the extra calls?
- client_->messages(room_id_, prev_batch_token_);
- }
+ if (!scroll_area_->verticalScrollBar()->isVisible())
+ return;
+
+ // The scrollbar is high enough so we can start retrieving old events.
+ if (position < SCROLL_BAR_GAP) {
+ if (isTimelineFinished)
+ return;
+
+ // Prevent user from moving up when there is pagination in
+ // progress.
+ // TODO: Keep a map of the event ids to filter out duplicates.
+ if (isPaginationInProgress_)
+ return;
+
+ isPaginationInProgress_ = true;
+
+ // FIXME: Maybe move this to TimelineViewManager to remove the
+ // extra calls?
+ client_->messages(room_id_, prev_batch_token_);
+ }
}
void
TimelineView::addBackwardsEvents(const QString &room_id, const RoomMessages &msgs)
{
- if (room_id_ != room_id)
- return;
+ if (room_id_ != room_id)
+ return;
- if (msgs.chunk().count() == 0) {
- isTimelineFinished = true;
- return;
- }
+ if (msgs.chunk().count() == 0) {
+ isTimelineFinished = true;
+ return;
+ }
- isTimelineFinished = false;
- QList<TimelineItem *> items;
+ isTimelineFinished = false;
+ QList<TimelineItem *> items;
- // Parse in reverse order to determine where we should not show sender's name.
- auto it = msgs.chunk().constEnd();
- while (it != msgs.chunk().constBegin()) {
- --it;
+ // Parse in reverse order to determine where we should not show sender's
+ // name.
+ auto it = msgs.chunk().constEnd();
+ while (it != msgs.chunk().constBegin()) {
+ --it;
- TimelineItem *item = parseMessageEvent((*it).toObject(), TimelineDirection::Top);
+ TimelineItem *item = parseMessageEvent((*it).toObject(), TimelineDirection::Top);
- if (item != nullptr)
- items.push_back(item);
- }
+ if (item != nullptr)
+ items.push_back(item);
+ }
- // Reverse again to render them.
- std::reverse(items.begin(), items.end());
+ // Reverse again to render them.
+ std::reverse(items.begin(), items.end());
- oldPosition_ = scroll_area_->verticalScrollBar()->value();
- oldHeight_ = scroll_widget_->size().height();
+ oldPosition_ = scroll_area_->verticalScrollBar()->value();
+ oldHeight_ = scroll_widget_->size().height();
- for (const auto &item : items)
- addTimelineItem(item, TimelineDirection::Top);
+ for (const auto &item : items)
+ addTimelineItem(item, TimelineDirection::Top);
- prev_batch_token_ = msgs.end();
- isPaginationInProgress_ = false;
- isPaginationScrollPending_ = true;
+ prev_batch_token_ = msgs.end();
+ isPaginationInProgress_ = false;
+ isPaginationScrollPending_ = true;
- // Exclude the top stretch.
- if (!msgs.chunk().isEmpty() && scroll_layout_->count() > 1)
- notifyForLastEvent();
+ // Exclude the top stretch.
+ if (!msgs.chunk().isEmpty() && scroll_layout_->count() > 1)
+ notifyForLastEvent();
- // 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.isEmpty())
- lastSender_ = items.constFirst()->descriptionMessage().userid;
+ // 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.isEmpty())
+ lastSender_ = items.constFirst()->descriptionMessage().userid;
}
TimelineItem *
TimelineView::parseMessageEvent(const QJsonObject &event, TimelineDirection direction)
{
- events::EventType ty = events::extractEventType(event);
+ events::EventType ty = events::extractEventType(event);
- if (ty == events::EventType::RoomMessage) {
- events::MessageEventType msg_type = events::extractMessageEventType(event);
+ if (ty == events::EventType::RoomMessage) {
+ events::MessageEventType msg_type = events::extractMessageEventType(event);
- if (msg_type == events::MessageEventType::Text) {
- events::MessageEvent<msgs::Text> text;
+ 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;
- }
+ try {
+ text.deserialize(event);
+ } catch (const DeserializationException &e) {
+ qWarning() << e.what() << event;
+ return nullptr;
+ }
- if (isDuplicate(text.eventId()))
- return nullptr;
+ if (isDuplicate(text.eventId()))
+ return nullptr;
- eventIds_[text.eventId()] = true;
+ eventIds_[text.eventId()] = true;
- if (isPendingMessage(text, local_user_)) {
- removePendingMessage(text);
- return nullptr;
- }
+ if (isPendingMessage(text, local_user_)) {
+ removePendingMessage(text);
+ return nullptr;
+ }
- auto with_sender = isSenderRendered(text.sender(), direction);
- auto color = TimelineViewManager::getUserColor(text.sender());
+ auto with_sender = isSenderRendered(text.sender(), direction);
- updateLastSender(text.sender(), direction);
+ updateLastSender(text.sender(), direction);
- return createTimelineItem(text, color, with_sender);
- } else if (msg_type == events::MessageEventType::Notice) {
- events::MessageEvent<msgs::Notice> notice;
+ return createTimelineItem(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;
- }
+ try {
+ notice.deserialize(event);
+ } catch (const DeserializationException &e) {
+ qWarning() << e.what() << event;
+ return nullptr;
+ }
- if (isDuplicate(notice.eventId()))
- return nullptr;
- ;
+ if (isDuplicate(notice.eventId()))
+ return nullptr;
+ ;
- eventIds_[notice.eventId()] = true;
+ eventIds_[notice.eventId()] = true;
- auto with_sender = isSenderRendered(notice.sender(), direction);
- auto color = TimelineViewManager::getUserColor(notice.sender());
+ auto with_sender = isSenderRendered(notice.sender(), direction);
- updateLastSender(notice.sender(), direction);
+ updateLastSender(notice.sender(), direction);
- return createTimelineItem(notice, color, with_sender);
- } else if (msg_type == events::MessageEventType::Image) {
- events::MessageEvent<msgs::Image> img;
+ return createTimelineItem(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;
- }
+ try {
+ img.deserialize(event);
+ } catch (const DeserializationException &e) {
+ qWarning() << e.what() << event;
+ return nullptr;
+ }
- if (isDuplicate(img.eventId()))
- return nullptr;
+ if (isDuplicate(img.eventId()))
+ return nullptr;
- eventIds_[img.eventId()] = true;
+ eventIds_[img.eventId()] = true;
- auto with_sender = isSenderRendered(img.sender(), direction);
- auto color = TimelineViewManager::getUserColor(img.sender());
+ auto with_sender = isSenderRendered(img.sender(), direction);
- updateLastSender(img.sender(), direction);
+ updateLastSender(img.sender(), direction);
- return createTimelineItem(img, color, with_sender);
- } else if (msg_type == events::MessageEventType::Unknown) {
- qWarning() << "Unknown message type" << event;
- return nullptr;
- }
- }
+ return createTimelineItem(img, with_sender);
+ } else if (msg_type == events::MessageEventType::Unknown) {
+ qWarning() << "Unknown message type" << event;
+ return nullptr;
+ }
+ }
- return nullptr;
+ return nullptr;
}
int
TimelineView::addEvents(const Timeline &timeline)
{
- int message_count = 0;
+ int message_count = 0;
- QSettings settings;
- QString localUser = settings.value("auth/user_id").toString();
+ QSettings settings;
+ QString localUser = settings.value("auth/user_id").toString();
- for (const auto &event : timeline.events()) {
- TimelineItem *item = parseMessageEvent(event.toObject(), TimelineDirection::Bottom);
+ for (const auto &event : timeline.events()) {
+ TimelineItem *item = parseMessageEvent(event.toObject(), TimelineDirection::Bottom);
- if (item != nullptr) {
- addTimelineItem(item, TimelineDirection::Bottom);
+ if (item != nullptr) {
+ addTimelineItem(item, TimelineDirection::Bottom);
- if (localUser != event.toObject().value("sender").toString())
- message_count += 1;
- }
- }
+ if (localUser != event.toObject().value("sender").toString())
+ message_count += 1;
+ }
+ }
- if (isInitialSync) {
- prev_batch_token_ = timeline.previousBatch();
- isInitialSync = false;
+ if (isInitialSync) {
+ prev_batch_token_ = timeline.previousBatch();
+ isInitialSync = false;
- client_->messages(room_id_, prev_batch_token_);
- }
+ client_->messages(room_id_, prev_batch_token_);
+ }
- // Exclude the top stretch.
- if (!timeline.events().isEmpty() && scroll_layout_->count() > 1)
- notifyForLastEvent();
+ // Exclude the top stretch.
+ if (!timeline.events().isEmpty() && scroll_layout_->count() > 1)
+ notifyForLastEvent();
- return message_count;
+ return message_count;
}
void
TimelineView::init()
{
- top_layout_ = new QVBoxLayout(this);
- top_layout_->setSpacing(0);
- top_layout_->setMargin(0);
+ top_layout_ = new QVBoxLayout(this);
+ top_layout_->setSpacing(0);
+ top_layout_->setMargin(0);
- scroll_area_ = new QScrollArea(this);
- scroll_area_->setWidgetResizable(true);
- scroll_area_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ scroll_area_ = new QScrollArea(this);
+ scroll_area_->setWidgetResizable(true);
+ scroll_area_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- scrollbar_ = new ScrollBar(scroll_area_);
- scroll_area_->setVerticalScrollBar(scrollbar_);
+ scrollbar_ = new ScrollBar(scroll_area_);
+ scroll_area_->setVerticalScrollBar(scrollbar_);
- scroll_widget_ = new QWidget();
+ scroll_widget_ = new QWidget();
- scroll_layout_ = new QVBoxLayout();
- scroll_layout_->addStretch(1);
- scroll_layout_->setSpacing(0);
+ scroll_layout_ = new QVBoxLayout();
+ scroll_layout_->addStretch(1);
+ scroll_layout_->setSpacing(0);
- scroll_widget_->setLayout(scroll_layout_);
+ scroll_widget_->setLayout(scroll_layout_);
- scroll_area_->setWidget(scroll_widget_);
+ scroll_area_->setWidget(scroll_widget_);
- top_layout_->addWidget(scroll_area_);
+ top_layout_->addWidget(scroll_area_);
- setLayout(top_layout_);
+ setLayout(top_layout_);
- paginationTimer_ = new QTimer(this);
- connect(paginationTimer_, &QTimer::timeout, this, &TimelineView::fetchHistory);
+ paginationTimer_ = new QTimer(this);
+ connect(paginationTimer_, &QTimer::timeout, this, &TimelineView::fetchHistory);
- connect(client_.data(), &MatrixClient::messagesRetrieved, this, &TimelineView::addBackwardsEvents);
+ connect(client_.data(),
+ &MatrixClient::messagesRetrieved,
+ this,
+ &TimelineView::addBackwardsEvents);
- connect(scroll_area_->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(sliderMoved(int)));
- connect(scroll_area_->verticalScrollBar(),
- SIGNAL(rangeChanged(int, int)),
- this,
- SLOT(sliderRangeChanged(int, int)));
+ connect(scroll_area_->verticalScrollBar(),
+ SIGNAL(valueChanged(int)),
+ this,
+ SLOT(sliderMoved(int)));
+ connect(scroll_area_->verticalScrollBar(),
+ SIGNAL(rangeChanged(int, int)),
+ this,
+ SLOT(sliderRangeChanged(int, int)));
}
void
TimelineView::updateLastSender(const QString &user_id, TimelineDirection direction)
{
- if (direction == TimelineDirection::Bottom)
- lastSender_ = user_id;
- else
- firstSender_ = user_id;
+ if (direction == TimelineDirection::Bottom)
+ lastSender_ = user_id;
+ else
+ firstSender_ = user_id;
}
bool
TimelineView::isSenderRendered(const QString &user_id, TimelineDirection direction)
{
- if (direction == TimelineDirection::Bottom)
- return lastSender_ != user_id;
- else
- return firstSender_ != user_id;
+ if (direction == TimelineDirection::Bottom)
+ return lastSender_ != user_id;
+ else
+ return firstSender_ != user_id;
}
TimelineItem *
-TimelineView::createTimelineItem(const events::MessageEvent<msgs::Image> &event, const QString &color, bool with_sender)
+TimelineView::createTimelineItem(const events::MessageEvent<msgs::Image> &event, bool with_sender)
{
- auto image = new ImageItem(client_, event);
-
- if (with_sender) {
- auto item = new TimelineItem(image, event, color, scroll_widget_);
- return item;
- }
+ auto image = new ImageItem(client_, event);
+ auto item = new TimelineItem(image, event, with_sender, scroll_widget_);
- auto item = new TimelineItem(image, event, scroll_widget_);
- return item;
+ return item;
}
TimelineItem *
-TimelineView::createTimelineItem(const events::MessageEvent<msgs::Notice> &event,
- const QString &color,
- bool with_sender)
+TimelineView::createTimelineItem(const events::MessageEvent<msgs::Notice> &event, bool with_sender)
{
- TimelineItem *item = new TimelineItem(event, with_sender, color, scroll_widget_);
- return item;
+ TimelineItem *item = new TimelineItem(event, with_sender, scroll_widget_);
+ return item;
}
TimelineItem *
-TimelineView::createTimelineItem(const events::MessageEvent<msgs::Text> &event, const QString &color, bool with_sender)
+TimelineView::createTimelineItem(const events::MessageEvent<msgs::Text> &event, bool with_sender)
{
- TimelineItem *item = new TimelineItem(event, with_sender, color, scroll_widget_);
- return item;
+ TimelineItem *item = new TimelineItem(event, with_sender, scroll_widget_);
+ return item;
}
void
TimelineView::addTimelineItem(TimelineItem *item, TimelineDirection direction)
{
- if (direction == TimelineDirection::Bottom)
- scroll_layout_->addWidget(item);
- else
- scroll_layout_->insertWidget(1, item);
+ if (direction == TimelineDirection::Bottom)
+ scroll_layout_->addWidget(item);
+ else
+ scroll_layout_->insertWidget(1, item);
}
void
TimelineView::updatePendingMessage(int txn_id, QString event_id)
{
- for (auto &msg : pending_msgs_) {
- if (msg.txn_id == txn_id) {
- msg.event_id = event_id;
- break;
- }
- }
+ for (auto &msg : pending_msgs_) {
+ if (msg.txn_id == txn_id) {
+ msg.event_id = event_id;
+ break;
+ }
+ }
}
bool
-TimelineView::isPendingMessage(const events::MessageEvent<msgs::Text> &e, const QString &local_userid)
+TimelineView::isPendingMessage(const events::MessageEvent<msgs::Text> &e,
+ const QString &local_userid)
{
- if (e.sender() != local_userid)
- return false;
+ if (e.sender() != local_userid)
+ return false;
- for (const auto &msg : pending_msgs_) {
- if (msg.event_id == e.eventId() || msg.body == e.content().body())
- return true;
- }
+ for (const auto &msg : pending_msgs_) {
+ if (msg.event_id == e.eventId() || msg.body == e.content().body())
+ return true;
+ }
- return false;
+ return false;
}
void
TimelineView::removePendingMessage(const events::MessageEvent<msgs::Text> &e)
{
- for (auto it = pending_msgs_.begin(); it != pending_msgs_.end(); it++) {
- int index = std::distance(pending_msgs_.begin(), it);
-
- if (it->event_id == e.eventId() || it->body == e.content().body()) {
- pending_msgs_.removeAt(index);
- break;
- }
- }
+ for (auto it = pending_msgs_.begin(); it != pending_msgs_.end(); it++) {
+ int index = std::distance(pending_msgs_.begin(), it);
+
+ if (it->event_id == e.eventId() || it->body == e.content().body()) {
+ pending_msgs_.removeAt(index);
+ break;
+ }
+ }
}
void
TimelineView::addUserTextMessage(const QString &body, int txn_id)
{
- QSettings settings;
- auto user_id = settings.value("auth/user_id").toString();
+ QSettings settings;
+ auto user_id = settings.value("auth/user_id").toString();
- auto with_sender = lastSender_ != user_id;
- auto color = TimelineViewManager::getUserColor(user_id);
+ auto with_sender = lastSender_ != user_id;
- TimelineItem *view_item;
+ TimelineItem *view_item;
- if (with_sender)
- view_item = new TimelineItem(user_id, color, body, scroll_widget_);
- else
- view_item = new TimelineItem(body, scroll_widget_);
+ if (with_sender)
+ view_item = new TimelineItem(user_id, body, scroll_widget_);
+ else
+ view_item = new TimelineItem(body, scroll_widget_);
- scroll_layout_->addWidget(view_item);
+ scroll_layout_->addWidget(view_item);
- lastSender_ = user_id;
+ lastSender_ = user_id;
- PendingMessage message(txn_id, body, "", view_item);
+ PendingMessage message(txn_id, body, "", view_item);
- pending_msgs_.push_back(message);
+ pending_msgs_.push_back(message);
}
void
TimelineView::notifyForLastEvent()
{
- auto lastItem = scroll_layout_->itemAt(scroll_layout_->count() - 1);
- auto *lastTimelineItem = qobject_cast<TimelineItem *>(lastItem->widget());
+ auto lastItem = scroll_layout_->itemAt(scroll_layout_->count() - 1);
+ auto *lastTimelineItem = qobject_cast<TimelineItem *>(lastItem->widget());
- if (lastTimelineItem)
- emit updateLastTimelineMessage(room_id_, lastTimelineItem->descriptionMessage());
- else
- qWarning() << "Cast to TimelineView failed" << room_id_;
+ if (lastTimelineItem)
+ emit updateLastTimelineMessage(room_id_, lastTimelineItem->descriptionMessage());
+ else
+ qWarning() << "Cast to TimelineView failed" << room_id_;
}
|