summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorKonstantinos Sideris <sideris.konstantin@gmail.com>2018-09-19 22:42:26 +0300
committerKonstantinos Sideris <sideris.konstantin@gmail.com>2018-09-19 22:42:26 +0300
commit1716502eff3e5108f05aba8acbabd5c9287d624c (patch)
treefe16cfce143a3350c1b1453edf47adbb5e13f665 /src
parentci: Don't count errors during brew upgrade (diff)
downloadnheko-1716502eff3e5108f05aba8acbabd5c9287d624c.tar.xz
Improvements on the system theme
Diffstat (limited to 'src')
-rw-r--r--src/MainWindow.cpp95
-rw-r--r--src/RoomInfoListItem.cpp2
-rw-r--r--src/SideBarActions.cpp3
-rw-r--r--src/TextInputWidget.cpp3
-rw-r--r--src/TopRoomBar.cpp8
-rw-r--r--src/TopRoomBar.h13
-rw-r--r--src/UserInfoWidget.cpp5
-rw-r--r--src/UserSettingsPage.cpp51
-rw-r--r--src/Utils.cpp14
-rw-r--r--src/Utils.h3
-rw-r--r--src/dialogs/CreateRoom.cpp38
-rw-r--r--src/dialogs/CreateRoom.h9
-rw-r--r--src/dialogs/InviteUsers.cpp37
-rw-r--r--src/dialogs/InviteUsers.h9
-rw-r--r--src/dialogs/JoinRoom.cpp36
-rw-r--r--src/dialogs/JoinRoom.h9
-rw-r--r--src/dialogs/LeaveRoom.cpp38
-rw-r--r--src/dialogs/LeaveRoom.h11
-rw-r--r--src/dialogs/Logout.cpp41
-rw-r--r--src/dialogs/Logout.h11
-rw-r--r--src/dialogs/MemberList.cpp33
-rw-r--r--src/dialogs/MemberList.h8
-rw-r--r--src/dialogs/ReadReceipts.cpp19
-rw-r--r--src/dialogs/ReadReceipts.h3
-rw-r--r--src/dialogs/RoomSettings.cpp41
-rw-r--r--src/dialogs/RoomSettings.h7
-rw-r--r--src/dialogs/UserProfile.cpp19
-rw-r--r--src/dialogs/UserProfile.h3
-rw-r--r--src/timeline/TimelineItem.cpp8
-rw-r--r--src/timeline/TimelineItem.h2
-rw-r--r--src/ui/TextField.cpp20
31 files changed, 269 insertions, 330 deletions
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index e6e75ee1..72424d12 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -310,7 +310,8 @@ MainWindow::openUserProfile(const QString &user_id, const QString &room_id)
         auto dialog = new dialogs::UserProfile(this);
         dialog->init(user_id, room_id);
 
-        showTransparentOverlayModal(dialog);
+        dialog->raise();
+        dialog->show();
 }
 
 void
@@ -319,20 +320,19 @@ MainWindow::openRoomSettings(const QString &room_id)
         const auto roomToSearch = room_id.isEmpty() ? chat_page_->currentRoom() : "";
 
         auto dialog = new dialogs::RoomSettings(roomToSearch, this);
-        connect(dialog, &dialogs::RoomSettings::closing, this, [this]() {
-                if (modal_)
-                        modal_->hide();
-        });
 
-        showTransparentOverlayModal(dialog);
+        dialog->raise();
+        dialog->show();
 }
 
 void
 MainWindow::openMemberListDialog(const QString &room_id)
 {
         const auto roomToSearch = room_id.isEmpty() ? chat_page_->currentRoom() : "";
+        auto dialog             = new dialogs::MemberList(roomToSearch, this);
 
-        showTransparentOverlayModal(new dialogs::MemberList(roomToSearch, this));
+        dialog->raise();
+        dialog->show();
 }
 
 void
@@ -341,15 +341,12 @@ MainWindow::openLeaveRoomDialog(const QString &room_id)
         auto roomToLeave = room_id.isEmpty() ? chat_page_->currentRoom() : room_id;
 
         auto dialog = new dialogs::LeaveRoom(this);
-        connect(dialog, &dialogs::LeaveRoom::closing, this, [this, roomToLeave](bool leaving) {
-                if (modal_)
-                        modal_->hide();
-
-                if (leaving)
-                        chat_page_->leaveRoom(roomToLeave);
+        connect(dialog, &dialogs::LeaveRoom::leaving, this, [this, roomToLeave]() {
+                chat_page_->leaveRoom(roomToLeave);
         });
 
-        showTransparentOverlayModal(dialog, Qt::AlignCenter);
+        dialog->raise();
+        dialog->show();
 }
 
 void
@@ -368,35 +365,26 @@ void
 MainWindow::openInviteUsersDialog(std::function<void(const QStringList &invitees)> callback)
 {
         auto dialog = new dialogs::InviteUsers(this);
-        connect(dialog,
-                &dialogs::InviteUsers::closing,
-                this,
-                [this, callback](bool isSending, QStringList invitees) {
-                        if (modal_)
-                                modal_->hide();
-                        if (isSending && !invitees.isEmpty())
-                                callback(invitees);
-                });
-
-        showTransparentOverlayModal(dialog);
+        connect(dialog, &dialogs::InviteUsers::sendInvites, this, [callback](QStringList invitees) {
+                if (!invitees.isEmpty())
+                        callback(invitees);
+        });
+
+        dialog->raise();
+        dialog->show();
 }
 
 void
 MainWindow::openJoinRoomDialog(std::function<void(const QString &room_id)> callback)
 {
         auto dialog = new dialogs::JoinRoom(this);
-        connect(dialog,
-                &dialogs::JoinRoom::closing,
-                this,
-                [this, callback](bool isJoining, const QString &room) {
-                        if (modal_)
-                                modal_->hide();
-
-                        if (isJoining && !room.isEmpty())
-                                callback(room);
-                });
+        connect(dialog, &dialogs::JoinRoom::joinRoom, this, [callback](const QString &room) {
+                if (!room.isEmpty())
+                        callback(room);
+        });
 
-        showTransparentOverlayModal(dialog, Qt::AlignCenter);
+        dialog->raise();
+        dialog->show();
 }
 
 void
@@ -405,17 +393,12 @@ MainWindow::openCreateRoomDialog(
 {
         auto dialog = new dialogs::CreateRoom(this);
         connect(dialog,
-                &dialogs::CreateRoom::closing,
+                &dialogs::CreateRoom::createRoom,
                 this,
-                [this, callback](bool isCreating, const mtx::requests::CreateRoom &request) {
-                        if (modal_)
-                                modal_->hide();
-
-                        if (isCreating)
-                                callback(request);
-                });
+                [callback](const mtx::requests::CreateRoom &request) { callback(request); });
 
-        showTransparentOverlayModal(dialog);
+        dialog->raise();
+        dialog->show();
 }
 
 void
@@ -444,22 +427,11 @@ void
 MainWindow::openLogoutDialog()
 {
         auto dialog = new dialogs::Logout(this);
-        connect(dialog, &dialogs::Logout::closing, this, [this](bool logging_out) {
-                if (modal_)
-                        modal_->hide();
-
-                // By initiating the logout process a new overlay widget
-                // will replace & destroy the previous widget (logout dialog).
-                //
-                // This will force the destruction of the logout widget to
-                // happen after the click event has been fully processed.
-                QTimer::singleShot(0, this, [logging_out, this]() {
-                        if (logging_out)
-                                chat_page_->initiateLogout();
-                });
-        });
+        connect(
+          dialog, &dialogs::Logout::loggingOut, this, [this]() { chat_page_->initiateLogout(); });
 
-        showTransparentOverlayModal(dialog, Qt::AlignCenter);
+        dialog->raise();
+        dialog->show();
 }
 
 void
@@ -480,7 +452,8 @@ MainWindow::openReadReceiptsDialog(const QString &event_id)
                 return;
         }
 
-        showTransparentOverlayModal(dialog);
+        dialog->raise();
+        dialog->show();
 }
 
 bool
