diff --git a/.clang-format b/.clang-format
index 48a81211..1f74e789 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,10 +1,12 @@
---
Language: Cpp
AccessModifierOffset: -8
-AlignAfterOpenBracket: true
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: true
AlignEscapedNewlinesLeft: false
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortFunctionsOnASingleLine: Empty
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: false
BasedOnStyle: Mozilla
@@ -12,10 +14,10 @@ BinPackArguments: false
BinPackParameters: false
BreakBeforeBraces: Linux
BreakConstructorInitializersBeforeComma: true
-ColumnLimit: 120
-ContinuationIndentWidth: 8
+ColumnLimit: 100
+CompactNamespaces: false
IndentCaseLabels: false
IndentWidth: 8
+KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 1
PointerAlignment: Right
-UseTab: Always
diff --git a/.gitignore b/.gitignore
index fd54f2b6..591744d7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -77,3 +77,4 @@ result
*.dmg
dist/MacOS/nheko.app/Contents/MacOS/nheko
+.clang
diff --git a/include/TimelineItem.h b/include/TimelineItem.h
index af2e273c..df43c26d 100644
--- a/include/TimelineItem.h
+++ b/include/TimelineItem.h
@@ -32,65 +32,65 @@
#include "Text.h"
namespace events = matrix::events;
-namespace msgs = matrix::events::messages;
+namespace msgs = matrix::events::messages;
class TimelineItem : public QWidget
{
- Q_OBJECT
+ Q_OBJECT
public:
- TimelineItem(const events::MessageEvent<msgs::Notice> &e,
- bool with_sender,
- const QString &color,
- QWidget *parent = 0);
- TimelineItem(const events::MessageEvent<msgs::Text> &e,
- bool with_sender,
- const QString &color,
- QWidget *parent = 0);
+ TimelineItem(const events::MessageEvent<msgs::Notice> &e,
+ bool with_sender,
+ QWidget *parent = 0);
+ TimelineItem(const events::MessageEvent<msgs::Text> &e,
+ bool with_sender,
+ QWidget *parent = 0);
- // For local messages.
- TimelineItem(const QString &userid, const QString &color, QString body, QWidget *parent = 0);
- TimelineItem(QString body, QWidget *parent = 0);
+ // For local messages.
+ TimelineItem(const QString &userid, QString body, QWidget *parent = 0);
+ TimelineItem(QString body, QWidget *parent = 0);
- TimelineItem(ImageItem *img, const events::MessageEvent<msgs::Image> &e, const QString &color, QWidget *parent);
- TimelineItem(ImageItem *img, const events::MessageEvent<msgs::Image> &e, QWidget *parent);
+ TimelineItem(ImageItem *img,
+ const events::MessageEvent<msgs::Image> &e,
+ bool with_sender,
+ QWidget *parent);
- void setUserAvatar(const QImage &pixmap);
- inline DescInfo descriptionMessage() const;
+ void setUserAvatar(const QImage &pixmap);
+ inline DescInfo descriptionMessage() const;
- ~TimelineItem();
+ ~TimelineItem();
private:
- void init();
+ void init();
- void generateBody(const QString &body);
- void generateBody(const QString &userid, const QString &color, const QString &body);
- void generateTimestamp(const QDateTime &time);
- QString descriptiveTime(const QDateTime &then);
+ void generateBody(const QString &body);
+ void generateBody(const QString &userid, const QString &body);
+ void generateTimestamp(const QDateTime &time);
+ QString descriptiveTime(const QDateTime &then);
- void setupAvatarLayout(const QString &userName);
- void setupSimpleLayout();
+ void setupAvatarLayout(const QString &userName);
+ void setupSimpleLayout();
- QString replaceEmoji(const QString &body);
+ QString replaceEmoji(const QString &body);
- DescInfo descriptionMsg_;
+ DescInfo descriptionMsg_;
- QHBoxLayout *topLayout_;
- QVBoxLayout *sideLayout_; // Avatar or Timestamp
- QVBoxLayout *mainLayout_; // Header & Message body
+ QHBoxLayout *topLayout_;
+ QVBoxLayout *sideLayout_; // Avatar or Timestamp
+ QVBoxLayout *mainLayout_; // Header & Message body
- QHBoxLayout *headerLayout_; // Username (&) Timestamp
+ QHBoxLayout *headerLayout_; // Username (&) Timestamp
- Avatar *userAvatar_;
+ Avatar *userAvatar_;
- QFont font_;
+ QFont font_;
- QLabel *timestamp_;
- QLabel *userName_;
- QLabel *body_;
+ QLabel *timestamp_;
+ QLabel *userName_;
+ QLabel *body_;
};
inline DescInfo
TimelineItem::descriptionMessage() const
{
- return descriptionMsg_;
+ return descriptionMsg_;
}
diff --git a/include/TimelineView.h b/include/TimelineView.h
index 17c2610a..c6eef266 100644
--- a/include/TimelineView.h
+++ b/include/TimelineView.h
@@ -32,122 +32,121 @@
#include "RoomInfoListItem.h"
#include "Text.h"
-namespace msgs = matrix::events::messages;
+namespace msgs = matrix::events::messages;
namespace events = matrix::events;
// Contains info about a message shown in the history view
// but not yet confirmed by the homeserver through sync.
struct PendingMessage {
- int txn_id;
- QString body;
- QString event_id;
- TimelineItem *widget;
-
- PendingMessage(int txn_id, QString body, QString event_id, TimelineItem *widget)
- : txn_id(txn_id)
- , body(body)
- , event_id(event_id)
- , widget(widget)
- {
- }
+ int txn_id;
+ QString body;
+ QString event_id;
+ TimelineItem *widget;
+
+ PendingMessage(int txn_id, QString body, QString event_id, TimelineItem *widget)
+ : txn_id(txn_id)
+ , body(body)
+ , event_id(event_id)
+ , widget(widget)
+ {
+ }
};
// In which place new TimelineItems should be inserted.
enum class TimelineDirection {
- Top,
- Bottom,
+ Top,
+ Bottom,
};
class TimelineView : public QWidget
{
- Q_OBJECT
+ Q_OBJECT
public:
- TimelineView(const Timeline &timeline,
- QSharedPointer<MatrixClient> client,
- const QString &room_id,
- QWidget *parent = 0);
- TimelineView(QSharedPointer<MatrixClient> client, const QString &room_id, QWidget *parent = 0);
-
- TimelineItem *createTimelineItem(const events::MessageEvent<msgs::Image> &e,
- const QString &color,
- bool with_sender);
- TimelineItem *createTimelineItem(const events::MessageEvent<msgs::Notice> &e,
- const QString &color,
- bool with_sender);
- TimelineItem *createTimelineItem(const events::MessageEvent<msgs::Text> &e,
- const QString &color,
- bool with_sender);
-
- // Add new events at the end of the timeline.
- int addEvents(const Timeline &timeline);
- void addUserTextMessage(const QString &msg, int txn_id);
- void updatePendingMessage(int txn_id, QString event_id);
- void scrollDown();
+ TimelineView(const Timeline &timeline,
+ QSharedPointer<MatrixClient> client,
+ const QString &room_id,
+ QWidget *parent = 0);
+ TimelineView(QSharedPointer<MatrixClient> client,
+ const QString &room_id,
+ QWidget *parent = 0);
+
+ TimelineItem *createTimelineItem(const events::MessageEvent<msgs::Image> &e,
+ bool with_sender);
+ TimelineItem *createTimelineItem(const events::MessageEvent<msgs::Notice> &e,
+ bool with_sender);
+ TimelineItem *createTimelineItem(const events::MessageEvent<msgs::Text> &e,
+ bool with_sender);
+
+ // Add new events at the end of the timeline.
+ int addEvents(const Timeline &timeline);
+ void addUserTextMessage(const QString &msg, int txn_id);
+ void updatePendingMessage(int txn_id, QString event_id);
+ void scrollDown();
public slots:
- void sliderRangeChanged(int min, int max);
- void sliderMoved(int position);
- void fetchHistory();
+ void sliderRangeChanged(int min, int max);
+ void sliderMoved(int position);
+ void fetchHistory();
- // Add old events at the top of the timeline.
- void addBackwardsEvents(const QString &room_id, const RoomMessages &msgs);
+ // Add old events at the top of the timeline.
+ void addBackwardsEvents(const QString &room_id, const RoomMessages &msgs);
signals:
- void updateLastTimelineMessage(const QString &user, const DescInfo &info);
+ void updateLastTimelineMessage(const QString &user, const DescInfo &info);
private:
- void init();
- void removePendingMessage(const events::MessageEvent<msgs::Text> &e);
- void addTimelineItem(TimelineItem *item, TimelineDirection direction);
- void updateLastSender(const QString &user_id, TimelineDirection direction);
- void notifyForLastEvent();
+ void init();
+ void removePendingMessage(const events::MessageEvent<msgs::Text> &e);
+ void addTimelineItem(TimelineItem *item, TimelineDirection direction);
+ void updateLastSender(const QString &user_id, TimelineDirection direction);
+ void notifyForLastEvent();
- // Used to determine whether or not we should prefix a message with the sender's name.
- bool isSenderRendered(const QString &user_id, TimelineDirection direction);
- bool isPendingMessage(const events::MessageEvent<msgs::Text> &e, const QString &userid);
- inline bool isDuplicate(const QString &event_id);
+ // Used to determine whether or not we should prefix a message with the sender's name.
+ bool isSenderRendered(const QString &user_id, TimelineDirection direction);
+ bool isPendingMessage(const events::MessageEvent<msgs::Text> &e, const QString &userid);
+ inline bool isDuplicate(const QString &event_id);
- // Return nullptr if the event couldn't be parsed.
- TimelineItem *parseMessageEvent(const QJsonObject &event, TimelineDirection direction);
+ // Return nullptr if the event couldn't be parsed.
+ TimelineItem *parseMessageEvent(const QJsonObject &event, TimelineDirection direction);
- QVBoxLayout *top_layout_;
- QVBoxLayout *scroll_layout_;
+ QVBoxLayout *top_layout_;
+ QVBoxLayout *scroll_layout_;
- QScrollArea *scroll_area_;
- ScrollBar *scrollbar_;
- QWidget *scroll_widget_;
+ QScrollArea *scroll_area_;
+ ScrollBar *scrollbar_;
+ QWidget *scroll_widget_;
- QString lastSender_;
- QString firstSender_;
- QString room_id_;
- QString prev_batch_token_;
- QString local_user_;
+ QString lastSender_;
+ QString firstSender_;
+ QString room_id_;
+ QString prev_batch_token_;
+ QString local_user_;
- bool isPaginationInProgress_ = false;
- bool isInitialized = false;
- bool isTimelineFinished = false;
- bool isInitialSync = true;
- bool isPaginationScrollPending_ = false;
+ bool isPaginationInProgress_ = false;
+ bool isInitialized = false;
+ bool isTimelineFinished = false;
+ bool isInitialSync = true;
+ bool isPaginationScrollPending_ = false;
- const int SCROLL_BAR_GAP = 400;
+ const int SCROLL_BAR_GAP = 400;
- QTimer *paginationTimer_;
+ QTimer *paginationTimer_;
- int scroll_height_ = 0;
- int previous_max_height_ = 0;
+ int scroll_height_ = 0;
+ int previous_max_height_ = 0;
- int oldPosition_;
- int oldHeight_;
+ int oldPosition_;
+ int oldHeight_;
- // The events currently rendered. Used for duplicate detection.
- QMap<QString, bool> eventIds_;
- QList<PendingMessage> pending_msgs_;
- QSharedPointer<MatrixClient> client_;
+ // The events currently rendered. Used for duplicate detection.
+ QMap<QString, bool> eventIds_;
+ QList<PendingMessage> pending_msgs_;
+ QSharedPointer<MatrixClient> client_;
};
inline bool
TimelineView::isDuplicate(const QString &event_id)
{
- return eventIds_.contains(event_id);
+ return eventIds_.contains(event_id);
}
diff --git a/include/TimelineViewManager.h b/include/TimelineViewManager.h
index 64140e3a..85e186dc 100644
--- a/include/TimelineViewManager.h
+++ b/include/TimelineViewManager.h
@@ -29,39 +29,37 @@
class TimelineViewManager : public QStackedWidget
{
- Q_OBJECT
+ Q_OBJECT
public:
- TimelineViewManager(QSharedPointer<MatrixClient> client, QWidget *parent);
- ~TimelineViewManager();
+ TimelineViewManager(QSharedPointer<MatrixClient> client, QWidget *parent);
+ ~TimelineViewManager();
- // Initialize with timeline events.
- void initialize(const Rooms &rooms);
- // Empty initialization.
- void initialize(const QList<QString> &rooms);
- void sync(const Rooms &rooms);
- void clearAll();
+ // Initialize with timeline events.
+ void initialize(const Rooms &rooms);
+ // Empty initialization.
+ void initialize(const QList<QString> &rooms);
+ void sync(const Rooms &rooms);
+ void clearAll();
- static QString chooseRandomColor();
- static QString getUserColor(const QString &userid);
- static QString displayName(const QString &userid);
+ static QString chooseRandomColor();
+ static QString displayName(const QString &userid);
- static QMap<QString, QString> NICK_COLORS;
- static QMap<QString, QString> DISPLAY_NAMES;
+ static QMap<QString, QString> DISPLAY_NAMES;
signals:
- void unreadMessages(QString roomid, int count);
- void updateRoomsLastMessage(const QString &user, const DescInfo &info);
+ void unreadMessages(QString roomid, int count);
+ void updateRoomsLastMessage(const QString &user, const DescInfo &info);
public slots:
- void setHistoryView(const QString &room_id);
- void sendTextMessage(const QString &msg);
+ void setHistoryView(const QString &room_id);
+ void sendTextMessage(const QString &msg);
private slots:
- void messageSent(const QString &eventid, const QString &roomid, int txnid);
+ void messageSent(const QString &eventid, const QString &roomid, int txnid);
private:
- QString active_room_;
- QMap<QString, QSharedPointer<TimelineView>> views_;
- QSharedPointer<MatrixClient> client_;
+ QString active_room_;
+ QMap<QString, QSharedPointer<TimelineView>> views_;
+ QSharedPointer<MatrixClient> client_;
};
diff --git a/src/TimelineItem.cc b/src/TimelineItem.cc
index 70cecca4..cfa5a988 100644
--- a/src/TimelineItem.cc
+++ b/src/TimelineItem.cc
@@ -31,62 +31,62 @@ static const QRegExp URL_REGEX("((?:https?|ftp)://\\S+)");
static const QString URL_HTML = "<a href=\"\\1\" style=\"color: #333333\">\\1</a>";
namespace events = matrix::events;
-namespace msgs = matrix::events::messages;
+namespace msgs = matrix::events::messages;
void
TimelineItem::init()
{
- userAvatar_ = nullptr;
- timestamp_ = nullptr;
- userName_ = nullptr;
- body_ = nullptr;
+ userAvatar_ = nullptr;
+ timestamp_ = nullptr;
+ userName_ = nullptr;
+ body_ = nullptr;
- font_.setPixelSize(conf::fontSize);
+ font_.setPixelSize(conf::fontSize);
- QFontMetrics fm(font_);
+ QFontMetrics fm(font_);
- topLayout_ = new QHBoxLayout(this);
- sideLayout_ = new QVBoxLayout();
- mainLayout_ = new QVBoxLayout();
- headerLayout_ = new QHBoxLayout();
+ topLayout_ = new QHBoxLayout(this);
+ sideLayout_ = new QVBoxLayout();
+ mainLayout_ = new QVBoxLayout();
+ headerLayout_ = new QHBoxLayout();
- topLayout_->setContentsMargins(conf::timeline::msgMargin, conf::timeline::msgMargin, 0, 0);
- topLayout_->setSpacing(0);
+ topLayout_->setContentsMargins(conf::timeline::msgMargin, conf::timeline::msgMargin, 0, 0);
+ topLayout_->setSpacing(0);
- topLayout_->addLayout(sideLayout_);
- topLayout_->addLayout(mainLayout_, 1);
+ topLayout_->addLayout(sideLayout_);
+ topLayout_->addLayout(mainLayout_, 1);
- sideLayout_->setMargin(0);
- sideLayout_->setSpacing(0);
+ sideLayout_->setMargin(0);
+ sideLayout_->setSpacing(0);
- mainLayout_->setContentsMargins(conf::timeline::headerLeftMargin, 0, 0, 0);
- mainLayout_->setSpacing(0);
+ mainLayout_->setContentsMargins(conf::timeline::headerLeftMargin, 0, 0, 0);
+ mainLayout_->setSpacing(0);
- headerLayout_->setMargin(0);
- headerLayout_->setSpacing(conf::timeline::headerSpacing);
+ headerLayout_->setMargin(0);
+ headerLayout_->setSpacing(conf::timeline::headerSpacing);
}
/*
* For messages created locally. The avatar and the username are displayed.
*/
-TimelineItem::TimelineItem(const QString &userid, const QString &color, QString body, QWidget *parent)
+TimelineItem::TimelineItem(const QString &userid, QString body, QWidget *parent)
: QWidget(parent)
{
- init();
- descriptionMsg_ = { "You: ", userid, body, descriptiveTime(QDateTime::currentDateTime()) };
+ init();
+ descriptionMsg_ = { "You: ", userid, body, descriptiveTime(QDateTime::currentDateTime()) };
- body.replace(URL_REGEX, URL_HTML);
- auto displayName = TimelineViewManager::displayName(userid);
+ body.replace(URL_REGEX, URL_HTML);
+ auto displayName = TimelineViewManager::displayName(userid);
- generateTimestamp(QDateTime::currentDateTime());
- generateBody(displayName, color, body);
+ generateTimestamp(QDateTime::currentDateTime());
+ generateBody(displayName, body);
- setupAvatarLayout(displayName);
+ setupAvatarLayout(displayName);
- mainLayout_->addLayout(headerLayout_);
- mainLayout_->addWidget(body_);
+ mainLayout_->addLayout(headerLayout_);
+ mainLayout_->addWidget(body_);
- AvatarProvider::resolve(userid, this);
+ AvatarProvider::resolve(userid, this);
}
/*
@@ -95,323 +95,301 @@ TimelineItem::TimelineItem(const QString &userid, const QString &color, QString
TimelineItem::TimelineItem(QString body, QWidget *parent)
: QWidget(parent)
{
- QSettings settings;
- auto userid = settings.value("auth/user_id").toString();
+ QSettings settings;
+ auto userid = settings.value("auth/user_id").toString();
- init();
- descriptionMsg_ = { "You: ", userid, body, descriptiveTime(QDateTime::currentDateTime()) };
+ init();
+ descriptionMsg_ = { "You: ", userid, body, descriptiveTime(QDateTime::currentDateTime()) };
- body.replace(URL_REGEX, URL_HTML);
+ body.replace(URL_REGEX, URL_HTML);
- generateTimestamp(QDateTime::currentDateTime());
- generateBody(body);
+ generateTimestamp(QDateTime::currentDateTime());
+ generateBody(body);
- setupSimpleLayout();
+ setupSimpleLayout();
- mainLayout_->addWidget(body_);
+ mainLayout_->addWidget(body_);
}
/*
* Used to display images. The avatar and the username are displayed.
*/
TimelineItem::TimelineItem(ImageItem *image,
- const events::MessageEvent<msgs::Image> &event,
- const QString &color,
- QWidget *parent)
+ const events::MessageEvent<msgs::Image> &event,
+ bool with_sender,
+ QWidget *parent)
: QWidget(parent)
{
- init();
+ init();
- auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
- auto displayName = TimelineViewManager::displayName(event.sender());
+ auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
+ auto displayName = TimelineViewManager::displayName(event.sender());
- QSettings settings;
- descriptionMsg_ = { event.sender() == settings.value("auth/user_id") ? "You" : displayName,
- event.sender(),
- " sent an image",
- descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.timestamp())) };
+ QSettings settings;
+ descriptionMsg_ = { event.sender() == settings.value("auth/user_id") ? "You" : displayName,
+ event.sender(),
+ " sent an image",
+ descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.timestamp())) };
- generateTimestamp(timestamp);
- generateBody(displayName, color, "");
+ generateTimestamp(timestamp);
- setupAvatarLayout(displayName);
+ auto imageLayout = new QHBoxLayout();
+ imageLayout->setMargin(0);
+ imageLayout->addWidget(image);
+ imageLayout->addStretch(1);
- auto imageLayout = new QHBoxLayout();
- imageLayout->addWidget(image);
- imageLayout->addStretch(1);
+ if (with_sender) {
+ generateBody(displayName, "");
+ setupAvatarLayout(displayName);
- mainLayout_->addLayout(headerLayout_);
- mainLayout_->addLayout(imageLayout);
+ mainLayout_->addLayout(headerLayout_);
- AvatarProvider::resolve(event.sender(), this);
-}
-
-/*
- * Used to display images. Only the image is displayed.
- */
-TimelineItem::TimelineItem(ImageItem *image, const events::MessageEvent<msgs::Image> &event, QWidget *parent)
- : QWidget(parent)
-{
- init();
-
- auto displayName = TimelineViewManager::displayName(event.sender());
+ AvatarProvider::resolve(event.sender(), this);
+ } else {
+ setupSimpleLayout();
+ }
- QSettings settings;
- descriptionMsg_ = { event.sender() == settings.value("auth/user_id") ? "You" : displayName,
- event.sender(),
- " sent an image",
- descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.timestamp())) };
-
- auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
- generateTimestamp(timestamp);
-
- setupSimpleLayout();
-
- auto imageLayout = new QHBoxLayout();
- imageLayout->setMargin(0);
- imageLayout->addWidget(image);
- imageLayout->addStretch(1);
-
- mainLayout_->addLayout(imageLayout);
+ mainLayout_->addLayout(imageLayout);
}
/*
* Used to display remote notice messages.
*/
TimelineItem::TimelineItem(const events::MessageEvent<msgs::Notice> &event,
- bool with_sender,
- const QString &color,
- QWidget *parent)
+ bool with_sender,
+ QWidget *parent)
: QWidget(parent)
{
- init();
- descriptionMsg_ = { TimelineViewManager::displayName(event.sender()),
- event.sender(),
- " sent a notification",
- descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.timestamp())) };
+ init();
+ descriptionMsg_ = { TimelineViewManager::displayName(event.sender()),
+ event.sender(),
+ " sent a notification",
+ descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.timestamp())) };
- auto body = event.content().body().trimmed().toHtmlEscaped();
- auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
+ auto body = event.content().body().trimmed().toHtmlEscaped();
+ auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
- generateTimestamp(timestamp);
+ generateTimestamp(timestamp);
- body.replace(URL_REGEX, URL_HTML);
- body = "<i style=\"color: #565E5E\">" + body + "</i>";
+ body.replace(URL_REGEX, URL_HTML);
+ body = "<i style=\"color: #565E5E\">" + body + "</i>";
- if (with_sender) {
- auto displayName = TimelineViewManager::displayName(event.sender());
+ if (with_sender) {
+ auto displayName = TimelineViewManager::displayName(event.sender());
- generateBody(displayName, color, body);
- setupAvatarLayout(displayName);
+ generateBody(displayName, body);
+ setupAvatarLayout(displayName);
- mainLayout_->addLayout(headerLayout_);
+ mainLayout_->addLayout(headerLayout_);
- AvatarProvider::resolve(event.sender(), this);
- } else {
- generateBody(body);
- setupSimpleLayout();
- }
+ AvatarProvider::resolve(event.sender(), this);
+ } else {
+ generateBody(body);
+ setupSimpleLayout();
+ }
- mainLayout_->addWidget(body_);
+ mainLayout_->addWidget(body_);
}
/*
* Used to display remote text messages.
*/
TimelineItem::TimelineItem(const events::MessageEvent<msgs::Text> &event,
- bool with_sender,
- const QString &color,
- QWidget *parent)
+ bool with_sender,
+ QWidget *parent)
: QWidget(parent)
{
- init();
+ init();
- auto body = event.content().body().trimmed().toHtmlEscaped();
- auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
- auto displayName = TimelineViewManager::displayName(event.sender());
+ auto body = event.content().body().trimmed().toHtmlEscaped();
+ auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
+ auto displayName = TimelineViewManager::displayName(event.sender());
- QSettings settings;
- descriptionMsg_ = { event.sender() == settings.value("auth/user_id") ? "You" : displayName,
- event.sender(),
- QString(": %1").arg(body),
- descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.timestamp())) };
+ QSettings settings;
+ descriptionMsg_ = { event.sender() == settings.value("auth/user_id") ? "You" : displayName,
+ event.sender(),
+ QString(": %1").arg(body),
+ descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.timestamp())) };
- generateTimestamp(timestamp);
+ generateTimestamp(timestamp);
- body.replace(URL_REGEX, URL_HTML);
+ body.replace(URL_REGEX, URL_HTML);
- if (with_sender) {
- auto displayName = TimelineViewManager::displayName(event.sender());
+ if (with_sender) {
+ auto displayName = TimelineViewManager::displayName(event.sender());
- generateBody(displayName, color, body);
- setupAvatarLayout(displayName);
+ generateBody(displayName, body);
+ setupAvatarLayout(displayName);
- mainLayout_->addLayout(headerLayout_);
+ mainLayout_->addLayout(headerLayout_);
- AvatarProvider::resolve(event.sender(), this);
- } else {
- generateBody(body);
- setupSimpleLayout();
- }
+ AvatarProvider::resolve(event.sender(), this);
+ } else {
+ generateBody(body);
+ setupSimpleLayout();
+ }
- mainLayout_->addWidget(body_);
+ mainLayout_->addWidget(body_);
}
// Only the body is displayed.
void
TimelineItem::generateBody(const QString &body)
{
- QString content("<span style=\"color: black;\"> %1 </span>");
+ QString content("<span style=\"color: black;\"> %1 </span>");
- body_ = new QLabel(this);
- body_->setFont(font_);
- body_->setWordWrap(true);
- body_->setText(content.arg(replaceEmoji(body)));
- body_->setMargin(0);
+ body_ = new QLabel(this);
+ body_->setFont(font_);
+ body_->setWordWrap(true);
+ body_->setText(content.arg(replaceEmoji(body)));
+ body_->setMargin(0);
- body_->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextBrowserInteraction);
- body_->setOpenExternalLinks(true);
+ body_->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextBrowserInteraction);
+ body_->setOpenExternalLinks(true);
}
// The username/timestamp is displayed along with the message body.
void
-TimelineItem::generateBody(const QString &userid, const QString &color, const QString &body)
+TimelineItem::generateBody(const QString &userid, const QString &body)
{
- auto sender = userid;
+ auto sender = userid;
- // TODO: Fix this by using a UserId type.
- if (userid.split(":")[0].split("@").size() > 1)
- sender = userid.split(":")[0].split("@")[1];
+ // TODO: Fix this by using a UserId type.
+ if (userid.split(":")[0].split("@").size() > 1)
+ sender = userid.split(":")[0].split("@")[1];
- QString userContent("<span style=\"color: %1\"> %2 </span>");
- QString bodyContent("<span style=\"color: #171717;\"> %1 </span>");
+ QString userContent("<span style=\"color: #171717\"> %1 </span>");
+ QString bodyContent("<span style=\"color: #171717;\"> %1 </span>");
- QFont usernameFont = font_;
- usernameFont.setBold(true);
+ QFont usernameFont = font_;
+ usernameFont.setBold(true);
- userName_ = new QLabel(this);
- userName_->setFont(usernameFont);
- userName_->setText(userContent.arg(color).arg(sender));
+ userName_ = new QLabel(this);
+ userName_->setFont(usernameFont);
+ userName_->setText(userContent.arg(sender));
- if (body.isEmpty())
- return;
+ if (body.isEmpty())
+ return;
- body_ = new QLabel(this);
- body_->setFont(font_);
- body_->setWordWrap(true);
- body_->setText(bodyContent.arg(replaceEmoji(body)));
- body_->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextBrowserInteraction);
- body_->setOpenExternalLinks(true);
- body_->setMargin(0);
+ body_ = new QLabel(this);
+ body_->setFont(font_);
+ body_->setWordWrap(true);
+ body_->setText(bodyContent.arg(replaceEmoji(body)));
+ body_->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextBrowserInteraction);
+ body_->setOpenExternalLinks(true);
+ body_->setMargin(0);
}
void
TimelineItem::generateTimestamp(const QDateTime &time)
{
- QString msg("<span style=\"color: #5d6565;\"> %1 </span>");
+ QString msg("<span style=\"color: #5d6565;\"> %1 </span>");
- QFont timestampFont;
- timestampFont.setPixelSize(conf::timeline::fonts::timestamp);
+ QFont timestampFont;
+ timestampFont.setPixelSize(conf::timeline::fonts::timestamp);
- QFontMetrics fm(timestampFont);
- int topMargin = QFontMetrics(font_).ascent() - fm.ascent();
+ QFontMetrics fm(timestampFont);
+ int topMargin = QFontMetrics(font_).ascent() - fm.ascent();
- timestamp_ = new QLabel(this);
- timestamp_->setFont(timestampFont);
- timestamp_->setText(msg.arg(time.toString("HH:mm")));
- timestamp_->setContentsMargins(0, topMargin, 0, 0);
+ timestamp_ = new QLabel(this);
+ timestamp_->setFont(timestampFont);
+ timestamp_->setText(msg.arg(time.toString("HH:mm")));
+ timestamp_->setContentsMargins(0, topMargin, 0, 0);
}
QString
TimelineItem::replaceEmoji(const QString &body)
{
- QString fmtBody = "";
-
- for (auto &c : body) {
- int code = c.unicode();
-
- // TODO: Be more precise here.
- if (code > 9000)
- fmtBody += QString("<span style=\"font-family: Emoji One; font-size: %1px\">")
- .arg(conf::emojiSize) +
- QString(c) + "</span>";
- else
- fmtBody += c;
- }
-
- return fmtBody;
+ QString fmtBody = "";
+
+ for (auto &c : body) {
+ int code = c.unicode();
+
+ // TODO: Be more precise here.
+ if (code > 9000)
+ fmtBody += QString("<span style=\"font-family: Emoji "
+ "One; font-size: %1px\">")
+ .arg(conf::emojiSize) +
+ QString(c) + "</span>";
+ else
+ fmtBody += c;
+ }
+
+ return fmtBody;
}
void
TimelineItem::setupAvatarLayout(const QString &userName)
{
- topLayout_->setContentsMargins(conf::timeline::msgMargin, conf::timeline::msgMargin, 0, 0);
+ topLayout_->setContentsMargins(conf::timeline::msgMargin, conf::timeline::msgMargin, 0, 0);
- userAvatar_ = new Avatar(this);
- userAvatar_->setLetter(QChar(userName[0]).toUpper());
- userAvatar_->setBackgroundColor(QColor("#eee"));
- userAvatar_->setTextColor(QColor("black"));
- userAvatar_->setSize(conf::timeline::avatarSize);
+ userAvatar_ = new Avatar(this);
+ userAvatar_->setLetter(QChar(userName[0]).toUpper());
+ userAvatar_->setBackgroundColor(QColor("#eee"));
+ userAvatar_->setTextColor(QColor("black"));
+ userAvatar_->setSize(conf::timeline::avatarSize);
- // TODO: The provided user name should be a UserId class
- if (userName[0] == '@' && userName.size() > 1)
- userAvatar_->setLetter(QChar(userName[1]).toUpper());
+ // TODO: The provided user name should be a UserId class
+ if (userName[0] == '@' && userName.size() > 1)
+ userAvatar_->setLetter(QChar(userName[1]).toUpper());
- sideLayout_->addWidget(userAvatar_);
- sideLayout_->addStretch(1);
+ sideLayout_->addWidget(userAvatar_);
+ sideLayout_->addStretch(1);
- headerLayout_->addWidget(userName_);
- headerLayout_->addWidget(timestamp_, 1);
+ headerLayout_->addWidget(userName_);
+ headerLayout_->addWidget(timestamp_, 1);
}
void
TimelineItem::setupSimpleLayout()
{
- sideLayout_->addWidget(timestamp_);
+ sideLayout_->addWidget(timestamp_);
- // Keep only the time in plain text.
- QTextEdit htmlText(timestamp_->text());
- QString plainText = htmlText.toPlainText();
+ // Keep only the time in plain text.
+ QTextEdit htmlText(timestamp_->text());
+ QString plainText = htmlText.toPlainText();
- timestamp_->adjustSize();
+ timestamp_->adjustSize();
- // Align the end of the avatar bubble with the end of the timestamp for
- // messages with and without avatar. Otherwise their bodies would not be aligned.
- int tsWidth = timestamp_->fontMetrics().width(plainText);
- int offset = std::max(0, conf::timeline::avatarSize - tsWidth);
+ // Align the end of the avatar bubble with the end of the timestamp for
+ // messages with and without avatar. Otherwise their bodies would not be
+ // aligned.
+ int tsWidth = timestamp_->fontMetrics().width(plainText);
+ int offset = std::max(0, conf::timeline::avatarSize - tsWidth);
- int defaultFontHeight = QFontMetrics(font_).ascent();
+ int defaultFontHeight = QFontMetrics(font_).ascent();
- timestamp_->setAlignment(Qt::AlignTop);
- timestamp_->setContentsMargins(offset + 1, defaultFontHeight - timestamp_->fontMetrics().ascent(), 0, 0);
- topLayout_->setContentsMargins(conf::timeline::msgMargin, conf::timeline::msgMargin / 3, 0, 0);
+ timestamp_->setAlignment(Qt::AlignTop);
+ timestamp_->setContentsMargins(
+ offset + 1, defaultFontHeight - timestamp_->fontMetrics().ascent(), 0, 0);
+ topLayout_->setContentsMargins(
+ conf::timeline::msgMargin, conf::timeline::msgMargin / 3, 0, 0);
}
void
TimelineItem::setUserAvatar(const QImage &avatar)
{
- if (userAvatar_ == nullptr)
- return;
+ if (userAvatar_ == nullptr)
+ return;
- userAvatar_->setImage(avatar);
+ userAvatar_->setImage(avatar);
}
QString
TimelineItem::descriptiveTime(const QDateTime &then)
{
- auto now = QDateTime::currentDateTime();
+ auto now = QDateTime::currentDateTime();
- auto days = then.daysTo(now);
+ auto days = then.daysTo(now);
- if (days == 0) {
- return then.toString("HH:mm");
- } else if (days < 2) {
- return QString("Yesterday");
- } else if (days < 365) {
- return then.toString("dd/MM");
- }
+ if (days == 0)
+ return then.toString("HH:mm");
+ else if (days < 2)
+ return QString("Yesterday");
+ else if (days < 365)
+ return then.toString("dd/MM");
- return then.toString("dd/MM/yy");
+ return then.toString("dd/MM/yy");
}
TimelineItem::~TimelineItem()
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_;
}
diff --git a/src/TimelineViewManager.cc b/src/TimelineViewManager.cc
index a02e89e9..3cb61889 100644
--- a/src/TimelineViewManager.cc
+++ b/src/TimelineViewManager.cc
@@ -30,12 +30,12 @@ TimelineViewManager::TimelineViewManager(QSharedPointer<MatrixClient> client, QW
: QStackedWidget(parent)
, client_(client)
{
- setStyleSheet("QWidget { background: #f8fbfe; color: #e8e8e8; border: none;}");
+ setStyleSheet("QWidget { background: #f8fbfe; color: #e8e8e8; border: none;}");
- connect(client_.data(),
- SIGNAL(messageSent(const QString &, const QString &, int)),
- this,
- SLOT(messageSent(const QString &, const QString &, int)));
+ connect(client_.data(),
+ SIGNAL(messageSent(const QString &, const QString &, int)),
+ this,
+ SLOT(messageSent(const QString &, const QString &, int)));
}
TimelineViewManager::~TimelineViewManager()
@@ -45,195 +45,179 @@ TimelineViewManager::~TimelineViewManager()
void
TimelineViewManager::messageSent(const QString &event_id, const QString &roomid, int txn_id)
{
- // We save the latest valid transaction ID for later use.
- QSettings settings;
- settings.setValue("client/transaction_id", txn_id + 1);
+ // We save the latest valid transaction ID for later use.
+ QSettings settings;
+ settings.setValue("client/transaction_id", txn_id + 1);
- auto view = views_[roomid];
- view->updatePendingMessage(txn_id, event_id);
+ auto view = views_[roomid];
+ view->updatePendingMessage(txn_id, event_id);
}
void
TimelineViewManager::sendTextMessage(const QString &msg)
{
- auto room_id = active_room_;
- auto view = views_[room_id];
+ auto room_id = active_room_;
+ auto view = views_[room_id];
- view->addUserTextMessage(msg, client_->transactionId());
- client_->sendTextMessage(room_id, msg);
+ view->addUserTextMessage(msg, client_->transactionId());
+ client_->sendTextMessage(room_id, msg);
}
void
TimelineViewManager::clearAll()
{
- NICK_COLORS.clear();
+ for (auto view : views_)
+ removeWidget(view.data());
- for (auto view : views_)
- removeWidget(view.data());
-
- views_.clear();
+ views_.clear();
}
void
TimelineViewManager::initialize(const Rooms &rooms)
{
- for (auto it = rooms.join().constBegin(); it != rooms.join().constEnd(); it++) {
- auto roomid = it.key();
+ for (auto it = rooms.join().constBegin(); it != rooms.join().constEnd(); it++) {
+ auto roomid = it.key();
- // Create a history view with the room events.
- TimelineView *view = new TimelineView(it.value().timeline(), client_, it.key());
- views_.insert(it.key(), QSharedPointer<TimelineView>(view));
+ // Create a history view with the room events.
+ TimelineView *view = new TimelineView(it.value().timeline(), client_, it.key());
+ views_.insert(it.key(), QSharedPointer<TimelineView>(view));
- connect(view,
- &TimelineView::updateLastTimelineMessage,
- this,
- &TimelineViewManager::updateRoomsLastMessage);
+ connect(view,
+ &TimelineView::updateLastTimelineMessage,
+ this,
+ &TimelineViewManager::updateRoomsLastMessage);
- // Add the view in the widget stack.
- addWidget(view);
- }
+ // Add the view in the widget stack.
+ addWidget(view);
+ }
}
void
TimelineViewManager::initialize(const QList<QString> &rooms)
{
- for (const auto &roomid : rooms) {
- // Create a history view without any events.
- TimelineView *view = new TimelineView(client_, roomid);
- views_.insert(roomid, QSharedPointer<TimelineView>(view));
-
- connect(view,
- &TimelineView::updateLastTimelineMessage,
- this,
- &TimelineViewManager::updateRoomsLastMessage);
-
- // Add the view in the widget stack.
- addWidget(view);
- }
+ for (const auto &roomid : rooms) {
+ // Create a history view without any events.
+ TimelineView *view = new TimelineView(client_, roomid);
+ views_.insert(roomid, QSharedPointer<TimelineView>(view));
+
+ connect(view,
+ &TimelineView::updateLastTimelineMessage,
+ this,
+ &TimelineViewManager::updateRoomsLastMessage);
+
+ // Add the view in the widget stack.
+ addWidget(view);
+ }
}
void
TimelineViewManager::sync(const Rooms &rooms)
{
- for (auto it = rooms.join().constBegin(); it != rooms.join().constEnd(); it++) {
- auto roomid = it.key();
+ for (auto it = rooms.join().constBegin(); it != rooms.join().constEnd(); it++) {
+ auto roomid = it.key();
- if (!views_.contains(roomid)) {
- qDebug() << "Ignoring event from unknown room" << roomid;
- continue;
- }
+ if (!views_.contains(roomid)) {
+ qDebug() << "Ignoring event from unknown room" << roomid;
+ continue;
+ }
- auto view = views_.value(roomid);
+ auto view = views_.value(roomid);
- int msgs_added = view->addEvents(it.value().timeline());
+ int msgs_added = view->addEvents(it.value().timeline());
- if (msgs_added > 0) {
- // TODO: When the app window gets active the current
- // unread count (if any) should be cleared.
- auto isAppActive = QApplication::activeWindow() != nullptr;
+ if (msgs_added > 0) {
+ // TODO: When the app window gets active the current
+ // unread count (if any) should be cleared.
+ auto isAppActive = QApplication::activeWindow() != nullptr;
- if (roomid != active_room_ || !isAppActive)
- emit unreadMessages(roomid, msgs_added);
- }
- }
+ if (roomid != active_room_ || !isAppActive)
+ emit unreadMessages(roomid, msgs_added);
+ }
+ }
}
void
TimelineViewManager::setHistoryView(const QString &room_id)
{
- if (!views_.contains(room_id)) {
- qDebug() << "Room ID from RoomList is not present in ViewManager" << room_id;
- return;
- }
+ if (!views_.contains(room_id)) {
+ qDebug() << "Room ID from RoomList is not present in ViewManager" << room_id;
+ return;
+ }
- active_room_ = room_id;
- auto view = views_.value(room_id);
+ active_room_ = room_id;
+ auto view = views_.value(room_id);
- setCurrentWidget(view.data());
+ setCurrentWidget(view.data());
- view->fetchHistory();
- view->scrollDown();
+ view->fetchHistory();
+ view->scrollDown();
}
-QMap<QString, QString> TimelineViewManager::NICK_COLORS;
QMap<QString, QString> TimelineViewManager::DISPLAY_NAMES;
QString
TimelineViewManager::chooseRandomColor()
{
- std::random_device random_device;
- std::mt19937 engine{ random_device() };
- std::uniform_real_distribution<float> dist(0, 1);
-
- float hue = dist(engine);
- float saturation = 0.9;
- float value = 0.7;
-
- int hue_i = hue * 6;
-
- float f = hue * 6 - hue_i;
-
- float p = value * (1 - saturation);
- float q = value * (1 - f * saturation);
- float t = value * (1 - (1 - f) * saturation);
-
- float r = 0;
- float g = 0;
- float b = 0;
-
- if (hue_i == 0) {
- r = value;
- g = t;
- b = p;
- } else if (hue_i == 1) {
- r = q;
- g = value;
- b = p;
- } else if (hue_i == 2) {
- r = p;
- g = value;
- b = t;
- } else if (hue_i == 3) {
- r = p;
- g = q;
- b = value;
- } else if (hue_i == 4) {
- r = t;
- g = p;
- b = value;
- } else if (hue_i == 5) {
- r = value;
- g = p;
- b = q;
- }
-
- int ri = r * 256;
- int gi = g * 256;
- int bi = b * 256;
-
- QColor color(ri, gi, bi);
-
- return color.name();
-}
-
-QString
-TimelineViewManager::getUserColor(const QString &userid)
-{
- auto color = NICK_COLORS.value(userid);
-
- if (color.isEmpty()) {
- color = chooseRandomColor();
- NICK_COLORS.insert(userid, color);
- }
-
- return color;
+ std::random_device random_device;
+ std::mt19937 engine{ random_device() };
+ std::uniform_real_distribution<float> dist(0, 1);
+
+ float hue = dist(engine);
+ float saturation = 0.9;
+ float value = 0.7;
+
+ int hue_i = hue * 6;
+
+ float f = hue * 6 - hue_i;
+
+ float p = value * (1 - saturation);
+ float q = value * (1 - f * saturation);
+ float t = value * (1 - (1 - f) * saturation);
+
+ float r = 0;
+ float g = 0;
+ float b = 0;
+
+ if (hue_i == 0) {
+ r = value;
+ g = t;
+ b = p;
+ } else if (hue_i == 1) {
+ r = q;
+ g = value;
+ b = p;
+ } else if (hue_i == 2) {
+ r = p;
+ g = value;
+ b = t;
+ } else if (hue_i == 3) {
+ r = p;
+ g = q;
+ b = value;
+ } else if (hue_i == 4) {
+ r = t;
+ g = p;
+ b = value;
+ } else if (hue_i == 5) {
+ r = value;
+ g = p;
+ b = q;
+ }
+
+ int ri = r * 256;
+ int gi = g * 256;
+ int bi = b * 256;
+
+ QColor color(ri, gi, bi);
+
+ return color.name();
}
QString
TimelineViewManager::displayName(const QString &userid)
{
- if (DISPLAY_NAMES.contains(userid))
- return DISPLAY_NAMES.value(userid);
+ if (DISPLAY_NAMES.contains(userid))
+ return DISPLAY_NAMES.value(userid);
- return userid;
+ return userid;
}
|