summary refs log tree commit diff
diff options
context:
space:
mode:
authorKonstantinos Sideris <sideris.konstantin@gmail.com>2017-07-01 12:46:58 +0300
committerKonstantinos Sideris <sideris.konstantin@gmail.com>2017-07-01 12:46:58 +0300
commit730a56f58e3b6e556437ca462645504a860a1ed2 (patch)
treeeb59e2922639ac342abdd53e78f9c6abd363db33
parentDon't collapse room list (diff)
downloadnheko-730a56f58e3b6e556437ca462645504a860a1ed2.tar.xz
Remove hardcoded font sizes, margins etc
- Fixes small font issue on MacOs
-rw-r--r--Makefile30
-rw-r--r--include/RoomInfoListItem.h6
-rw-r--r--include/TimelineItem.h9
-rw-r--r--src/RoomInfoListItem.cc30
-rw-r--r--src/TimelineItem.cc126
5 files changed, 132 insertions, 69 deletions
diff --git a/Makefile b/Makefile
index 5802f833..b4af63fb 100644
--- a/Makefile
+++ b/Makefile
@@ -1,23 +1,45 @@
 SRC := $(shell find include src -type f -type f \( -iname "*.cc" -o -iname "*.h" \))
 
+# Linux specific helpers
 debug:
 	@cmake -DBUILD_TESTS=OFF -H. -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Debug
 	@cmake --build build
 
+
 release-debug:
 	@cmake -DBUILD_TESTS=OFF -H. -GNinja -Bbuild -DCMAKE_BUILD_TYPE=RelWithDebInfo
 	@cmake --build build
 
+test:
+	@cmake -DBUILD_TESTS=ON -H. -GNinja -Bbuild -DCMAKE_BUILD_TYPE=RelWithDebInfo
+	@cmake --build build
+	@cd build && GTEST_COLOR=1 ctest --verbose
+
+# MacOS specific helpers
+mdebug:
+	@cmake -DBUILD_TESTS=OFF \
+		-H. \
+		-GNinja \
+		-Bbuild \
+		-DCMAKE_PREFIX_PATH=/usr/local/opt/qt5 \
+		-DCMAKE_BUILD_TYPE=Debug
+	@cmake --build build
+
+mrelease:
+	@cmake -DBUILD_TESTS=OFF \
+		-H. \
+		-GNinja \
+		-Bbuild \
+		-DCMAKE_PREFIX_PATH=/usr/local/opt/qt5 \
+		-DCMAKE_BUILD_TYPE=RelWithDebInfo
+	@cmake --build build
+
 run:
 	@./build/nheko
 
 lint:
 	@clang-format -i $(SRC)
 
-test:
-	@cmake -DBUILD_TESTS=ON -H. -GNinja -Bbuild -DCMAKE_BUILD_TYPE=RelWithDebInfo
-	@cmake --build build
-	@cd build && GTEST_COLOR=1 ctest --verbose
 
 clean:
 	rm -rf build
diff --git a/include/RoomInfoListItem.h b/include/RoomInfoListItem.h
index 12d5abb1..f725dc06 100644
--- a/include/RoomInfoListItem.h
+++ b/include/RoomInfoListItem.h
@@ -75,6 +75,12 @@ private:
 
 	QPixmap roomAvatar_;
 
+	// Sizes are relative to the default font size of the Widget.
+	static const float UnreadCountFontRatio;
+	static const float RoomNameFontRatio;
+	static const float RoomDescriptionFontRatio;
+	static const float RoomAvatarLetterFontRatio;
+
 	Menu *menu_;
 	QAction *toggleNotifications_;
 
diff --git a/include/TimelineItem.h b/include/TimelineItem.h
index c0cf1c7b..ccba27ad 100644
--- a/include/TimelineItem.h
+++ b/include/TimelineItem.h
@@ -69,13 +69,14 @@ private:
 
 	QHBoxLayout *headerLayout_;  // Username (&) Timestamp
 
+	int MessageMargin;
+
+	const int AvatarSize = 36;
+	const float TimestampFontRatio = 0.8;
+
 	Avatar *userAvatar_;
 
 	QLabel *timestamp_;
 	QLabel *userName_;
 	QLabel *body_;
-
-	QFont bodyFont_;
-	QFont usernameFont_;
-	QFont timestampFont_;
 };