diff --git a/src/RoomInfoListItem.cpp b/src/RoomInfoListItem.cpp
index a0d35b0c..ed3b081c 100644
--- a/src/RoomInfoListItem.cpp
+++ b/src/RoomInfoListItem.cpp
@@ -32,7 +32,7 @@
 constexpr int MaxUnreadCountDisplayed = 99;
 
 constexpr int Padding          = 9;
-constexpr int UnreadLineWidth  = 4;
+constexpr int UnreadLineWidth  = 6;
 constexpr int UnreadLineOffset = 4;
 constexpr int IconSize         = 44;
 constexpr int MaxHeight        = IconSize + 2 * Padding;
diff --git a/src/SideBarActions.cpp b/src/SideBarActions.cpp
index 2b66749f..1c215592 100644
--- a/src/SideBarActions.cpp
+++ b/src/SideBarActions.cpp
@@ -103,7 +103,4 @@ SideBarActions::paintEvent(QPaintEvent *)
         opt.init(this);
         QPainter p(this);
         style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
-
-        p.setPen(QPen(borderColor()));
-        p.drawLine(QPointF(0, 0), QPointF(width(), 0));
 }
diff --git a/src/TextInputWidget.cpp b/src/TextInputWidget.cpp
index 3c5fa9e9..7167f572 100644
--- a/src/TextInputWidget.cpp
+++ b/src/TextInputWidget.cpp
@@ -640,9 +640,6 @@ TextInputWidget::paintEvent(QPaintEvent *)
         QPainter p(this);
 
         style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
-
-        p.setPen(QPen(borderColor()));
-        p.drawLine(QPointF(0, 0), QPointF(width(), 0));
 }
 
 void
diff --git a/src/TopRoomBar.cpp b/src/TopRoomBar.cpp
index d9c4a3ae..5fc6ab4a 100644
--- a/src/TopRoomBar.cpp
+++ b/src/TopRoomBar.cpp
@@ -22,6 +22,7 @@
 #include "MainWindow.h"
 #include "TopRoomBar.h"
 #include "Utils.h"
+#include "timeline/TimelineItem.h"
 #include "ui/Avatar.h"
 #include "ui/FlatButton.h"
 #include "ui/Menu.h"
@@ -55,7 +56,9 @@ TopRoomBar::TopRoomBar(QWidget *parent)
         QFont descriptionFont("Open Sans");
         descriptionFont.setPixelSize(conf::topRoomBar::fonts::roomDescription);
 
-        topicLabel_ = new QLabel(this);
+        topicLabel_ = new TextLabel(this);
+        topicLabel_->setLineWrapMode(QTextEdit::NoWrap);
+        topicLabel_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
         topicLabel_->setFont(descriptionFont);
         topicLabel_->setTextInteractionFlags(Qt::TextBrowserInteraction);
         topicLabel_->setOpenExternalLinks(true);
@@ -180,6 +183,7 @@ void
 TopRoomBar::updateRoomTopic(QString topic)
 {
         topic.replace(conf::strings::url_regex, conf::strings::url_html);
-        topicLabel_->setText(topic);
+        topicLabel_->clearLinks();
+        topicLabel_->setHtml(topic);
         update();
 }
diff --git a/src/TopRoomBar.h b/src/TopRoomBar.h
index 42f647db..5b7d3344 100644
--- a/src/TopRoomBar.h
+++ b/src/TopRoomBar.h
@@ -31,6 +31,7 @@
 class Avatar;
 class FlatButton;
 class Menu;
+class TextLabel;
 class OverlayModal;
 
 class TopRoomBar : public QWidget
@@ -76,22 +77,14 @@ protected:
                 opt.init(this);
                 QPainter p(this);
                 style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
-
-#if !defined(Q_OS_MAC)
-                p.setPen(QPen(borderColor()));
-                p.drawLine(QPointF(0, height() - p.pen().width()), QPointF(width(), height()));
-#else
-                p.setPen(QPen(borderColor()));
-                p.drawLine(QPointF(0, height()), QPointF(width(), height()));
-#endif
         }
 
 private:
         QHBoxLayout *topLayout_  = nullptr;
         QVBoxLayout *textLayout_ = nullptr;
 
-        QLabel *nameLabel_  = nullptr;
-        QLabel *topicLabel_ = nullptr;
+        QLabel *nameLabel_     = nullptr;
+        TextLabel *topicLabel_ = nullptr;
 
         Menu *menu_;
         QAction *leaveRoom_    = nullptr;
diff --git a/src/UserInfoWidget.cpp b/src/UserInfoWidget.cpp
index c3f541ba..0677b9cb 100644
--- a/src/UserInfoWidget.cpp
+++ b/src/UserInfoWidget.cpp
@@ -160,9 +160,4 @@ UserInfoWidget::paintEvent(QPaintEvent *event)
         opt.init(this);
         QPainter p(this);
         style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
-
-#if !defined(Q_OS_MAC)
-        p.setPen(QPen(borderColor()));
-        p.drawLine(QPointF(0, height() - p.pen().width()), QPointF(width(), height()));
-#endif
 }
diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp
index b8223a58..7e7f601d 100644
--- a/src/UserSettingsPage.cpp
+++ b/src/UserSettingsPage.cpp
@@ -66,14 +66,11 @@ void
 UserSettings::applyTheme()
 {
         QFile stylefile;
-        QPalette pal;
 
         if (theme() == "light") {
                 stylefile.setFileName(":/styles/styles/nheko.qss");
-                pal.setColor(QPalette::Link, QColor("#333"));
         } else if (theme() == "dark") {
                 stylefile.setFileName(":/styles/styles/nheko-dark.qss");
-                pal.setColor(QPalette::Link, QColor("#d7d9dc"));
         } else {
                 stylefile.setFileName(":/styles/styles/system.qss");
         }
@@ -81,7 +78,6 @@ UserSettings::applyTheme()
         stylefile.open(QFile::ReadOnly);
         QString stylesheet = QString(stylefile.readAll());
 
-        QApplication::setPalette(pal);
         qobject_cast<QApplication *>(QApplication::instance())->setStyleSheet(stylesheet);
 }
 
@@ -145,7 +141,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
         trayToggle_ = new Toggle(this);
 
         trayOptionLayout_->addWidget(trayLabel);
-        trayOptionLayout_->addWidget(trayToggle_, 0, Qt::AlignBottom | Qt::AlignRight);
+        trayOptionLayout_->addWidget(trayToggle_, 0, Qt::AlignRight);
 
         auto startInTrayOptionLayout_ = new QHBoxLayout;
         startInTrayOptionLayout_->setContentsMargins(0, OptionMargin, 0, OptionMargin);
@@ -156,8 +152,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
                 startInTrayToggle_->setDisabled(true);
 
         startInTrayOptionLayout_->addWidget(startInTrayLabel);
-        startInTrayOptionLayout_->addWidget(
-          startInTrayToggle_, 0, Qt::AlignBottom | Qt::AlignRight);
+        startInTrayOptionLayout_->addWidget(startInTrayToggle_, 0, Qt::AlignRight);
 
         auto orderRoomLayout = new QHBoxLayout;
         orderRoomLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin);
@@ -166,7 +161,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
         roomOrderToggle_ = new Toggle(this);
 
         orderRoomLayout->addWidget(orderLabel);
-        orderRoomLayout->addWidget(roomOrderToggle_, 0, Qt::AlignBottom | Qt::AlignRight);
+        orderRoomLayout->addWidget(roomOrderToggle_, 0, Qt::AlignRight);
 
         auto groupViewLayout = new QHBoxLayout;
         groupViewLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin);
@@ -175,7 +170,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
         groupViewToggle_ = new Toggle(this);
 
         groupViewLayout->addWidget(groupViewLabel);
-        groupViewLayout->addWidget(groupViewToggle_, 0, Qt::AlignBottom | Qt::AlignRight);
+        groupViewLayout->addWidget(groupViewToggle_, 0, Qt::AlignRight);
 
         auto typingLayout = new QHBoxLayout;
         typingLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin);
