diff --git a/src/TimelineItem.cc b/src/TimelineItem.cc
index b1c58e6a..cf8d5e85 100644
--- a/src/TimelineItem.cc
+++ b/src/TimelineItem.cc
@@ -17,8 +17,10 @@
#include <QDateTime>
#include <QDebug>
+#include <QFontDatabase>
#include <QRegExp>
+#include "AvatarProvider.h"
#include "ImageItem.h"
#include "TimelineItem.h"
#include "TimelineViewManager.h"
@@ -29,65 +31,119 @@ static const QString URL_HTML = "<a href=\"\\1\" style=\"color: #333333\">\\1</a
namespace events = matrix::events;
namespace msgs = matrix::events::messages;
+void TimelineItem::init()
+{
+ userAvatar_ = nullptr;
+ timestamp_ = nullptr;
+ userName_ = nullptr;
+ body_ = nullptr;
+
+ QFontDatabase db;
+
+ bodyFont_ = db.font("Open Sans", "Regular", 10);
+ usernameFont_ = db.font("Open Sans", "Bold", 10);
+ timestampFont_ = db.font("Open Sans", "Regular", 7);
+
+ topLayout_ = new QHBoxLayout(this);
+ sideLayout_ = new QVBoxLayout();
+ mainLayout_ = new QVBoxLayout();
+ headerLayout_ = new QHBoxLayout();
+
+ topLayout_->setContentsMargins(7, 0, 0, 0);
+ topLayout_->setSpacing(9);
+
+ topLayout_->addLayout(sideLayout_);
+ topLayout_->addLayout(mainLayout_, 1);
+}
+
TimelineItem::TimelineItem(const QString &userid, const QString &color, QString body, QWidget *parent)
: QWidget(parent)
{
+ init();
+
body.replace(URL_REGEX, URL_HTML);
+ auto displayName = TimelineViewManager::displayName(userid);
generateTimestamp(QDateTime::currentDateTime());
- generateBody(TimelineViewManager::displayName(userid), color, body);
- setupLayout();
+ generateBody(displayName, color, body);
+
+ setupAvatarLayout(displayName);
+
+ mainLayout_->addLayout(headerLayout_);
+ mainLayout_->addWidget(body_);
+ mainLayout_->setMargin(0);
+ mainLayout_->setSpacing(0);
+
+ AvatarProvider::resolve(userid, this);
}
TimelineItem::TimelineItem(QString body, QWidget *parent)
: QWidget(parent)
{
+ init();
+
body.replace(URL_REGEX, URL_HTML);
generateTimestamp(QDateTime::currentDateTime());
generateBody(body);
- setupLayout();
+
+ setupSimpleLayout();
+
+ mainLayout_->addWidget(body_);
+ mainLayout_->setMargin(0);
+ mainLayout_->setSpacing(2);
}
TimelineItem::TimelineItem(ImageItem *image, const events::MessageEvent<msgs::Image> &event, const QString &color, QWidget *parent)
: QWidget(parent)
{
+ init();
+
auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
+ auto displayName = TimelineViewManager::displayName(event.sender());
+
generateTimestamp(timestamp);
- generateBody(TimelineViewManager::displayName(event.sender()), color, "");
+ generateBody(displayName, color, "");
- top_layout_ = new QHBoxLayout();
- top_layout_->setMargin(0);
- top_layout_->addWidget(time_label_);
+ setupAvatarLayout(displayName);
- auto right_layout = new QVBoxLayout();
- right_layout->addWidget(content_label_);
- right_layout->addWidget(image);
+ auto imageLayout = new QHBoxLayout();
+ imageLayout->addWidget(image);
+ imageLayout->addStretch(1);
- top_layout_->addLayout(right_layout);
- top_layout_->addStretch(1);
+ mainLayout_->addLayout(headerLayout_);
+ mainLayout_->addLayout(imageLayout);
+ mainLayout_->setContentsMargins(0, 4, 0, 0);
+ mainLayout_->setSpacing(0);
- setLayout(top_layout_);
+ AvatarProvider::resolve(event.sender(), this);
}
TimelineItem::TimelineItem(ImageItem *image, const events::MessageEvent<msgs::Image> &event, QWidget *parent)
: QWidget(parent)
{
+ init();
+
auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
generateTimestamp(timestamp);
- top_layout_ = new QHBoxLayout();
- top_layout_->setMargin(0);
- top_layout_->addWidget(time_label_);
- top_layout_->addWidget(image, 1);
- top_layout_->addStretch(1);
+ setupSimpleLayout();
- setLayout(top_layout_);
+ auto imageLayout = new QHBoxLayout();
+ imageLayout->setMargin(0);
+ imageLayout->addWidget(image);
+ imageLayout->addStretch(1);
+
+ mainLayout_->addLayout(imageLayout);
+ mainLayout_->setContentsMargins(0, 4, 0, 0);
+ mainLayout_->setSpacing(2);
}
TimelineItem::TimelineItem(const events::MessageEvent<msgs::Notice> &event, bool with_sender, const QString &color, QWidget *parent)
: QWidget(parent)
{
+ init();
+
auto body = event.content().body().trimmed().toHtmlEscaped();
auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
@@ -96,17 +152,34 @@ TimelineItem::TimelineItem(const events::MessageEvent<msgs::Notice> &event, bool
body.replace(URL_REGEX, URL_HTML);
body = "<i style=\"color: #565E5E\">" + body + "</i>";
- if (with_sender)
- generateBody(TimelineViewManager::displayName(event.sender()), color, body);
- else
+ if (with_sender) {
+ auto displayName = TimelineViewManager::displayName(event.sender());
+
+ generateBody(displayName, color, body);
+ setupAvatarLayout(displayName);
+
+ mainLayout_->addLayout(headerLayout_);
+ mainLayout_->addWidget(body_);
+ mainLayout_->setMargin(0);
+ mainLayout_->setSpacing(0);
+
+ AvatarProvider::resolve(event.sender(), this);
+ } else {
generateBody(body);
- setupLayout();
+ setupSimpleLayout();
+
+ mainLayout_->addWidget(body_);
+ mainLayout_->setMargin(0);
+ mainLayout_->setSpacing(2);
+ }
}
TimelineItem::TimelineItem(const events::MessageEvent<msgs::Text> &event, bool with_sender, const QString &color, QWidget *parent)
: QWidget(parent)
{
+ init();
+
auto body = event.content().body().trimmed().toHtmlEscaped();
auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
@@ -114,34 +187,45 @@ TimelineItem::TimelineItem(const events::MessageEvent<msgs::Text> &event, bool w
body.replace(URL_REGEX, URL_HTML);
- if (with_sender)
- generateBody(TimelineViewManager::displayName(event.sender()), color, body);
- else
+ if (with_sender) {
+ auto displayName = TimelineViewManager::displayName(event.sender());
+ generateBody(displayName, color, body);
+
+ setupAvatarLayout(displayName);
+
+ mainLayout_->addLayout(headerLayout_);
+ mainLayout_->addWidget(body_);
+ mainLayout_->setMargin(0);
+ mainLayout_->setSpacing(0);
+
+ AvatarProvider::resolve(event.sender(), this);
+ } else {
generateBody(body);
- setupLayout();
+ setupSimpleLayout();
+
+ mainLayout_->addWidget(body_);
+ mainLayout_->setMargin(0);
+ mainLayout_->setSpacing(2);
+ }
}
+// Only the body is displayed.
void TimelineItem::generateBody(const QString &body)
{
- content_label_ = new QLabel(this);
- content_label_->setWordWrap(true);
- content_label_->setAlignment(Qt::AlignTop);
- content_label_->setStyleSheet("margin: 0;");
- QString content(
- "<html>"
- "<head/>"
- "<body>"
- " <span style=\"font-size: 10pt; color: #171919;\">"
- " %1"
- " </span>"
- "</body>"
- "</html>");
- content_label_->setText(content.arg(replaceEmoji(body)));
- content_label_->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextBrowserInteraction);
- content_label_->setOpenExternalLinks(true);
+ QString content("<span style=\"color: #171919;\">%1</span>");
+
+ body_ = new QLabel(this);
+ body_->setWordWrap(true);
+ body_->setFont(bodyFont_);
+ body_->setText(content.arg(replaceEmoji(body)));
+ body_->setAlignment(Qt::AlignTop);
+
+ 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)
{
auto sender = userid;
@@ -150,64 +234,35 @@ void TimelineItem::generateBody(const QString &userid, const QString &color, con
if (userid.split(":")[0].split("@").size() > 1)
sender = userid.split(":")[0].split("@")[1];
- content_label_ = new QLabel(this);
- content_label_->setWordWrap(true);
- content_label_->setAlignment(Qt::AlignTop);
- content_label_->setStyleSheet("margin: 0;");
- QString content(
- "<html>"
- "<head/>"
- "<body>"
- " <span style=\"font-size: 10pt; font-weight: 600; color: %1\">"
- " %2"
- " </span>"
- " <span style=\"font-size: 10pt; color: #171919;\">"
- " %3"
- " </span>"
- "</body>"
- "</html>");
- content_label_->setText(content.arg(color).arg(sender).arg(replaceEmoji(body)));
- content_label_->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextBrowserInteraction);
- content_label_->setOpenExternalLinks(true);
-}
-
-void TimelineItem::generateTimestamp(const QDateTime &time)
-{
- auto local_time = time.toString("HH:mm");
+ QString userContent("<span style=\"color: %1\"> %2 </span>");
+ QString bodyContent("<span style=\"color: #171717;\"> %1 </span>");
- time_label_ = new QLabel(this);
- QString msg(
- "<html>"
- "<head/>"
- "<body>"
- " <span style=\"font-size: 7pt; color: #5d6565;\">"
- " %1"
- " </span>"
- "</body>"
- "</html>");
- time_label_->setText(msg.arg(local_time));
- time_label_->setStyleSheet("margin-left: 7px; margin-right: 7px; margin-top: 0;");
- time_label_->setAlignment(Qt::AlignTop);
-}
+ userName_ = new QLabel(this);
+ userName_->setFont(usernameFont_);
+ userName_->setText(userContent.arg(color).arg(sender));
+ userName_->setAlignment(Qt::AlignTop);
-void TimelineItem::setupLayout()
-{
- if (time_label_ == nullptr) {
- qWarning() << "TimelineItem: Time label is not initialized";
+ if (body.isEmpty())
return;
- }
- if (content_label_ == nullptr) {
- qWarning() << "TimelineItem: Content label is not initialized";
- return;
- }
+ body_ = new QLabel(this);
+ body_->setFont(bodyFont_);
+ body_->setWordWrap(true);
+ body_->setAlignment(Qt::AlignTop);
+ body_->setText(bodyContent.arg(replaceEmoji(body)));
+ body_->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextBrowserInteraction);
+ body_->setOpenExternalLinks(true);
+}
- top_layout_ = new QHBoxLayout();
- top_layout_->setMargin(0);
- top_layout_->addWidget(time_label_);
- top_layout_->addWidget(content_label_, 1);
+void TimelineItem::generateTimestamp(const QDateTime &time)
+{
+ QString msg("<span style=\"color: #5d6565;\"> %1 </span>");
- setLayout(top_layout_);
+ timestamp_ = new QLabel(this);
+ timestamp_->setFont(timestampFont_);
+ timestamp_->setText(msg.arg(time.toString("HH:mm")));
+ timestamp_->setAlignment(Qt::AlignTop);
+ timestamp_->setStyleSheet("margin-top: 2px;");
}
QString TimelineItem::replaceEmoji(const QString &body)
@@ -227,6 +282,46 @@ QString TimelineItem::replaceEmoji(const QString &body)
return fmtBody;
}
+void TimelineItem::setupAvatarLayout(const QString &userName)
+{
+ topLayout_->setContentsMargins(7, 6, 0, 0);
+
+ userAvatar_ = new Avatar(this);
+ userAvatar_->setLetter(QChar(userName[0]).toUpper());
+ userAvatar_->setBackgroundColor(QColor("#eee"));
+ userAvatar_->setTextColor(QColor("black"));
+ userAvatar_->setSize(32);
+
+ // 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_->setMargin(0);
+ sideLayout_->setSpacing(0);
+
+ headerLayout_->addWidget(userName_);
+ headerLayout_->addWidget(timestamp_, 1);
+ headerLayout_->setMargin(0);
+}
+
+void TimelineItem::setupSimpleLayout()
+{
+ sideLayout_->addWidget(timestamp_);
+ sideLayout_->addStretch(1);
+
+ topLayout_->setContentsMargins(9, 0, 0, 0);
+}
+
+void TimelineItem::setUserAvatar(const QImage &avatar)
+{
+ if (userAvatar_ == nullptr)
+ return;
+
+ userAvatar_->setImage(avatar);
+}
+
TimelineItem::~TimelineItem()
{
}
|