diff --git a/src/RoomInfoListItem.cc b/src/RoomInfoListItem.cc
index be1b4133..eec53ce4 100644
--- a/src/RoomInfoListItem.cc
+++ b/src/RoomInfoListItem.cc
@@ -24,6 +24,11 @@
 #include "RoomState.h"
 #include "Theme.h"
 
+const float RoomInfoListItem::UnreadCountFontRatio = 0.8;
+const float RoomInfoListItem::RoomNameFontRatio = 1.1;
+const float RoomInfoListItem::RoomDescriptionFontRatio = 1.1;
+const float RoomInfoListItem::RoomAvatarLetterFontRatio = 1.8;
+
 RoomInfoListItem::RoomInfoListItem(QSharedPointer<RoomSettings> settings,
 				   RoomState state,
 				   QString room_id,
@@ -84,10 +89,9 @@ void RoomInfoListItem::paintEvent(QPaintEvent *event)
 	else
 		p.fillRect(rect(), QColor("#F8FBFE"));
 
-	QFont font("Open Sans", 10);
-
+	QFont font;
 	QFontMetrics metrics(font);
-	p.setFont(font);
+
 	p.setPen(QColor("#333"));
 
 	QRect avatarRegion(Padding, Padding, IconSize, IconSize);
@@ -101,6 +105,9 @@ void RoomInfoListItem::paintEvent(QPaintEvent *event)
 			p.setPen(pen);
 		}
 
+		font.setPointSize(this->font().pointSize() * RoomNameFontRatio);
+		p.setFont(font);
+
 		auto name = metrics.elidedText(state_.getName(), Qt::ElideRight, (width() - IconSize - 2 * Padding) * 0.8);
 		p.drawText(QPoint(2 * Padding + IconSize, Padding + metrics.height()), name);
 
@@ -109,11 +116,14 @@ void RoomInfoListItem::paintEvent(QPaintEvent *event)
 			p.setPen(pen);
 		}
 
-		double descPercentage = 0.95;
+		double descPercentage = 0.90;
 
 		if (unreadMsgCount_ > 0)
 			descPercentage = 0.8;
 
+		font.setPointSize(this->font().pointSize() * RoomDescriptionFontRatio);
+		p.setFont(font);
+
 		auto description = metrics.elidedText(state_.getTopic(), Qt::ElideRight, width() * descPercentage - 2 * Padding - IconSize);
 		p.drawText(QPoint(2 * Padding + IconSize, bottom_y), description);
 	}
@@ -131,7 +141,7 @@ void RoomInfoListItem::paintEvent(QPaintEvent *event)
 
 		p.drawEllipse(avatarRegion.center(), IconSize / 2, IconSize / 2);
 
-		font.setPointSize(13);
+		font.setPointSize(this->font().pointSize() * RoomAvatarLetterFontRatio);
 		p.setFont(font);
 		p.setPen(QColor("#333"));
 		p.setBrush(Qt::NoBrush);
@@ -158,13 +168,13 @@ void RoomInfoListItem::paintEvent(QPaintEvent *event)
 		if (isPressed_)
 			brush.setColor(textColor);
 
+		QFont unreadCountFont;
+		unreadCountFont.setPointSize(this->font().pointSize() * UnreadCountFontRatio);
+		unreadCountFont.setBold(true);
+
 		p.setBrush(brush);
 		p.setPen(Qt::NoPen);
-
-		QFont msgFont("Open Sans", 8);
-		msgFont.setStyleName("Bold");
-
-		p.setFont(msgFont);
+		p.setFont(unreadCountFont);
 
 		int diameter = 20;
 
diff --git a/src/TimelineItem.cc b/src/TimelineItem.cc
index cf8d5e85..12ebcfde 100644
--- a/src/TimelineItem.cc
+++ b/src/TimelineItem.cc
@@ -19,6 +19,7 @@
 #include <QDebug>
 #include <QFontDatabase>
 #include <QRegExp>
+#include <QTextEdit>
 
 #include "AvatarProvider.h"
 #include "ImageItem.h"
@@ -38,24 +39,35 @@ void TimelineItem::init()
 	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);