@@ -184,7 +179,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
         typingNotifications_ = new Toggle(this);
 
         typingLayout->addWidget(typingLabel);
-        typingLayout->addWidget(typingNotifications_, 0, Qt::AlignBottom | Qt::AlignRight);
+        typingLayout->addWidget(typingNotifications_, 0, Qt::AlignRight);
 
         auto receiptsLayout = new QHBoxLayout;
         receiptsLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin);
@@ -193,7 +188,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
         readReceipts_ = new Toggle(this);
 
         receiptsLayout->addWidget(receiptsLabel);
-        receiptsLayout->addWidget(readReceipts_, 0, Qt::AlignBottom | Qt::AlignRight);
+        receiptsLayout->addWidget(readReceipts_, 0, Qt::AlignRight);
 
         auto desktopLayout = new QHBoxLayout;
         desktopLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin);
@@ -202,7 +197,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
         desktopNotifications_ = new Toggle(this);
 
         desktopLayout->addWidget(desktopLabel);
-        desktopLayout->addWidget(desktopNotifications_, 0, Qt::AlignBottom | Qt::AlignRight);
+        desktopLayout->addWidget(desktopNotifications_, 0, Qt::AlignRight);
 
         auto scaleFactorOptionLayout = new QHBoxLayout;
         scaleFactorOptionLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin);
@@ -220,7 +215,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
         scaleFactorCombo_->addItem("3");
 
         scaleFactorOptionLayout->addWidget(scaleFactorLabel);
-        scaleFactorOptionLayout->addWidget(scaleFactorCombo_, 0, Qt::AlignBottom | Qt::AlignRight);
+        scaleFactorOptionLayout->addWidget(scaleFactorCombo_, 0, Qt::AlignRight);
 
         auto themeOptionLayout_ = new QHBoxLayout;
         themeOptionLayout_->setContentsMargins(0, OptionMargin, 0, OptionMargin);
@@ -232,15 +227,15 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
         themeCombo_->addItem("System");
 
         themeOptionLayout_->addWidget(themeLabel_);
-        themeOptionLayout_->addWidget(themeCombo_, 0, Qt::AlignBottom | Qt::AlignRight);
+        themeOptionLayout_->addWidget(themeCombo_, 0, Qt::AlignRight);
 
         auto encryptionLayout_ = new QVBoxLayout;
         encryptionLayout_->setContentsMargins(0, OptionMargin, 0, OptionMargin);
-        encryptionLayout_->setAlignment(Qt::AlignVCenter | Qt::AlignBottom);
+        encryptionLayout_->setAlignment(Qt::AlignVCenter);
 
-        QFont monospaceFont = QFont(font);
-        monospaceFont.setFamily("Courier New");
-        monospaceFont.setStyleHint(QFont::Courier);
+        QFont monospaceFont;
+        monospaceFont.setFamily("Monospace");
+        monospaceFont.setStyleHint(QFont::Monospace);
         monospaceFont.setPointSizeF(monospaceFont.pointSizeF() * 0.9);
 
         auto deviceIdLayout = new QHBoxLayout;
@@ -248,6 +243,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
 
         auto deviceIdLabel = new QLabel(tr("Device ID"), this);
         deviceIdLabel->setFont(font);
+        deviceIdLabel->setMargin(0);
         deviceIdValue_ = new QLabel{this};
         deviceIdValue_->setTextInteractionFlags(Qt::TextSelectableByMouse);
         deviceIdValue_->setFont(monospaceFont);
@@ -259,6 +255,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
 
         auto deviceFingerprintLabel = new QLabel(tr("Device Fingerprint"), this);
         deviceFingerprintLabel->setFont(font);
+        deviceFingerprintLabel->setMargin(0);
         deviceFingerprintValue_ = new QLabel{this};
         deviceFingerprintValue_->setTextInteractionFlags(Qt::TextSelectableByMouse);
         deviceFingerprintValue_->setFont(monospaceFont);
@@ -271,18 +268,18 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
         sessionKeysLabel->setFont(font);
         sessionKeysLayout->addWidget(sessionKeysLabel, 1);
 
-        auto sessionKeysImportBtn = new FlatButton(tr("IMPORT"), this);
+        auto sessionKeysImportBtn = new QPushButton{tr("IMPORT"), this};
         connect(
           sessionKeysImportBtn, &QPushButton::clicked, this, &UserSettingsPage::importSessionKeys);
-        auto sessionKeysExportBtn = new FlatButton(tr("EXPORT"), this);
+        auto sessionKeysExportBtn = new QPushButton{tr("EXPORT"), this};
         connect(
           sessionKeysExportBtn, &QPushButton::clicked, this, &UserSettingsPage::exportSessionKeys);
-        sessionKeysLayout->addWidget(sessionKeysExportBtn);
-        sessionKeysLayout->addWidget(sessionKeysImportBtn);
+        sessionKeysLayout->addWidget(sessionKeysExportBtn, 0, Qt::AlignRight);
+        sessionKeysLayout->addWidget(sessionKeysImportBtn, 0, Qt::AlignRight);
 
         encryptionLayout_->addLayout(deviceIdLayout);
         encryptionLayout_->addLayout(deviceFingerprintLayout);
-        encryptionLayout_->addWidget(new HorizontalLine(this));
+        encryptionLayout_->addWidget(new HorizontalLine{this});
         encryptionLayout_->addLayout(sessionKeysLayout);
 
         font.setWeight(65);
@@ -493,8 +490,10 @@ UserSettingsPage::importSessionKeys()
                                               QLineEdit::Password,
                                               "",
                                               &ok);
+        if (!ok)
+                return;
 
-        if (!ok || password.isEmpty()) {
+        if (password.isEmpty()) {
                 QMessageBox::warning(this, tr("Error"), tr("The password cannot be empty"));
                 return;
         }
@@ -523,8 +522,10 @@ UserSettingsPage::exportSessionKeys()
                                               QLineEdit::Password,
                                               "",
                                               &ok);
+        if (!ok)
+                return;
 
-        if (!ok || password.isEmpty()) {
+        if (password.isEmpty()) {
                 QMessageBox::warning(this, tr("Error"), tr("The password cannot be empty"));
                 return;
         }
diff --git a/src/Utils.cpp b/src/Utils.cpp
index 221f89a0..41be9e08 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -370,3 +370,17 @@ utils::markdownToHtml(const QString &text)
 
         return result;
 }
+
+QString
+utils::linkColor()
+{
+        QSettings settings;
+        const auto theme = settings.value("user/theme", "light").toString();
+
+        if (theme == "light")
+                return "#0077b5";
+        else if (theme == "dark")
+                return "#38A3D8";
+
+        return QPalette().color(QPalette::Link).name();
+}
diff --git a/src/Utils.h b/src/Utils.h
index 1d976000..f0973a8a 100644
--- a/src/Utils.h
+++ b/src/Utils.h
@@ -220,4 +220,7 @@ linkifyMessage(const QString &body);
 //! Convert the input markdown text to html.
 QString
 markdownToHtml(const QString &text);
+
+QString
+linkColor();
 }
diff --git a/src/dialogs/CreateRoom.cpp b/src/dialogs/CreateRoom.cpp
index 51f38fa8..bfd1e751 100644
--- a/src/dialogs/CreateRoom.cpp
+++ b/src/dialogs/CreateRoom.cpp
@@ -1,12 +1,11 @@
 #include <QComboBox>
 #include <QLabel>
-#include <QStyleOption>
+#include <QPushButton>
 #include <QVBoxLayout>
 
 #include "dialogs/CreateRoom.h"
 
 #include "Config.h"
-#include "ui/FlatButton.h"
 #include "ui/TextField.h"
 #include "ui/Theme.h"
 #include "ui/ToggleButton.h"
