summary refs log tree commit diff
path: root/src/TimelineItem.cc
diff options
context:
space:
mode:
authorKonstantinos Sideris <sideris.konstantin@gmail.com>2017-06-05 02:14:05 +0300
committerKonstantinos Sideris <sideris.konstantin@gmail.com>2017-06-05 02:14:05 +0300
commit95c492bad837b999df409c01ea3253d52951c18c (patch)
treed2ed1f13db32071f3181abd6ab3b3e57d035dc13 /src/TimelineItem.cc
parentShow confirmation dialog on logout (diff)
downloadnheko-95c492bad837b999df409c01ea3253d52951c18c.tar.xz
Experimental support for user avatars in timeline
Diffstat (limited to 'src/TimelineItem.cc')
-rw-r--r--src/TimelineItem.cc285
1 files changed, 190 insertions, 95 deletions
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() { }