+	// Initialize layout spacing variables based on the current font.
+	QFontMetrics fm(this->font());
+	const int baseWidth = fm.width('A');
+	MessageMargin = baseWidth * 1.5;
 
 	topLayout_ = new QHBoxLayout(this);
 	sideLayout_ = new QVBoxLayout();
 	mainLayout_ = new QVBoxLayout();
 	headerLayout_ = new QHBoxLayout();
 
-	topLayout_->setContentsMargins(7, 0, 0, 0);
-	topLayout_->setSpacing(9);
+	topLayout_->setContentsMargins(MessageMargin, MessageMargin, 0, 0);
+	topLayout_->setSpacing(0);
 
 	topLayout_->addLayout(sideLayout_);
 	topLayout_->addLayout(mainLayout_, 1);
+
+	sideLayout_->setMargin(0);
+	sideLayout_->setSpacing(0);
+
+	mainLayout_->setContentsMargins(baseWidth * 2, 0, 0, 0);
+	mainLayout_->setSpacing(0);
+
+	headerLayout_->setMargin(0);
+	headerLayout_->setSpacing(baseWidth / 2);
 }
 
+/* 
+ * For messages created locally. The avatar and the username are displayed. 
+ */
 TimelineItem::TimelineItem(const QString &userid, const QString &color, QString body, QWidget *parent)
     : QWidget(parent)
 {
@@ -71,12 +83,13 @@ TimelineItem::TimelineItem(const QString &userid, const QString &color, QString
 
 	mainLayout_->addLayout(headerLayout_);
 	mainLayout_->addWidget(body_);
-	mainLayout_->setMargin(0);
-	mainLayout_->setSpacing(0);
 
 	AvatarProvider::resolve(userid, this);
 }
 
+/*
+ * For messages created locally. Only the text is displayed. 
+ */
 TimelineItem::TimelineItem(QString body, QWidget *parent)
     : QWidget(parent)
 {
@@ -90,11 +103,15 @@ TimelineItem::TimelineItem(QString body, QWidget *parent)
 	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)
+/*
+ * 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)
     : QWidget(parent)
 {
 	init();
@@ -113,12 +130,13 @@ TimelineItem::TimelineItem(ImageItem *image, const events::MessageEvent<msgs::Im
 
 	mainLayout_->addLayout(headerLayout_);
 	mainLayout_->addLayout(imageLayout);
-	mainLayout_->setContentsMargins(0, 4, 0, 0);
-	mainLayout_->setSpacing(0);
 
 	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)
 {
@@ -135,10 +153,11 @@ TimelineItem::TimelineItem(ImageItem *image, const events::MessageEvent<msgs::Im
 	imageLayout->addStretch(1);
 
 	mainLayout_->addLayout(imageLayout);
-	mainLayout_->setContentsMargins(0, 4, 0, 0);
-	mainLayout_->setSpacing(2);
 }
 
+/*
+ * Used to display remote notice messages.
+ */
 TimelineItem::TimelineItem(const events::MessageEvent<msgs::Notice> &event, bool with_sender, const QString &color, QWidget *parent)
     : QWidget(parent)
 {
@@ -159,22 +178,19 @@ TimelineItem::TimelineItem(const events::MessageEvent<msgs::Notice> &event, bool
 		setupAvatarLayout(displayName);
 
 		mainLayout_->addLayout(headerLayout_);
-		mainLayout_->addWidget(body_);
-		mainLayout_->setMargin(0);
-		mainLayout_->setSpacing(0);
 
 		AvatarProvider::resolve(event.sender(), this);
 	} else {
 		generateBody(body);
-
 		setupSimpleLayout();
-
-		mainLayout_->addWidget(body_);
-		mainLayout_->setMargin(0);
-		mainLayout_->setSpacing(2);
 	}
+
+	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)
     : QWidget(parent)
 {
@@ -189,37 +205,30 @@ TimelineItem::TimelineItem(const events::MessageEvent<msgs::Text> &event, bool w
 
 	if (with_sender) {
 		auto displayName = TimelineViewManager::displayName(event.sender());
-		generateBody(displayName, color, body);
 
+		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);
-
 		setupSimpleLayout();
-
-		mainLayout_->addWidget(body_);
-		mainLayout_->setMargin(0);
-		mainLayout_->setSpacing(2);
 	}
+
+	mainLayout_->addWidget(body_);
 }
 
 // Only the body is displayed.
 void TimelineItem::generateBody(const QString &body)
 {
-	QString content("<span style=\"color: #171919;\">%1</span>");
+	QString content("<span style=\"color: black;\"> %1 </span>");
 
 	body_ = new QLabel(this);
 	body_->setWordWrap(true);
-	body_->setFont(bodyFont_);
 	body_->setText(content.arg(replaceEmoji(body)));
-	body_->setAlignment(Qt::AlignTop);
+	body_->setMargin(0);
 
 	body_->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextBrowserInteraction);
 	body_->setOpenExternalLinks(true);
@@ -237,32 +246,38 @@ void TimelineItem::generateBody(const QString &userid, const QString &color, con
 	QString userContent("<span style=\"color: %1\"> %2 </span>");
 	QString bodyContent("<span style=\"color: #171717;\"> %1 </span>");
 
+	QFont usernameFont;
+	usernameFont.setBold(true);
+
 	userName_ = new QLabel(this);
-	userName_->setFont(usernameFont_);
+	userName_->setFont(usernameFont);
 	userName_->setText(userContent.arg(color).arg(sender));
-	userName_->setAlignment(Qt::AlignTop);
 
 	if (body.isEmpty())
 		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);
+	body_->setMargin(0);
 }
 
 void TimelineItem::generateTimestamp(const QDateTime &time)
 {
 	QString msg("<span style=\"color: #5d6565;\"> %1 </span>");
 
+	QFont timestampFont;
+	timestampFont.setPointSize(this->font().pointSize() * TimestampFontRatio);
+
+	QFontMetrics fm(timestampFont);
+	int topMargin = QFontMetrics(this->font()).height() - fm.height();
+
 	timestamp_ = new QLabel(this);
-	timestamp_->setFont(timestampFont_);
+	timestamp_->setFont(timestampFont);
 	timestamp_->setText(msg.arg(time.toString("HH:mm")));
-	timestamp_->setAlignment(Qt::AlignTop);
-	timestamp_->setStyleSheet("margin-top: 2px;");
+	timestamp_->setContentsMargins(0, topMargin, 0, 0);
 }
 
 QString TimelineItem::replaceEmoji(const QString &body)