@@ -16,6 +15,11 @@ using namespace dialogs;
 CreateRoom::CreateRoom(QWidget *parent)
   : QFrame(parent)
 {
+        setAutoFillBackground(true);
+        setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
+        setWindowModality(Qt::WindowModal);
+        setAttribute(Qt::WA_DeleteOnClose, true);
+
         QFont doubleFont;
         doubleFont.setPointSizeF(doubleFont.pointSizeF() * 2);
 
@@ -29,21 +33,15 @@ CreateRoom::CreateRoom(QWidget *parent)
         layout->setMargin(conf::modals::WIDGET_MARGIN);
 
         auto buttonLayout = new QHBoxLayout();
-        buttonLayout->setSpacing(0);
-        buttonLayout->setMargin(0);
-
-        QFont buttonFont;
-        buttonFont.setPointSizeF(buttonFont.pointSizeF() * conf::modals::BUTTON_TEXT_SIZE_RATIO);
-
-        confirmBtn_ = new FlatButton("CREATE", this);
-        confirmBtn_->setFont(buttonFont);
+        buttonLayout->setSpacing(15);
 
-        cancelBtn_ = new FlatButton(tr("CANCEL"), this);
-        cancelBtn_->setFont(buttonFont);
+        confirmBtn_ = new QPushButton(tr("Create room"), this);
+        cancelBtn_  = new QPushButton(tr("Cancel"), this);
+        cancelBtn_->setDefault(true);
 
         buttonLayout->addStretch(1);
-        buttonLayout->addWidget(confirmBtn_);
         buttonLayout->addWidget(cancelBtn_);
+        buttonLayout->addWidget(confirmBtn_);
 
         QFont font;
         font.setPixelSize(conf::headerFontSize);
@@ -104,15 +102,14 @@ CreateRoom::CreateRoom(QWidget *parent)
                 request_.topic           = topicInput_->text().toStdString();
                 request_.room_alias_name = aliasInput_->text().toStdString();
 
-                emit closing(true, request_);
+                emit createRoom(request_);
 
                 clearFields();
         });
 
         connect(cancelBtn_, &QPushButton::clicked, this, [this]() {
-                emit closing(false, request_);
-
                 clearFields();
+                emit close();
         });
 
         connect(visibilityCombo_,
@@ -151,15 +148,6 @@ CreateRoom::clearFields()
 }
 
 void
-CreateRoom::paintEvent(QPaintEvent *)
-{
-        QStyleOption opt;
-        opt.init(this);
-        QPainter p(this);
-        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
-}
-
-void
 CreateRoom::showEvent(QShowEvent *event)
 {
         nameInput_->setFocus();
diff --git a/src/dialogs/CreateRoom.h b/src/dialogs/CreateRoom.h
index 46edebdc..22ac6a43 100644
--- a/src/dialogs/CreateRoom.h
+++ b/src/dialogs/CreateRoom.h
@@ -4,7 +4,7 @@
 
 #include <mtx.hpp>
 
-class FlatButton;
+class QPushButton;
 class TextField;
 class QComboBox;
 class Toggle;
@@ -18,10 +18,9 @@ public:
         CreateRoom(QWidget *parent = nullptr);
 
 signals:
-        void closing(bool isCreating, const mtx::requests::CreateRoom &request);
+        void createRoom(const mtx::requests::CreateRoom &request);
 
 protected:
-        void paintEvent(QPaintEvent *event) override;
         void showEvent(QShowEvent *event) override;
 
 private:
@@ -32,8 +31,8 @@ private:
 
         Toggle *directToggle_;
 
-        FlatButton *confirmBtn_;
-        FlatButton *cancelBtn_;
+        QPushButton *confirmBtn_;
+        QPushButton *cancelBtn_;
 
         TextField *nameInput_;
         TextField *topicInput_;
diff --git a/src/dialogs/InviteUsers.cpp b/src/dialogs/InviteUsers.cpp
index 8361468a..635a205e 100644
--- a/src/dialogs/InviteUsers.cpp
+++ b/src/dialogs/InviteUsers.cpp
@@ -2,6 +2,7 @@
 #include <QIcon>
 #include <QListWidget>
 #include <QListWidgetItem>
+#include <QPushButton>
 #include <QStyleOption>
 #include <QTimer>
 #include <QVBoxLayout>
@@ -10,7 +11,6 @@
 
 #include "Config.h"
 #include "InviteeItem.h"
-#include "ui/FlatButton.h"
 #include "ui/TextField.h"
 
 #include "mtx.hpp"
@@ -20,6 +20,11 @@ using namespace dialogs;
 InviteUsers::InviteUsers(QWidget *parent)
   : QFrame(parent)
 {
+        setAutoFillBackground(true);
+        setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
+        setWindowModality(Qt::WindowModal);
+        setAttribute(Qt::WA_DeleteOnClose, true);
+
         setMinimumWidth(conf::modals::MIN_WIDGET_WIDTH);
         setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
 
@@ -31,18 +36,14 @@ InviteUsers::InviteUsers(QWidget *parent)
         buttonLayout->setSpacing(0);
         buttonLayout->setMargin(0);
 
-        QFont buttonFont;
-        buttonFont.setPointSizeF(buttonFont.pointSizeF() * conf::modals::BUTTON_TEXT_SIZE_RATIO);
-
-        confirmBtn_ = new FlatButton("INVITE", this);
-        confirmBtn_->setFont(buttonFont);
-
-        cancelBtn_ = new FlatButton(tr("CANCEL"), this);
-        cancelBtn_->setFont(buttonFont);
+        confirmBtn_ = new QPushButton("Invite", this);
+        cancelBtn_  = new QPushButton(tr("Cancel"), this);
+        cancelBtn_->setDefault(true);
 
         buttonLayout->addStretch(1);
-        buttonLayout->addWidget(confirmBtn_);
+        buttonLayout->setSpacing(15);
         buttonLayout->addWidget(cancelBtn_);
+        buttonLayout->addWidget(confirmBtn_);
 
         inviteeInput_ = new TextField(this);
         inviteeInput_->setLabel(tr("User ID to invite"));
@@ -63,7 +64,7 @@ InviteUsers::InviteUsers(QWidget *parent)
 
         connect(inviteeInput_, &TextField::returnPressed, this, &InviteUsers::addUser);
         connect(confirmBtn_, &QPushButton::clicked, [this]() {
-                emit closing(true, invitedUsers());
+                emit sendInvites(invitedUsers());
 
                 inviteeInput_->clear();
                 inviteeList_->clear();
@@ -71,12 +72,11 @@ InviteUsers::InviteUsers(QWidget *parent)
         });
 
         connect(cancelBtn_, &QPushButton::clicked, [this]() {
-                QStringList emptyList;
-                emit closing(false, emptyList);
-
                 inviteeInput_->clear();
                 inviteeList_->clear();
                 errorLabel_->hide();
+
+                emit close();
         });
 }
 
@@ -119,15 +119,6 @@ InviteUsers::removeInvitee(QListWidgetItem *item)
         inviteeList_->removeItemWidget(widget);
 }
 
-void
-InviteUsers::paintEvent(QPaintEvent *)
-{
-        QStyleOption opt;
-        opt.init(this);
-        QPainter p(this);
-        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
-}
-
 QStringList
 InviteUsers::invitedUsers() const
 {
diff --git a/src/dialogs/InviteUsers.h b/src/dialogs/InviteUsers.h
index 41e6236a..952c97a5 100644
--- a/src/dialogs/InviteUsers.h
+++ b/src/dialogs/InviteUsers.h
@@ -5,7 +5,7 @@
 #include <QListWidgetItem>
 #include <QStringList>
 
-class FlatButton;
+class QPushButton;
 class TextField;
 class QListWidget;
 
@@ -18,11 +18,10 @@ public:
         explicit InviteUsers(QWidget *parent = nullptr);
 
 protected:
-        void paintEvent(QPaintEvent *event) override;
         void showEvent(QShowEvent *event) override;
 
 signals:
-        void closing(bool isLeaving, QStringList invitees);
+        void sendInvites(QStringList invitees);
 
 private slots:
         void removeInvitee(QListWidgetItem *item);
@@ -31,8 +30,8 @@ private:
         void addUser();
         QStringList invitedUsers() const;
 
-        FlatButton *confirmBtn_;
-        FlatButton *cancelBtn_;
+        QPushButton *confirmBtn_;
+        QPushButton *cancelBtn_;
 
         TextField *inviteeInput_;
         QLabel *errorLabel_;
diff --git a/src/dialogs/JoinRoom.cpp b/src/dialogs/JoinRoom.cpp
index 1ff6bba1..135cb4f5 100644
--- a/src/dialogs/JoinRoom.cpp
+++ b/src/dialogs/JoinRoom.cpp
@@ -1,11 +1,11 @@
 #include <QLabel>
+#include <QPushButton>
 #include <QStyleOption>
 #include <QVBoxLayout>
 
 #include "dialogs/JoinRoom.h"
 
 #include "Config.h"
-#include "ui/FlatButton.h"
 #include "ui/TextField.h"
 #include "ui/Theme.h"
 
@@ -14,6 +14,11 @@ using namespace dialogs;
 JoinRoom::JoinRoom(QWidget *parent)
   : QFrame(parent)
 {
+        setAutoFillBackground(true);
+        setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
+        setWindowModality(Qt::WindowModal);
+        setAttribute(Qt::WA_DeleteOnClose, true);
+
         setMinimumWidth(conf::modals::MIN_WIDGET_WIDTH);
         setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
 
@@ -22,21 +27,15 @@ JoinRoom::JoinRoom(QWidget *parent)
         layout->setMargin(conf::modals::WIDGET_MARGIN);
 
         auto buttonLayout = new QHBoxLayout();
-        buttonLayout->setSpacing(0);
-        buttonLayout->setMargin(0);
-
-        QFont buttonFont;
-        buttonFont.setPointSizeF(buttonFont.pointSizeF() * conf::modals::BUTTON_TEXT_SIZE_RATIO);
-
-        confirmBtn_ = new FlatButton("JOIN", this);
-        confirmBtn_->setFont(buttonFont);
+        buttonLayout->setSpacing(15);
 
-        cancelBtn_ = new FlatButton(tr("CANCEL"), this);
-        cancelBtn_->setFont(buttonFont);
+        confirmBtn_ = new QPushButton(tr("Join"), this);
+        cancelBtn_  = new QPushButton(tr("Cancel"), this);
+        cancelBtn_->setDefault(true);
 
         buttonLayout->addStretch(1);
-        buttonLayout->addWidget(confirmBtn_);
         buttonLayout->addWidget(cancelBtn_);
+        buttonLayout->addWidget(confirmBtn_);
 
         roomInput_ = new TextField(this);
         roomInput_->setLabel(tr("Room ID or alias"));
@@ -47,7 +46,7 @@ JoinRoom::JoinRoom(QWidget *parent)
 
         connect(roomInput_, &QLineEdit::returnPressed, this, &JoinRoom::handleInput);
         connect(confirmBtn_, &QPushButton::clicked, this, &JoinRoom::handleInput);
-        connect(cancelBtn_, &QPushButton::clicked, [this]() { emit closing(false, ""); });
+        connect(cancelBtn_, &QPushButton::clicked, this, &JoinRoom::close);
 }
 
 void
@@ -57,20 +56,11 @@ JoinRoom::handleInput()
                 return;
 
         // TODO: input validation with error messages.
-        emit closing(true, roomInput_->text());
+        emit joinRoom(roomInput_->text());
         roomInput_->clear();
 }
 
 void
-JoinRoom::paintEvent(QPaintEvent *)
-{
-        QStyleOption opt;
-        opt.init(this);
-        QPainter p(this);
-        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
-}
-
-void
 JoinRoom::showEvent(QShowEvent *event)
 {
         roomInput_->setFocus();
diff --git a/src/dialogs/JoinRoom.h b/src/dialogs/JoinRoom.h
index 0c2f47d7..257cb950 100644
--- a/src/dialogs/JoinRoom.h
+++ b/src/dialogs/JoinRoom.h
@@ -2,7 +2,7 @@
 
 #include <QFrame>
 
-class FlatButton;
+class QPushButton;
 class TextField;
 
 namespace dialogs {
@@ -14,18 +14,17 @@ public:
         JoinRoom(QWidget *parent = nullptr);
 
 signals:
-        void closing(bool isJoining, const QString &room);
+        void joinRoom(const QString &room);
 
 protected:
-        void paintEvent(QPaintEvent *event) override;
         void showEvent(QShowEvent *event) override;
 
 private slots:
         void handleInput();
 
 private:
-        FlatButton *confirmBtn_;
-        FlatButton *cancelBtn_;
+        QPushButton *confirmBtn_;
+        QPushButton *cancelBtn_;
 
         TextField *roomInput_;
 };
diff --git a/src/dialogs/LeaveRoom.cpp b/src/dialogs/LeaveRoom.cpp
index 30f8dace..5ac62615 100644
--- a/src/dialogs/LeaveRoom.cpp
+++ b/src/dialogs/LeaveRoom.cpp
@@ -1,11 +1,11 @@
 #include <QLabel>
+#include <QPushButton>
 #include <QStyleOption>
 #include <QVBoxLayout>
 
 #include "dialogs/LeaveRoom.h"
 
 #include "Config.h"
-#include "ui/FlatButton.h"
 #include "ui/Theme.h"
 
 using namespace dialogs;
@@ -13,6 +13,11 @@ using namespace dialogs;
 LeaveRoom::LeaveRoom(QWidget *parent)
   : QFrame(parent)
 {
+        setAutoFillBackground(true);
+        setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
+        setWindowModality(Qt::WindowModal);
+        setAttribute(Qt::WA_DeleteOnClose, true);
+
         setMinimumWidth(conf::modals::MIN_WIDGET_WIDTH);
         setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
 
@@ -24,37 +29,20 @@ LeaveRoom::LeaveRoom(QWidget *parent)
         buttonLayout->setSpacing(0);
         buttonLayout->setMargin(0);
 
-        QFont buttonFont;
-        buttonFont.setPointSizeF(buttonFont.pointSizeF() * conf::modals::BUTTON_TEXT_SIZE_RATIO);
-
-        confirmBtn_ = new FlatButton("LEAVE", this);
-        confirmBtn_->setFont(buttonFont);
-
-        cancelBtn_ = new FlatButton(tr("CANCEL"), this);
-        cancelBtn_->setFont(buttonFont);
+        confirmBtn_ = new QPushButton("Leave", this);
+        cancelBtn_  = new QPushButton(tr("Cancel"), this);
+        cancelBtn_->setDefault(true);
 
         buttonLayout->addStretch(1);
-        buttonLayout->addWidget(confirmBtn_);
+        buttonLayout->setSpacing(15);
         buttonLayout->addWidget(cancelBtn_);
-
-        QFont font;
-        font.setPointSizeF(font.pointSizeF() * conf::modals::LABEL_MEDIUM_SIZE_RATIO);
+        buttonLayout->addWidget(confirmBtn_);
 
         auto label = new QLabel(tr("Are you sure you want to leave?"), this);
-        label->setFont(font);
 
         layout->addWidget(label);
         layout->addLayout(buttonLayout);
 
-        connect(confirmBtn_, &QPushButton::clicked, [this]() { emit closing(true); });
-        connect(cancelBtn_, &QPushButton::clicked, [this]() { emit closing(false); });
-}
-
-void
-LeaveRoom::paintEvent(QPaintEvent *)
-{
-        QStyleOption opt;
-        opt.init(this);
-        QPainter p(this);
-        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
+        connect(confirmBtn_, &QPushButton::clicked, this, &LeaveRoom::leaving);
+        connect(cancelBtn_, &QPushButton::clicked, this, &LeaveRoom::close);
 }
diff --git a/src/dialogs/LeaveRoom.h b/src/dialogs/LeaveRoom.h
index 98e4938d..a35cf04d 100644
--- a/src/dialogs/LeaveRoom.h
+++ b/src/dialogs/LeaveRoom.h
@@ -2,7 +2,7 @@
 
 #include <QFrame>
 
-class FlatButton;
+class QPushButton;
 
 namespace dialogs {
 
@@ -12,14 +12,11 @@ class LeaveRoom : public QFrame
 public:
         explicit LeaveRoom(QWidget *parent = nullptr);
 
-protected:
-        void paintEvent(QPaintEvent *event) override;
-
 signals:
-        void closing(bool isLeaving);
+        void leaving();
 
 private:
-        FlatButton *confirmBtn_;
-        FlatButton *cancelBtn_;
+        QPushButton *confirmBtn_;
+        QPushButton *cancelBtn_;
 };
 } // dialogs