@@ -274,7 +289,7 @@ QString TimelineItem::replaceEmoji(const QString &body)
 
 		// TODO: Be more precise here.
 		if (code > 9000)
-			fmtBody += "<span style=\"font-family: Emoji One; font-size: 16px\">" + QString(c) + "</span>";
+			fmtBody += "<span style=\"font-family: Emoji One; font-size: 14px\">" + QString(c) + "</span>";
 		else
 			fmtBody += c;
 	}
@@ -284,13 +299,13 @@ QString TimelineItem::replaceEmoji(const QString &body)
 
 void TimelineItem::setupAvatarLayout(const QString &userName)
 {
-	topLayout_->setContentsMargins(7, 6, 0, 0);
+	topLayout_->setContentsMargins(MessageMargin, MessageMargin, 0, 0);
 
 	userAvatar_ = new Avatar(this);
 	userAvatar_->setLetter(QChar(userName[0]).toUpper());
 	userAvatar_->setBackgroundColor(QColor("#eee"));
 	userAvatar_->setTextColor(QColor("black"));
-	userAvatar_->setSize(32);
+	userAvatar_->setSize(AvatarSize);
 
 	// TODO: The provided user name should be a UserId class
 	if (userName[0] == '@' && userName.size() > 1)
@@ -298,20 +313,29 @@ void TimelineItem::setupAvatarLayout(const QString &userName)
 
 	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);
+	// Keep only the time in plain text.
+	QTextEdit htmlText(timestamp_->text());
+	QString plainText = htmlText.toPlainText();
+
+	// 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 timestampWidth = timestamp_->fontMetrics().boundingRect(plainText).width();
+	int offset = std::max(0, AvatarSize - timestampWidth) / 2;
+
+	int defaultFontHeight = QFontMetrics(this->font()).height();
+
+	timestamp_->setAlignment(Qt::AlignTop);
+	timestamp_->setContentsMargins(offset, defaultFontHeight - timestamp_->fontMetrics().height(), offset, 0);
+	topLayout_->setContentsMargins(MessageMargin, MessageMargin / 3, 0, 0);
 }
 
 void TimelineItem::setUserAvatar(const QImage &avatar)