diff --git a/src/dialogs/Logout.cpp b/src/dialogs/Logout.cpp
index 54ccb7c6..882ef915 100644
--- a/src/dialogs/Logout.cpp
+++ b/src/dialogs/Logout.cpp
@@ -17,13 +17,14 @@
 
 #include <QLabel>
 #include <QPaintEvent>
+#include <QPainter>
+#include <QPushButton>
 #include <QStyleOption>
 #include <QVBoxLayout>
 
 #include "dialogs/Logout.h"
 
 #include "Config.h"
-#include "ui/FlatButton.h"
 #include "ui/Theme.h"
 
 using namespace dialogs;
@@ -31,6 +32,11 @@ using namespace dialogs;
 Logout::Logout(QWidget *parent)
   : QFrame(parent)
 {
+        setAutoFillBackground(true);
+        setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
+        setWindowModality(Qt::WindowModal);
+        setAttribute(Qt::WA_DeleteOnClose, true);
+
         setMinimumWidth(conf::modals::MIN_WIDGET_WIDTH);
         setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
 
@@ -42,40 +48,21 @@ Logout::Logout(QWidget *parent)
         buttonLayout->setSpacing(0);
         buttonLayout->setMargin(0);
 
-        QFont buttonFont;
-        buttonFont.setPointSizeF(buttonFont.pointSizeF() * conf::modals::BUTTON_TEXT_SIZE_RATIO);
-
-        confirmBtn_ = new FlatButton("OK", this);
-        confirmBtn_->setFont(buttonFont);
-        confirmBtn_->setRippleStyle(ui::RippleStyle::NoRipple);
-
-        cancelBtn_ = new FlatButton(tr("CANCEL"), this);
-        cancelBtn_->setFont(buttonFont);
-        cancelBtn_->setRippleStyle(ui::RippleStyle::NoRipple);
+        confirmBtn_ = new QPushButton("Logout", this);
+        cancelBtn_  = new QPushButton(tr("Cancel"), this);
+        cancelBtn_->setDefault(true);
 
         buttonLayout->addStretch(1);
-        buttonLayout->addWidget(confirmBtn_);
+        buttonLayout->setSpacing(15);
         buttonLayout->addWidget(cancelBtn_);
-
-        QFont font;
-        font.setPointSizeF(font.pointSizeF() * conf::modals::LABEL_MEDIUM_SIZE_RATIO);
+        buttonLayout->addWidget(confirmBtn_);
 
         auto label = new QLabel(tr("Logout. Are you sure?"), this);
-        label->setFont(font);
 
         layout->addWidget(label);
         layout->addLayout(buttonLayout);
         layout->addStretch(1);
 
-        connect(confirmBtn_, &QPushButton::clicked, [this]() { emit closing(true); });
-        connect(cancelBtn_, &QPushButton::clicked, [this]() { emit closing(false); });
-}
-
-void
-Logout::paintEvent(QPaintEvent *)
-{
-        QStyleOption opt;
-        opt.init(this);
-        QPainter p(this);
-        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
+        connect(confirmBtn_, &QPushButton::clicked, this, &Logout::loggingOut);
+        connect(cancelBtn_, &QPushButton::clicked, this, &Logout::close);
 }
diff --git a/src/dialogs/Logout.h b/src/dialogs/Logout.h
index cfefb970..b7e962eb 100644
--- a/src/dialogs/Logout.h
+++ b/src/dialogs/Logout.h
@@ -19,7 +19,7 @@
 
 #include <QFrame>
 
-class FlatButton;
+class QPushButton;
 
 namespace dialogs {
 
@@ -29,14 +29,11 @@ class Logout : public QFrame
 public:
         explicit Logout(QWidget *parent = nullptr);
 
-protected:
-        void paintEvent(QPaintEvent *event) override;
-
 signals:
-        void closing(bool isLoggingOut);
+        void loggingOut();
 
 private:
-        FlatButton *confirmBtn_;
-        FlatButton *cancelBtn_;
+        QPushButton *confirmBtn_;
+        QPushButton *cancelBtn_;
 };
 } // dialogs
diff --git a/src/dialogs/MemberList.cpp b/src/dialogs/MemberList.cpp
index b353229f..bd9b1edf 100644
--- a/src/dialogs/MemberList.cpp
+++ b/src/dialogs/MemberList.cpp
@@ -1,5 +1,7 @@
 #include <QListWidgetItem>
 #include <QPainter>
+#include <QPushButton>
+#include <QShortcut>
 #include <QStyleOption>
 #include <QVBoxLayout>
 
@@ -11,7 +13,6 @@
 #include "Config.h"
 #include "Utils.h"
 #include "ui/Avatar.h"
-#include "ui/FlatButton.h"
 
 using namespace dialogs;
 
@@ -51,10 +52,22 @@ MemberItem::MemberItem(const RoomMember &member, QWidget *parent)
         topLayout_->addLayout(textLayout_, 1);
 }
 
+void
+MemberItem::paintEvent(QPaintEvent *)
+{
+        QStyleOption opt;
+        opt.init(this);
+        QPainter p(this);
+        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
+}
+
 MemberList::MemberList(const QString &room_id, QWidget *parent)
   : QFrame(parent)
   , room_id_{room_id}
 {
+        setAutoFillBackground(true);
+        setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
+        setWindowModality(Qt::WindowModal);
         setAttribute(Qt::WA_DeleteOnClose, true);
 
         auto layout = new QVBoxLayout(this);
@@ -64,7 +77,6 @@ MemberList::MemberList(const QString &room_id, QWidget *parent)
         list_ = new QListWidget;
         list_->setFrameStyle(QFrame::NoFrame);
         list_->setSelectionMode(QAbstractItemView::NoSelection);
-        list_->setAttribute(Qt::WA_MacShowFocusRect, 0);
         list_->setSpacing(5);
 
         QFont doubleFont;
@@ -89,7 +101,8 @@ MemberList::MemberList(const QString &room_id, QWidget *parent)
         list_->clear();
 
         // Add button at the bottom.
-        moreBtn_  = new FlatButton(tr("SHOW MORE"), this);
+        moreBtn_ = new QPushButton(tr("Show more"), this);
+        moreBtn_->setFlat(true);
         auto item = new QListWidgetItem;
         item->setSizeHint(moreBtn_->minimumSizeHint());
         item->setFlags(Qt::NoItemFlags);
@@ -97,7 +110,7 @@ MemberList::MemberList(const QString &room_id, QWidget *parent)
         list_->insertItem(0, item);
         list_->setItemWidget(item, moreBtn_);
 
-        connect(moreBtn_, &FlatButton::clicked, this, [this]() {
+        connect(moreBtn_, &QPushButton::clicked, this, [this]() {
                 const size_t numMembers = list_->count() - 1;
 
                 if (numMembers > 0)
@@ -109,6 +122,9 @@ MemberList::MemberList(const QString &room_id, QWidget *parent)
         } catch (const lmdb::error &e) {
                 qCritical() << e.what();
         }
+
+        auto closeShortcut = new QShortcut(QKeySequence(tr("ESC")), this);
+        connect(closeShortcut, &QShortcut::activated, this, &MemberList::close);
 }
 
 void
@@ -143,12 +159,3 @@ MemberList::addUsers(const std::vector<RoomMember> &members)
                 list_->setItemWidget(item, user);
         }
 }
-
-void
-MemberList::paintEvent(QPaintEvent *)
-{
-        QStyleOption opt;
-        opt.init(this);
-        QPainter p(this);
-        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
-}
diff --git a/src/dialogs/MemberList.h b/src/dialogs/MemberList.h
index 9c3dc5dc..ac7fe94e 100644
--- a/src/dialogs/MemberList.h
+++ b/src/dialogs/MemberList.h
@@ -4,7 +4,7 @@
 #include <QListWidget>
 
 class Avatar;
-class FlatButton;
+class QPushButton;
 class QHBoxLayout;
 class QLabel;
 class QVBoxLayout;
@@ -23,6 +23,9 @@ class MemberItem : public QWidget
 public:
         MemberItem(const RoomMember &member, QWidget *parent);
 
+protected:
+        void paintEvent(QPaintEvent *) override;
+
 private:
         QHBoxLayout *topLayout_;
         QVBoxLayout *textLayout_;
@@ -43,7 +46,6 @@ public slots:
         void addUsers(const std::vector<RoomMember> &users);
 
 protected:
-        void paintEvent(QPaintEvent *event) override;
         void hideEvent(QHideEvent *event) override
         {
                 list_->clear();
@@ -56,6 +58,6 @@ private:
         QString room_id_;
         QLabel *topLabel_;
         QListWidget *list_;
-        FlatButton *moreBtn_;
+        QPushButton *moreBtn_;
 };
 } // dialogs
diff --git a/src/dialogs/ReadReceipts.cpp b/src/dialogs/ReadReceipts.cpp
index 400963b5..5a36bd89 100644
--- a/src/dialogs/ReadReceipts.cpp
+++ b/src/dialogs/ReadReceipts.cpp
@@ -2,6 +2,7 @@
 #include <QIcon>
 #include <QListWidgetItem>
 #include <QPainter>
+#include <QShortcut>
 #include <QStyleOption>
 #include <QTimer>
 #include <QVBoxLayout>
@@ -60,6 +61,15 @@ ReceiptItem::ReceiptItem(QWidget *parent,
                                 [this](const QImage &img) { avatar_->setImage(img); });
 }
 
+void
+ReceiptItem::paintEvent(QPaintEvent *)
+{
+        QStyleOption opt;
+        opt.init(this);
+        QPainter p(this);
+        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
+}
+
 QString
 ReceiptItem::dateFormat(const QDateTime &then) const
 {
@@ -79,6 +89,11 @@ ReceiptItem::dateFormat(const QDateTime &then) const
 ReadReceipts::ReadReceipts(QWidget *parent)
   : QFrame(parent)
 {
+        setAutoFillBackground(true);
+        setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
+        setWindowModality(Qt::WindowModal);
+        setAttribute(Qt::WA_DeleteOnClose, true);
+
         auto layout = new QVBoxLayout(this);
         layout->setSpacing(conf::modals::WIDGET_SPACING);
         layout->setMargin(conf::modals::WIDGET_MARGIN);
@@ -86,7 +101,6 @@ ReadReceipts::ReadReceipts(QWidget *parent)
         userList_ = new QListWidget;
         userList_->setFrameStyle(QFrame::NoFrame);
         userList_->setSelectionMode(QAbstractItemView::NoSelection);
-        userList_->setAttribute(Qt::WA_MacShowFocusRect, 0);
         userList_->setSpacing(conf::modals::TEXT_SPACING);
 
         QFont doubleFont;
@@ -107,6 +121,9 @@ ReadReceipts::ReadReceipts(QWidget *parent)
 
         layout->addWidget(topLabel_);
         layout->addWidget(userList_);
+
+        auto closeShortcut = new QShortcut(QKeySequence(tr("ESC")), this);
+        connect(closeShortcut, &QShortcut::activated, this, &ReadReceipts::close);
 }
 
 void
diff --git a/src/dialogs/ReadReceipts.h b/src/dialogs/ReadReceipts.h
index 5e5615df..8e1b6b75 100644
--- a/src/dialogs/ReadReceipts.h
+++ b/src/dialogs/ReadReceipts.h
@@ -21,6 +21,9 @@ public:
                     uint64_t timestamp,
                     const QString &room_id);
 
+protected:
+        void paintEvent(QPaintEvent *);
+
 private:
         QString dateFormat(const QDateTime &then) const;
 
diff --git a/src/dialogs/RoomSettings.cpp b/src/dialogs/RoomSettings.cpp
index 7409c5bd..21ddc079 100644
--- a/src/dialogs/RoomSettings.cpp
+++ b/src/dialogs/RoomSettings.cpp
@@ -8,6 +8,8 @@
 #include <QMimeDatabase>
 #include <QPainter>
 #include <QPixmap>
+#include <QPushButton>
+#include <QShortcut>
 #include <QShowEvent>
 #include <QStyleOption>
 #include <QVBoxLayout>
@@ -54,24 +56,15 @@ EditModal::EditModal(const QString &roomId, QWidget *parent)
 
         auto layout = new QVBoxLayout(this);
 
-        QFont buttonFont;
-        buttonFont.setPointSizeF(buttonFont.pointSizeF() * 1.3);
-
-        applyBtn_ = new FlatButton(tr("APPLY"), this);
-        applyBtn_->setFont(buttonFont);
-        applyBtn_->setRippleStyle(ui::RippleStyle::NoRipple);
-        applyBtn_->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
-
-        cancelBtn_ = new FlatButton(tr("CANCEL"), this);
-        cancelBtn_->setFont(buttonFont);
-        cancelBtn_->setRippleStyle(ui::RippleStyle::NoRipple);
-        cancelBtn_->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
+        applyBtn_  = new QPushButton(tr("Apply"), this);
+        cancelBtn_ = new QPushButton(tr("Cancel"), this);
+        cancelBtn_->setDefault(true);
 
         auto btnLayout = new QHBoxLayout;
-        btnLayout->setMargin(5);
         btnLayout->addStretch(1);
-        btnLayout->addWidget(applyBtn_);
+        btnLayout->setSpacing(15);
         btnLayout->addWidget(cancelBtn_);
+        btnLayout->addWidget(applyBtn_);
 
         nameInput_ = new TextField(this);
         nameInput_->setLabel(tr("Name").toUpper());
@@ -172,6 +165,11 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent)
 {
         retrieveRoomInfo();
 
+        setAutoFillBackground(true);
+        setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
+        setWindowModality(Qt::WindowModal);
+        setAttribute(Qt::WA_DeleteOnClose, true);
+
         QFont doubleFont;
         doubleFont.setPointSizeF(doubleFont.pointSizeF() * 2);
 
@@ -422,6 +420,9 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent)
                 stopLoadingSpinner();
                 resetErrorLabel();
         });
+
+        auto closeShortcut = new QShortcut(QKeySequence(tr("ESC")), this);
+        connect(closeShortcut, &QShortcut::activated, this, &RoomSettings::close);
 }
 
 void
@@ -446,9 +447,10 @@ RoomSettings::setupEditButton()
         connect(editFieldsBtn_, &QPushButton::clicked, this, [this]() {
                 retrieveRoomInfo();
 
-                auto modal = new EditModal(room_id_, this->parentWidget());
+                auto modal = new EditModal(room_id_, this);
                 modal->setFields(QString::fromStdString(info_.name),
                                  QString::fromStdString(info_.topic));
+                modal->raise();
                 modal->show();
                 connect(modal, &EditModal::nameChanged, this, [this](const QString &newName) {
                         if (roomNameLabel_)
@@ -505,15 +507,6 @@ RoomSettings::showEvent(QShowEvent *event)
         QWidget::showEvent(event);
 }
 
-void
-RoomSettings::paintEvent(QPaintEvent *)
-{
-        QStyleOption opt;
-        opt.init(this);
-        QPainter p(this);
-        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
-}
-
 bool
 RoomSettings::canChangeJoinRules(const std::string &room_id, const std::string &user_id) const
 {
diff --git a/src/dialogs/RoomSettings.h b/src/dialogs/RoomSettings.h
index c2c81cdb..6667b68b 100644
--- a/src/dialogs/RoomSettings.h
+++ b/src/dialogs/RoomSettings.h
@@ -9,6 +9,7 @@
 
 class Avatar;
 class FlatButton;
+class QPushButton;
 class QComboBox;
 class QHBoxLayout;
 class QShowEvent;
@@ -100,8 +101,8 @@ private:
         TextField *nameInput_;
         TextField *topicInput_;
 
-        FlatButton *applyBtn_;
-        FlatButton *cancelBtn_;
+        QPushButton *applyBtn_;
+        QPushButton *cancelBtn_;
 };
 
 namespace dialogs {
@@ -113,13 +114,11 @@ public:
         RoomSettings(const QString &room_id, QWidget *parent = nullptr);
 
 signals:
-        void closing();
         void enableEncryptionError(const QString &msg);
         void showErrorMessage(const QString &msg);
         void accessRulesUpdated();
 
 protected:
-        void paintEvent(QPaintEvent *event) override;
         void showEvent(QShowEvent *event) override;
 
 private slots:
diff --git a/src/dialogs/UserProfile.cpp b/src/dialogs/UserProfile.cpp
index 15e0a46c..54929e03 100644
--- a/src/dialogs/UserProfile.cpp
+++ b/src/dialogs/UserProfile.cpp
@@ -3,6 +3,7 @@
 #include <QListWidget>
 #include <QPaintEvent>
 #include <QSettings>
+#include <QShortcut>
 #include <QStyleOption>
 #include <QVBoxLayout>
 
@@ -48,6 +49,11 @@ DeviceItem::DeviceItem(DeviceInfo device, QWidget *parent)
 UserProfile::UserProfile(QWidget *parent)
   : QWidget(parent)
 {
+        setAutoFillBackground(true);
+        setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
+        setWindowModality(Qt::WindowModal);
+        setAttribute(Qt::WA_DeleteOnClose, true);
+
         QIcon banIcon, kickIcon, ignoreIcon, startChatIcon;
 
         banIcon.addFile(":/icons/icons/ui/do-not-disturb-rounded-sign.png");
@@ -134,6 +140,7 @@ UserProfile::UserProfile(QWidget *parent)
         devices_->setSelectionMode(QAbstractItemView::NoSelection);
         devices_->setAttribute(Qt::WA_MacShowFocusRect, 0);
         devices_->setSpacing(DEVICE_SPACING);
+        devices_->setMinimumHeight(devices_->sizeHint().height() * 1.2);
         devices_->hide();
 
         QFont descriptionLabelFont;
@@ -170,6 +177,9 @@ UserProfile::UserProfile(QWidget *parent)
         vlayout->setContentsMargins(WIDGET_MARGIN, TOP_WIDGET_MARGIN, WIDGET_MARGIN, WIDGET_MARGIN);
 
         qRegisterMetaType<std::vector<DeviceInfo>>();
+
+        auto closeShortcut = new QShortcut(QKeySequence(tr("ESC")), this);
+        connect(closeShortcut, &QShortcut::activated, this, &UserProfile::close);
 }
 
 void
@@ -292,12 +302,3 @@ UserProfile::updateDeviceList(const QString &user_id, const std::vector<DeviceIn
         devicesLabel_->show();
         devices_->show();
 }
-
-void
-UserProfile::paintEvent(QPaintEvent *)
-{
-        QStyleOption opt;
-        opt.init(this);
-        QPainter p(this);
-        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
-}
diff --git a/src/dialogs/UserProfile.h b/src/dialogs/UserProfile.h
index 7dc1c0c8..0f684cda 100644
--- a/src/dialogs/UserProfile.h
+++ b/src/dialogs/UserProfile.h
@@ -48,9 +48,6 @@ public:
 
         void init(const QString &userId, const QString &roomId);
 
-protected:
-        void paintEvent(QPaintEvent *) override;
-
 private slots:
         void updateDeviceList(const QString &user_id, const std::vector<DeviceInfo> &devices);
 
diff --git a/src/timeline/TimelineItem.cpp b/src/timeline/TimelineItem.cpp
index 18598487..fcc2accf 100644
--- a/src/timeline/TimelineItem.cpp
+++ b/src/timeline/TimelineItem.cpp
@@ -41,9 +41,15 @@
 constexpr int MSG_RIGHT_MARGIN = 7;
 constexpr int MSG_PADDING      = 20;
 
+TextLabel::TextLabel(QWidget *parent)
+  : TextLabel(QString(), parent)
+{}
+
 TextLabel::TextLabel(const QString &text, QWidget *parent)
   : QTextBrowser(parent)
 {
+        document()->setDefaultStyleSheet(QString("a {color: %1; }").arg(utils::linkColor()));
+
         setText(text);
         setOpenExternalLinks(true);
 
@@ -722,6 +728,8 @@ void
 TimelineItem::generateTimestamp(const QDateTime &time)
 {
         QFont timestampFont;
+        timestampFont.setFamily("Monospace");
+        timestampFont.setStyleHint(QFont::Monospace);
         timestampFont.setPixelSize(conf::timeline::fonts::timestamp);
 
         timestamp_ = new QLabel(this);
diff --git a/src/timeline/TimelineItem.h b/src/timeline/TimelineItem.h
index b98dd148..e87864a5 100644
--- a/src/timeline/TimelineItem.h
+++ b/src/timeline/TimelineItem.h
@@ -102,8 +102,10 @@ class TextLabel : public QTextBrowser
 
 public:
         TextLabel(const QString &text, QWidget *parent = nullptr);
+        TextLabel(QWidget *parent = nullptr);
 
         void wheelEvent(QWheelEvent *event) override { event->ignore(); }
+        void clearLinks() { link_.clear(); }
 
 protected:
         void mousePressEvent(QMouseEvent *e) override;
diff --git a/src/ui/TextField.cpp b/src/ui/TextField.cpp
index 0c936e69..7e2f359a 100644
--- a/src/ui/TextField.cpp
+++ b/src/ui/TextField.cpp
@@ -13,21 +13,19 @@ TextField::TextField(QWidget *parent)
         // Get rid of the focus border on macOS.
         setAttribute(Qt::WA_MacShowFocusRect, 0);
 
+        QPalette pal;
+
         state_machine_    = new TextFieldStateMachine(this);
         label_            = 0;
         label_font_size_  = 15;
         show_label_       = false;
-        background_color_ = QColor("white");
+        background_color_ = pal.color(QPalette::Window);
 
         setFrame(false);
         setAttribute(Qt::WA_Hover);
         setMouseTracking(true);
         setTextMargins(0, 4, 0, 6);
 
-        QFont font("Open Sans");
-        font.setPixelSize(14);
-        setFont(font);
-
         state_machine_->start();
         QCoreApplication::processEvents();
 }
@@ -115,7 +113,7 @@ QColor
 TextField::textColor() const
 {
         if (!text_color_.isValid()) {
-                return QColor("black");
+                return QPalette().color(QPalette::Text);
         }
 
         return text_color_;
@@ -132,7 +130,7 @@ QColor
 TextField::labelColor() const
 {
         if (!label_color_.isValid()) {
-                return QColor("#abb"); // TODO: Move this into Theme.h
+                return QPalette().color(QPalette::Text);
         }
 
         return label_color_;
@@ -149,7 +147,7 @@ QColor
 TextField::inkColor() const
 {
         if (!ink_color_.isValid()) {
-                return QColor("black");
+                return QPalette().color(QPalette::Text);
         }
 
         return ink_color_;
@@ -166,7 +164,7 @@ QColor
 TextField::underlineColor() const
 {
         if (!underline_color_.isValid()) {
-                return QColor("black");
+                return QPalette().color(QPalette::Highlight);
         }
 
         return underline_color_;
@@ -340,8 +338,8 @@ TextFieldLabel::TextFieldLabel(TextField *parent)
         scale_ = 1;
         color_ = parent->labelColor();
 
-        QFont font("Open Sans SemiBold");
-        font.setPixelSize(parent->labelFontSize());
+        QFont font;
+        font.setWeight(60);
         font.setLetterSpacing(QFont::PercentageSpacing, 102);
         setFont(font);
 }