diff --git a/src/Cache.cpp b/src/Cache.cpp
index 1061e60e..009cbabc 100644
--- a/src/Cache.cpp
+++ b/src/Cache.cpp
@@ -31,6 +31,7 @@
#include "Cache.h"
#include "Cache_p.h"
+#include "EventAccessors.h"
#include "Logging.h"
#include "Utils.h"
@@ -1947,13 +1948,14 @@ Cache::saveTimelineMessages(lmdb::txn &txn,
json obj = json::object();
- obj["event"] = utils::serialize_event(e);
+ obj["event"] = mtx::accessors::serialize_event(e);
obj["token"] = res.prev_batch;
- lmdb::dbi_put(txn,
- db,
- lmdb::val(std::to_string(utils::event_timestamp(e))),
- lmdb::val(obj.dump()));
+ lmdb::dbi_put(
+ txn,
+ db,
+ lmdb::val(std::to_string(obj["event"]["origin_server_ts"].get<uint64_t>())),
+ lmdb::val(obj.dump()));
}
}
@@ -2026,7 +2028,7 @@ Cache::saveTimelineMentions(lmdb::txn &txn,
using namespace mtx::events::state;
for (const auto ¬if : res) {
- const auto event_id = utils::event_id(notif.event);
+ const auto event_id = mtx::accessors::event_id(notif.event);
// double check that we have the correct room_id...
if (room_id.compare(notif.room_id) != 0) {
diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index 1e06da5d..2340b146 100644
--- a/src/ChatPage.cpp
+++ b/src/ChatPage.cpp
@@ -26,6 +26,7 @@
#include "Cache.h"
#include "Cache_p.h"
#include "ChatPage.h"
+#include "EventAccessors.h"
#include "Logging.h"
#include "MainWindow.h"
#include "MatrixClient.h"
@@ -255,7 +256,7 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
text_input_, &TextInputWidget::startedTyping, this, &ChatPage::sendTypingNotifications);
connect(typingRefresher_, &QTimer::timeout, this, &ChatPage::sendTypingNotifications);
connect(text_input_, &TextInputWidget::stoppedTyping, this, [this]() {
- if (!userSettings_->isTypingNotificationsEnabled())
+ if (!userSettings_->typingNotifications())
return;
typingRefresher_->stop();
@@ -482,7 +483,7 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
activateWindow();
});
- setGroupViewState(userSettings_->isGroupViewEnabled());
+ setGroupViewState(userSettings_->groupView());
connect(userSettings_.data(),
&UserSettings::groupViewStateChanged,
@@ -891,7 +892,7 @@ void
ChatPage::sendDesktopNotifications(const mtx::responses::Notifications &res)
{
for (const auto &item : res.notifications) {
- const auto event_id = utils::event_id(item.event);
+ const auto event_id = mtx::accessors::event_id(item.event);
try {
if (item.read) {
@@ -901,7 +902,8 @@ ChatPage::sendDesktopNotifications(const mtx::responses::Notifications &res)
if (!cache::isNotificationSent(event_id)) {
const auto room_id = QString::fromStdString(item.room_id);
- const auto user_id = utils::event_sender(item.event);
+ const auto user_id =
+ QString::fromStdString(mtx::accessors::sender(item.event));
// We should only sent one notification per event.
cache::markSentNotification(event_id);
@@ -1213,7 +1215,7 @@ ChatPage::unbanUser(QString userid, QString reason)
void
ChatPage::sendTypingNotifications()
{
- if (!userSettings_->isTypingNotificationsEnabled())
+ if (!userSettings_->typingNotifications())
return;
http::client()->start_typing(
@@ -1349,7 +1351,7 @@ ChatPage::hideSideBars()
void
ChatPage::showSideBars()
{
- if (userSettings_->isGroupViewEnabled())
+ if (userSettings_->groupView())
communitiesList_->show();
sideBar_->show();
diff --git a/src/CommunitiesListItem.h b/src/CommunitiesListItem.h
index 0cc5d60c..535a6ec0 100644
--- a/src/CommunitiesListItem.h
+++ b/src/CommunitiesListItem.h
@@ -7,7 +7,6 @@
#include "ui/Theme.h"
class RippleOverlay;
-class QPainter;
class QMouseEvent;
class CommunitiesListItem : public QWidget
diff --git a/src/EventAccessors.cpp b/src/EventAccessors.cpp
index 7f28eb46..a2d8adbb 100644
--- a/src/EventAccessors.cpp
+++ b/src/EventAccessors.cpp
@@ -400,3 +400,9 @@ mtx::accessors::media_width(const mtx::events::collections::TimelineEvents &even
{
return std::visit(EventMediaWidth{}, event);
}
+
+nlohmann::json
+mtx::accessors::serialize_event(const mtx::events::collections::TimelineEvents &event)
+{
+ return std::visit([](const auto &e) { return nlohmann::json(e); }, event);
+}
diff --git a/src/EventAccessors.h b/src/EventAccessors.h
index c9ac4d00..a7577d86 100644
--- a/src/EventAccessors.h
+++ b/src/EventAccessors.h
@@ -63,4 +63,7 @@ media_height(const mtx::events::collections::TimelineEvents &event);
uint64_t
media_width(const mtx::events::collections::TimelineEvents &event);
+
+nlohmann::json
+serialize_event(const mtx::events::collections::TimelineEvents &event);
}
diff --git a/src/InviteeItem.cpp b/src/InviteeItem.cpp
index 906a3bfe..a6b471dc 100644
--- a/src/InviteeItem.cpp
+++ b/src/InviteeItem.cpp
@@ -1,4 +1,5 @@
#include <QHBoxLayout>
+#include <QLabel>
#include <QPushButton>
#include "InviteeItem.h"
diff --git a/src/InviteeItem.h b/src/InviteeItem.h
index 582904b4..54c61938 100644
--- a/src/InviteeItem.h
+++ b/src/InviteeItem.h
@@ -1,11 +1,11 @@
#pragma once
-#include <QLabel>
#include <QWidget>
#include <mtx/identifiers.hpp>
class QPushButton;
+class QLabel;
class InviteeItem : public QWidget
{
diff --git a/src/LoginPage.cpp b/src/LoginPage.cpp
index bb329699..9a920d1d 100644
--- a/src/LoginPage.cpp
+++ b/src/LoginPage.cpp
@@ -16,6 +16,7 @@
*/
#include <QDesktopServices>
+#include <QLabel>
#include <QPainter>
#include <QStyleOption>
@@ -118,7 +119,7 @@ LoginPage::LoginPage(QWidget *parent)
deviceName_->setLabel(tr("Device name"));
deviceName_->setToolTip(
tr("A name for this device, which will be shown to others, when verifying your devices. "
- "If none is provided, a random string is used for privacy purposes."));
+ "If none is provided a default is used."));
serverInput_ = new TextField(this);
serverInput_->setLabel("Homeserver address");
@@ -132,7 +133,7 @@ LoginPage::LoginPage(QWidget *parent)
form_layout_->addLayout(matrixidLayout_);
form_layout_->addWidget(password_input_);
- form_layout_->addWidget(deviceName_, Qt::AlignHCenter, nullptr);
+ form_layout_->addWidget(deviceName_, Qt::AlignHCenter);
form_layout_->addLayout(serverLayout_);
button_layout_ = new QHBoxLayout();
@@ -180,6 +181,12 @@ LoginPage::LoginPage(QWidget *parent)
}
void
+LoginPage::loginError(const QString &msg)
+{
+ error_label_->setText(msg);
+}
+
+void
LoginPage::onMatrixIdEntered()
{
error_label_->setText("");
diff --git a/src/LoginPage.h b/src/LoginPage.h
index 8a402aea..c9220297 100644
--- a/src/LoginPage.h
+++ b/src/LoginPage.h
@@ -17,8 +17,6 @@
#pragma once
-#include <QLabel>
-#include <QLayout>
#include <QWidget>
class FlatButton;
@@ -26,6 +24,9 @@ class LoadingIndicator;
class OverlayModal;
class RaisedButton;
class TextField;
+class QLabel;
+class QVBoxLayout;
+class QHBoxLayout;
namespace mtx {
namespace responses {
@@ -65,7 +66,7 @@ protected:
public slots:
// Displays errors produced during the login.
- void loginError(const QString &msg) { error_label_->setText(msg); }
+ void loginError(const QString &msg);
private slots:
// Callback for the back button.
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index c6abdca2..cc1d868b 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -148,7 +148,7 @@ MainWindow::MainWindow(QWidget *parent)
QSettings settings;
- trayIcon_->setVisible(userSettings_->isTrayEnabled());
+ trayIcon_->setVisible(userSettings_->tray());
if (hasActiveUser()) {
QString token = settings.value("auth/access_token").toString();
@@ -286,7 +286,7 @@ void
MainWindow::closeEvent(QCloseEvent *event)
{
if (!qApp->isSavingSession() && isVisible() && pageSupportsTray() &&
- userSettings_->isTrayEnabled()) {
+ userSettings_->tray()) {
event->ignore();
hide();
}
diff --git a/src/MxcImageProvider.cpp b/src/MxcImageProvider.cpp
index 8e67375d..a197e4aa 100644
--- a/src/MxcImageProvider.cpp
+++ b/src/MxcImageProvider.cpp
@@ -17,7 +17,8 @@ MxcImageResponse::run()
auto data = cache::image(fileName);
if (!data.isNull()) {
m_image = utils::readImage(&data);
- m_image = m_image.scaled(m_requestedSize, Qt::KeepAspectRatio);
+ m_image = m_image.scaled(
+ m_requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
m_image.setText("mxc url", "mxc://" + m_id);
if (!m_image.isNull()) {
diff --git a/src/RegisterPage.cpp b/src/RegisterPage.cpp
index 03e9ab34..b8fe93b5 100644
--- a/src/RegisterPage.cpp
+++ b/src/RegisterPage.cpp
@@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <QLabel>
#include <QMetaType>
#include <QPainter>
#include <QStyleOption>
@@ -106,10 +107,10 @@ RegisterPage::RegisterPage(QWidget *parent)
tr("A server that allows registration. Since matrix is decentralized, you need to first "
"find a server you can register on or host your own."));
- form_layout_->addWidget(username_input_, Qt::AlignHCenter, nullptr);
- form_layout_->addWidget(password_input_, Qt::AlignHCenter, nullptr);
- form_layout_->addWidget(password_confirmation_, Qt::AlignHCenter, nullptr);
- form_layout_->addWidget(server_input_, Qt::AlignHCenter, nullptr);
+ form_layout_->addWidget(username_input_, Qt::AlignHCenter);
+ form_layout_->addWidget(password_input_, Qt::AlignHCenter);
+ form_layout_->addWidget(password_confirmation_, Qt::AlignHCenter);
+ form_layout_->addWidget(server_input_, Qt::AlignHCenter);
button_layout_ = new QHBoxLayout();
button_layout_->setSpacing(0);
diff --git a/src/RegisterPage.h b/src/RegisterPage.h
index ebc24bb1..59ba3d1d 100644
--- a/src/RegisterPage.h
+++ b/src/RegisterPage.h
@@ -17,8 +17,8 @@
#pragma once
-#include <QLabel>
-#include <QLayout>
+#include <QWidget>
+
#include <memory>
#include <mtx/user_interactive.hpp>
@@ -26,6 +26,9 @@
class FlatButton;
class RaisedButton;
class TextField;
+class QLabel;
+class QVBoxLayout;
+class QHBoxLayout;
class RegisterPage : public QWidget
{
diff --git a/src/RoomInfoListItem.cpp b/src/RoomInfoListItem.cpp
index ad774360..f234b59b 100644
--- a/src/RoomInfoListItem.cpp
+++ b/src/RoomInfoListItem.cpp
@@ -451,7 +451,7 @@ RoomInfoListItem::calculateImportance() const
// returns ImportanceDisabled or Invite
if (isInvite()) {
return Invite;
- } else if (!settings->isSortByImportanceEnabled()) {
+ } else if (!settings->sortByImportance()) {
return ImportanceDisabled;
} else if (unreadHighlightedMsgCount_) {
return NewMentions;
diff --git a/src/RoomList.cpp b/src/RoomList.cpp
index 85a22026..b4c507b5 100644
--- a/src/RoomList.cpp
+++ b/src/RoomList.cpp
@@ -21,6 +21,8 @@
#include <QObject>
#include <QPainter>
#include <QScroller>
+#include <QStyle>
+#include <QStyleOption>
#include <QTimer>
#include "Logging.h"
diff --git a/src/SideBarActions.cpp b/src/SideBarActions.cpp
index 4934ec05..5af01cc2 100644
--- a/src/SideBarActions.cpp
+++ b/src/SideBarActions.cpp
@@ -1,6 +1,8 @@
#include <QIcon>
#include <QPainter>
#include <QResizeEvent>
+#include <QStyle>
+#include <QStyleOption>
#include <mtx/requests.hpp>
diff --git a/src/TopRoomBar.h b/src/TopRoomBar.h
index 1aa5934b..0c33c1e0 100644
--- a/src/TopRoomBar.h
+++ b/src/TopRoomBar.h
@@ -27,7 +27,6 @@ class Menu;
class TextLabel;
class OverlayModal;
-class QPainter;
class QLabel;
class QHBoxLayout;
class QVBoxLayout;
diff --git a/src/UserInfoWidget.cpp b/src/UserInfoWidget.cpp
index 2e21d41f..e11aa6aa 100644
--- a/src/UserInfoWidget.cpp
+++ b/src/UserInfoWidget.cpp
@@ -16,7 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <QLabel>
#include <QPainter>
+#include <QStyle>
+#include <QStyleOption>
#include <QTimer>
#include <iostream>
diff --git a/src/UserInfoWidget.h b/src/UserInfoWidget.h
index e1a925a4..575ade52 100644
--- a/src/UserInfoWidget.h
+++ b/src/UserInfoWidget.h
@@ -17,13 +17,16 @@
#pragma once
-#include <QLabel>
-#include <QLayout>
+#include <QWidget>
class Avatar;
class FlatButton;
class OverlayModal;
+class QLabel;
+class QHBoxLayout;
+class QVBoxLayout;
+
class UserInfoWidget : public QWidget
{
Q_OBJECT
diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp
index 6af08e12..dfd99069 100644
--- a/src/UserSettingsPage.cpp
+++ b/src/UserSettingsPage.cpp
@@ -30,6 +30,7 @@
#include <QScrollArea>
#include <QScroller>
#include <QSettings>
+#include <QSpinBox>
#include <QStandardPaths>
#include <QString>
#include <QTextStream>
@@ -51,54 +52,206 @@ void
UserSettings::load()
{
QSettings settings;
- isTrayEnabled_ = settings.value("user/window/tray", false).toBool();
- hasDesktopNotifications_ = settings.value("user/desktop_notifications", true).toBool();
- isStartInTrayEnabled_ = settings.value("user/window/start_in_tray", false).toBool();
- isGroupViewEnabled_ = settings.value("user/group_view", true).toBool();
- isButtonsInTimelineEnabled_ = settings.value("user/timeline/buttons", true).toBool();
- isMessageHoverHighlightEnabled_ =
+ tray_ = settings.value("user/window/tray", false).toBool();
+ hasDesktopNotifications_ = settings.value("user/desktop_notifications", true).toBool();
+ startInTray_ = settings.value("user/window/start_in_tray", false).toBool();
+ groupView_ = settings.value("user/group_view", true).toBool();
+ buttonsInTimeline_ = settings.value("user/timeline/buttons", true).toBool();
+ timelineMaxWidth_ = settings.value("user/timeline/max_width", 0).toInt();
+ messageHoverHighlight_ =
settings.value("user/timeline/message_hover_highlight", false).toBool();
- isMarkdownEnabled_ = settings.value("user/markdown_enabled", true).toBool();
- isTypingNotificationsEnabled_ = settings.value("user/typing_notifications", true).toBool();
- sortByImportance_ = settings.value("user/sort_by_unread", true).toBool();
- isReadReceiptsEnabled_ = settings.value("user/read_receipts", true).toBool();
- theme_ = settings.value("user/theme", defaultTheme_).toString();
- font_ = settings.value("user/font_family", "default").toString();
- avatarCircles_ = settings.value("user/avatar_circles", true).toBool();
- decryptSidebar_ = settings.value("user/decrypt_sidebar", true).toBool();
- emojiFont_ = settings.value("user/emoji_font_family", "default").toString();
- baseFontSize_ = settings.value("user/font_size", QFont().pointSizeF()).toDouble();
+ enlargeEmojiOnlyMessages_ =
+ settings.value("user/timeline/enlarge_emoji_only_msg", false).toBool();
+ markdown_ = settings.value("user/markdown_enabled", true).toBool();
+ typingNotifications_ = settings.value("user/typing_notifications", true).toBool();
+ sortByImportance_ = settings.value("user/sort_by_unread", true).toBool();
+ readReceipts_ = settings.value("user/read_receipts", true).toBool();
+ theme_ = settings.value("user/theme", defaultTheme_).toString();
+ font_ = settings.value("user/font_family", "default").toString();
+ avatarCircles_ = settings.value("user/avatar_circles", true).toBool();
+ decryptSidebar_ = settings.value("user/decrypt_sidebar", true).toBool();
+ emojiFont_ = settings.value("user/emoji_font_family", "default").toString();
+ baseFontSize_ = settings.value("user/font_size", QFont().pointSizeF()).toDouble();
applyTheme();
}
+void
+UserSettings::setMessageHoverHighlight(bool state)
+{
+ if (state == messageHoverHighlight_)
+ return;
+ messageHoverHighlight_ = state;
+ emit messageHoverHighlightChanged(state);
+ save();
+}
+void
+UserSettings::setEnlargeEmojiOnlyMessages(bool state)
+{
+ if (state == enlargeEmojiOnlyMessages_)
+ return;
+ enlargeEmojiOnlyMessages_ = state;
+ emit enlargeEmojiOnlyMessagesChanged(state);
+ save();
+}
+void
+UserSettings::setTray(bool state)
+{
+ if (state == tray_)
+ return;
+ tray_ = state;
+ emit trayChanged(state);
+ save();
+}
+
+void
+UserSettings::setStartInTray(bool state)
+{
+ if (state == startInTray_)
+ return;
+ startInTray_ = state;
+ emit startInTrayChanged(state);
+ save();
+}
+
+void
+UserSettings::setGroupView(bool state)
+{
+ if (groupView_ != state)
+ emit groupViewStateChanged(state);
+
+ groupView_ = state;
+ save();
+}
+
+void
+UserSettings::setMarkdown(bool state)
+{
+ if (state == markdown_)
+ return;
+ markdown_ = state;
+ emit markdownChanged(state);
+ save();
+}
+
+void
+UserSettings::setReadReceipts(bool state)
+{
+ if (state == readReceipts_)
+ return;
+ readReceipts_ = state;
+ emit readReceiptsChanged(state);
+ save();
+}
+
+void
+UserSettings::setTypingNotifications(bool state)
+{
+ if (state == typingNotifications_)
+ return;
+ typingNotifications_ = state;
+ emit typingNotificationsChanged(state);
+ save();
+}
+
+void
+UserSettings::setSortByImportance(bool state)
+{
+ if (state == sortByImportance_)
+ return;
+ sortByImportance_ = state;
+ emit roomSortingChanged(state);
+ save();
+}
+
+void
+UserSettings::setButtonsInTimeline(bool state)
+{
+ if (state == buttonsInTimeline_)
+ return;
+ buttonsInTimeline_ = state;
+ emit buttonInTimelineChanged(state);
+ save();
+}
+
+void
+UserSettings::setTimelineMaxWidth(int state)
+{
+ if (state == timelineMaxWidth_)
+ return;
+ timelineMaxWidth_ = state;
+ emit timelineMaxWidthChanged(state);
+ save();
+}
+
+void
+UserSettings::setDesktopNotifications(bool state)
+{
+ if (state == hasDesktopNotifications_)
+ return;
+ hasDesktopNotifications_ = state;
+ emit desktopNotificationsChanged(state);
+ save();
+}
+
+void
+UserSettings::setAvatarCircles(bool state)
+{
+ if (state == avatarCircles_)
+ return;
+ avatarCircles_ = state;
+ emit avatarCirclesChanged(state);
+ save();
+}
+
+void
+UserSettings::setDecryptSidebar(bool state)
+{
+ if (state == decryptSidebar_)
+ return;
+ decryptSidebar_ = state;
+ emit decryptSidebarChanged(state);
+ save();
+}
void
UserSettings::setFontSize(double size)
{
+ if (size == baseFontSize_)
+ return;
baseFontSize_ = size;
+ emit fontSizeChanged(size);
save();
}
void
UserSettings::setFontFamily(QString family)
{
+ if (family == font_)
+ return;
font_ = family;
+ emit fontChanged(family);
save();
}
void
UserSettings::setEmojiFontFamily(QString family)
{
+ if (family == emojiFont_)
+ return;
emojiFont_ = family;
+ emit emojiFontChanged(family);
save();
}
void
UserSettings::setTheme(QString theme)
{
+ if (theme == theme)
+ return;
theme_ = theme;
save();
applyTheme();
+ emit themeChanged(theme);
}
void
@@ -161,29 +314,33 @@ UserSettings::save()
settings.beginGroup("user");
settings.beginGroup("window");
- settings.setValue("tray", isTrayEnabled_);
- settings.setValue("start_in_tray", isStartInTrayEnabled_);
+ settings.setValue("tray", tray_);
+ settings.setValue("start_in_tray", startInTray_);
settings.endGroup();
settings.beginGroup("timeline");
- settings.setValue("buttons", isButtonsInTimelineEnabled_);
- settings.setValue("message_hover_highlight", isMessageHoverHighlightEnabled_);
+ settings.setValue("buttons", buttonsInTimeline_);
+ settings.setValue("message_hover_highlight", messageHoverHighlight_);
+ settings.setValue("enlarge_emoji_only_msg", enlargeEmojiOnlyMessages_);
+ settings.setValue("max_width", timelineMaxWidth_);
settings.endGroup();
settings.setValue("avatar_circles", avatarCircles_);
settings.setValue("decrypt_sidebar", decryptSidebar_);
settings.setValue("font_size", baseFontSize_);
- settings.setValue("typing_notifications", isTypingNotificationsEnabled_);
+ settings.setValue("typing_notifications", typingNotifications_);
settings.setValue("minor_events", sortByImportance_);
- settings.setValue("read_receipts", isReadReceiptsEnabled_);
- settings.setValue("group_view", isGroupViewEnabled_);
- settings.setValue("markdown_enabled", isMarkdownEnabled_);
+ settings.setValue("read_receipts", readReceipts_);
+ settings.setValue("group_view", groupView_);
+ settings.setValue("markdown_enabled", markdown_);
settings.setValue("desktop_notifications", hasDesktopNotifications_);
settings.setValue("theme", theme());
settings.setValue("font_family", font_);
settings.setValue("emoji_font_family", emojiFont_);
settings.endGroup();
+
+ settings.sync();
}
HorizontalLine::HorizontalLine(QWidget *parent)
@@ -231,24 +388,26 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
general_->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
general_->setFont(font);
- trayToggle_ = new Toggle{this};
- startInTrayToggle_ = new Toggle{this};
- avatarCircles_ = new Toggle{this};
- decryptSidebar_ = new Toggle(this);
- groupViewToggle_ = new Toggle{this};
- timelineButtonsToggle_ = new Toggle{this};
- typingNotifications_ = new Toggle{this};
- messageHoverHighlight_ = new Toggle{this};
- sortByImportance_ = new Toggle{this};
- readReceipts_ = new Toggle{this};
- markdownEnabled_ = new Toggle{this};
- desktopNotifications_ = new Toggle{this};
- scaleFactorCombo_ = new QComboBox{this};
- fontSizeCombo_ = new QComboBox{this};
- fontSelectionCombo_ = new QComboBox{this};
- emojiFontSelectionCombo_ = new QComboBox{this};
+ trayToggle_ = new Toggle{this};
+ startInTrayToggle_ = new Toggle{this};
+ avatarCircles_ = new Toggle{this};
+ decryptSidebar_ = new Toggle(this);
+ groupViewToggle_ = new Toggle{this};
+ timelineButtonsToggle_ = new Toggle{this};
+ typingNotifications_ = new Toggle{this};
+ messageHoverHighlight_ = new Toggle{this};
+ enlargeEmojiOnlyMessages_ = new Toggle{this};
+ sortByImportance_ = new Toggle{this};
+ readReceipts_ = new Toggle{this};
+ markdown_ = new Toggle{this};
+ desktopNotifications_ = new Toggle{this};
+ scaleFactorCombo_ = new QComboBox{this};
+ fontSizeCombo_ = new QComboBox{this};
+ fontSelectionCombo_ = new QComboBox{this};
+ emojiFontSelectionCombo_ = new QComboBox{this};
+ timelineMaxWidthSpin_ = new QSpinBox{this};
- if (!settings_->isTrayEnabled())
+ if (!settings_->tray())
startInTrayToggle_->setDisabled(true);
avatarCircles_->setFixedSize(64, 48);
@@ -291,6 +450,10 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
int themeIndex = themeCombo_->findText(themeStr);
themeCombo_->setCurrentIndex(themeIndex);
+ timelineMaxWidthSpin_->setMinimum(0);
+ timelineMaxWidthSpin_->setMaximum(100'000'000);
+ timelineMaxWidthSpin_->setSingleStep(10);
+
auto encryptionLabel_ = new QLabel{tr("ENCRYPTION"), this};
encryptionLabel_->setFixedHeight(encryptionLabel_->minimumHeight() + LayoutTopMargin);
encryptionLabel_->setAlignment(Qt::AlignBottom);
@@ -323,11 +486,15 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
sessionKeysLayout->addWidget(sessionKeysExportBtn, 0, Qt::AlignRight);
sessionKeysLayout->addWidget(sessionKeysImportBtn, 0, Qt::AlignRight);
- auto boxWrap = [this, &font](QString labelText, QWidget *field) {
+ auto boxWrap = [this, &font](QString labelText, QWidget *field, QString tooltipText = "") {
auto label = new QLabel{labelText, this};
label->setFont(font);
label->setMargin(OptionMargin);
+ if (!tooltipText.isEmpty()) {
+ label->setToolTip(tooltipText);
+ }
+
auto layout = new QHBoxLayout;
layout->addWidget(field, 0, Qt::AlignRight);
@@ -336,25 +503,70 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
formLayout_->addRow(general_);
formLayout_->addRow(new HorizontalLine{this});
- boxWrap(tr("Minimize to tray"), trayToggle_);
- boxWrap(tr("Start in tray"), startInTrayToggle_);
+ boxWrap(
+ tr("Minimize to tray"),
+ trayToggle_,
+ tr("Keep the application running in the background after closing the client window."));
+ boxWrap(tr("Start in tray"),
+ startInTrayToggle_,
+ tr("Start the application in the background without showing the client window."));
formLayout_->addRow(new HorizontalLine{this});
- boxWrap(tr("Circular Avatars"), avatarCircles_);
- boxWrap(tr("Group's sidebar"), groupViewToggle_);
- boxWrap(tr("Decrypt messages in sidebar"), decryptSidebar_);
- boxWrap(tr("Show buttons in timeline"), timelineButtonsToggle_);
- boxWrap(tr("Typing notifications"), typingNotifications_);
- boxWrap(tr("Sort rooms by unreads"), sortByImportance_);
+ boxWrap(tr("Circular Avatars"),
+ avatarCircles_,
+ tr("Change the appearance of user avatars in chats.\nOFF - square, ON - Circle."));
+ boxWrap(tr("Group's sidebar"),
+ groupViewToggle_,
+ tr("Show a column containing groups and tags next to the room list."));
+ boxWrap(tr("Decrypt messages in sidebar"),
+ decryptSidebar_,
+ tr("Decrypt the messages shown in the sidebar.\nOnly affects messages in "
+ "encrypted chats."));
+ boxWrap(tr("Show buttons in timeline"),
+ timelineButtonsToggle_,
+ tr("Show buttons to quickly reply, react or access additional options next to each "
+ "message."));
+ boxWrap(tr("Limit width of timeline"),
+ timelineMaxWidthSpin_,
+ tr("Set the max width of messages in the timeline (in pixels). This can help "
+ "readability on wide screen, when Nheko is maximised"));
+ boxWrap(tr("Typing notifications"),
+ typingNotifications_,
+ tr("Show who is typing in a room.\nThis will also enable or disable sending typing "
+ "notifications to others."));
+ boxWrap(
+ tr("Sort rooms by unreads"),
+ sortByImportance_,
+ tr(
+ "Display rooms with new messages first.\nIf this is off, the list of rooms will only "
+ "be sorted by the timestamp of the last message in a room.\nIf this is on, rooms which "
+ "have active notifications (the small circle with a number in it) will be sorted on "
+ "top. Rooms, that you have muted, will still be sorted by timestamp, since you don't "
+ "seem to consider them as important as the other rooms."));
formLayout_->addRow(new HorizontalLine{this});
- boxWrap(tr("Read receipts"), readReceipts_);
- boxWrap(tr("Send messages as Markdown"), markdownEnabled_);
- boxWrap(tr("Desktop notifications"), desktopNotifications_);
- boxWrap(tr("Highlight message on hover"), messageHoverHighlight_);
+ boxWrap(tr("Read receipts"),
+ readReceipts_,
+ tr("Show if your message was read.\nStatus is displayed next to timestamps."));
+ boxWrap(
+ tr("Send messages as Markdown"),
+ markdown_,
+ tr("Allow using markdown in messages.\nWhen disabled, all messages are sent as a plain "
+ "text."));
+ boxWrap(tr("Desktop notifications"),
+ desktopNotifications_,
+ tr("Notify about received message when the client is not currently focused."));
+ boxWrap(tr("Highlight message on hover"),
+ messageHoverHighlight_,
+ tr("Change the background color of messages when you hover over them."));
+ boxWrap(tr("Large Emoji in timeline"),
+ enlargeEmojiOnlyMessages_,
+ tr("Make font size larger if messages with only a few emojis are displayed."));
formLayout_->addRow(uiLabel_);
formLayout_->addRow(new HorizontalLine{this});
#if !defined(Q_OS_MAC)
- boxWrap(tr("Scale factor"), scaleFactorCombo_);
+ boxWrap(tr("Scale factor"),
+ scaleFactorCombo_,
+ tr("Change the scale factor of the whole user interface."));
#else
scaleFactorCombo_->hide();
#endif
@@ -400,78 +612,87 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
topLayout_->addWidget(versionInfo);
connect(themeCombo_,
- static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::activated),
+ static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
[this](const QString &text) {
settings_->setTheme(text.toLower());
emit themeChanged();
});
connect(scaleFactorCombo_,
- static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::activated),
+ static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
[](const QString &factor) { utils::setScaleFactor(factor.toFloat()); });
connect(fontSizeCombo_,
- static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::activated),
+ static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
[this](const QString &size) { settings_->setFontSize(size.trimmed().toDouble()); });
connect(fontSelectionCombo_,
- static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::activated),
+ static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
[this](const QString &family) { settings_->setFontFamily(family.trimmed()); });
connect(emojiFontSelectionCombo_,
- static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::activated),
+ static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
[this](const QString &family) { settings_->setEmojiFontFamily(family.trimmed()); });
- connect(trayToggle_, &Toggle::toggled, this, [this](bool isDisabled) {
- settings_->setTray(!isDisabled);
- if (isDisabled) {
+ connect(trayToggle_, &Toggle::toggled, this, [this](bool disabled) {
+ settings_->setTray(!disabled);
+ if (disabled) {
startInTrayToggle_->setDisabled(true);
} else {
startInTrayToggle_->setEnabled(true);
}
- emit trayOptionChanged(!isDisabled);
+ emit trayOptionChanged(!disabled);
});
- connect(startInTrayToggle_, &Toggle::toggled, this, [this](bool isDisabled) {
- settings_->setStartInTray(!isDisabled);
+ connect(startInTrayToggle_, &Toggle::toggled, this, [this](bool disabled) {
+ settings_->setStartInTray(!disabled);
});
- connect(groupViewToggle_, &Toggle::toggled, this, [this](bool isDisabled) {
- settings_->setGroupView(!isDisabled);
+ connect(groupViewToggle_, &Toggle::toggled, this, [this](bool disabled) {
+ settings_->setGroupView(!disabled);
});
- connect(decryptSidebar_, &Toggle::toggled, this, [this](bool isDisabled) {
- settings_->setDecryptSidebar(!isDisabled);
+ connect(decryptSidebar_, &Toggle::toggled, this, [this](bool disabled) {
+ settings_->setDecryptSidebar(!disabled);
emit decryptSidebarChanged();
});
- connect(avatarCircles_, &Toggle::toggled, this, [this](bool isDisabled) {
- settings_->setAvatarCircles(!isDisabled);
+ connect(avatarCircles_, &Toggle::toggled, this, [this](bool disabled) {
+ settings_->setAvatarCircles(!disabled);
});
- connect(markdownEnabled_, &Toggle::toggled, this, [this](bool isDisabled) {
- settings_->setMarkdownEnabled(!isDisabled);
+ connect(markdown_, &Toggle::toggled, this, [this](bool disabled) {
+ settings_->setMarkdown(!disabled);
});
- connect(typingNotifications_, &Toggle::toggled, this, [this](bool isDisabled) {
- settings_->setTypingNotifications(!isDisabled);
+ connect(typingNotifications_, &Toggle::toggled, this, [this](bool disabled) {
+ settings_->setTypingNotifications(!disabled);
});
- connect(sortByImportance_, &Toggle::toggled, this, [this](bool isDisabled) {
- settings_->setSortByImportance(!isDisabled);
+ connect(sortByImportance_, &Toggle::toggled, this, [this](bool disabled) {
+ settings_->setSortByImportance(!disabled);
});
- connect(timelineButtonsToggle_, &Toggle::toggled, this, [this](bool isDisabled) {
- settings_->setButtonsInTimeline(!isDisabled);
+ connect(timelineButtonsToggle_, &Toggle::toggled, this, [this](bool disabled) {
+ settings_->setButtonsInTimeline(!disabled);
});
- connect(readReceipts_, &Toggle::toggled, this, [this](bool isDisabled) {
- settings_->setReadReceipts(!isDisabled);
+ connect(readReceipts_, &Toggle::toggled, this, [this](bool disabled) {
+ settings_->setReadReceipts(!disabled);
});
- connect(desktopNotifications_, &Toggle::toggled, this, [this](bool isDisabled) {
- settings_->setDesktopNotifications(!isDisabled);
+ connect(desktopNotifications_, &Toggle::toggled, this, [this](bool disabled) {
+ settings_->setDesktopNotifications(!disabled);
});
- connect(messageHoverHighlight_, &Toggle::toggled, this, [this](bool isDisabled) {
- settings_->setMessageHoverHighlight(!isDisabled);
+ connect(messageHoverHighlight_, &Toggle::toggled, this, [this](bool disabled) {
+ settings_->setMessageHoverHighlight(!disabled);
});
+ connect(enlargeEmojiOnlyMessages_, &Toggle::toggled, this, [this](bool disabled) {
+ settings_->setEnlargeEmojiOnlyMessages(!disabled);
+ });
+
+ connect(timelineMaxWidthSpin_,
+ qOverload<int>(&QSpinBox::valueChanged),
+ this,
+ [this](int newValue) { settings_->setTimelineMaxWidth(newValue); });
+
connect(
sessionKeysImportBtn, &QPushButton::clicked, this, &UserSettingsPage::importSessionKeys);
@@ -493,19 +714,21 @@ UserSettingsPage::showEvent(QShowEvent *)
utils::restoreCombobox(themeCombo_, settings_->theme());
// FIXME: Toggle treats true as "off"
- trayToggle_->setState(!settings_->isTrayEnabled());
- startInTrayToggle_->setState(!settings_->isStartInTrayEnabled());
- groupViewToggle_->setState(!settings_->isGroupViewEnabled());
- decryptSidebar_->setState(!settings_->isDecryptSidebarEnabled());
- avatarCircles_->setState(!settings_->isAvatarCirclesEnabled());
- typingNotifications_->setState(!settings_->isTypingNotificationsEnabled());
- sortByImportance_->setState(!settings_->isSortByImportanceEnabled());
- timelineButtonsToggle_->setState(!settings_->isButtonsInTimelineEnabled());
- readReceipts_->setState(!settings_->isReadReceiptsEnabled());
- markdownEnabled_->setState(!settings_->isMarkdownEnabled());
+ trayToggle_->setState(!settings_->tray());
+ startInTrayToggle_->setState(!settings_->startInTray());
+ groupViewToggle_->setState(!settings_->groupView());
+ decryptSidebar_->setState(!settings_->decryptSidebar());
+ avatarCircles_->setState(!settings_->avatarCircles());
+ typingNotifications_->setState(!settings_->typingNotifications());
+ sortByImportance_->setState(!settings_->sortByImportance());
+ timelineButtonsToggle_->setState(!settings_->buttonsInTimeline());
+ readReceipts_->setState(!settings_->readReceipts());
+ markdown_->setState(!settings_->markdown());
desktopNotifications_->setState(!settings_->hasDesktopNotifications());
- messageHoverHighlight_->setState(!settings_->isMessageHoverHighlightEnabled());
+ messageHoverHighlight_->setState(!settings_->messageHoverHighlight());
+ enlargeEmojiOnlyMessages_->setState(!settings_->enlargeEmojiOnlyMessages());
deviceIdValue_->setText(QString::fromStdString(http::client()->device_id()));
+ timelineMaxWidthSpin_->setValue(settings_->timelineMaxWidth());
deviceFingerprintValue_->setText(
utils::humanReadableFingerprint(olm::client()->identity_keys().ed25519));
diff --git a/src/UserSettingsPage.h b/src/UserSettingsPage.h
index 088bbfb5..fb807067 100644
--- a/src/UserSettingsPage.h
+++ b/src/UserSettingsPage.h
@@ -17,17 +17,19 @@
#pragma once
-#include <QComboBox>
#include <QFontDatabase>
-#include <QFormLayout>
#include <QFrame>
-#include <QLabel>
-#include <QLayout>
#include <QProcessEnvironment>
#include <QSharedPointer>
#include <QWidget>
class Toggle;
+class QLabel;
+class QFormLayout;
+class QComboBox;
+class QSpinBox;
+class QHBoxLayout;
+class QVBoxLayout;
constexpr int OptionMargin = 6;
constexpr int LayoutTopMargin = 50;
@@ -37,6 +39,36 @@ class UserSettings : public QObject
{
Q_OBJECT
+ Q_PROPERTY(QString theme READ theme WRITE setTheme NOTIFY themeChanged)
+ Q_PROPERTY(bool messageHoverHighlight READ messageHoverHighlight WRITE
+ setMessageHoverHighlight NOTIFY messageHoverHighlightChanged)
+ Q_PROPERTY(bool enlargeEmojiOnlyMessages READ enlargeEmojiOnlyMessages WRITE
+ setEnlargeEmojiOnlyMessages NOTIFY enlargeEmojiOnlyMessagesChanged)
+ Q_PROPERTY(bool tray READ tray WRITE setTray NOTIFY trayChanged)
+ Q_PROPERTY(bool startInTray READ startInTray WRITE setStartInTray NOTIFY startInTrayChanged)
+ Q_PROPERTY(bool groupView READ groupView WRITE setGroupView NOTIFY groupViewStateChanged)
+ Q_PROPERTY(bool markdown READ markdown WRITE setMarkdown NOTIFY markdownChanged)
+ Q_PROPERTY(bool typingNotifications READ typingNotifications WRITE setTypingNotifications
+ NOTIFY typingNotificationsChanged)
+ Q_PROPERTY(bool sortByImportance READ sortByImportance WRITE setSortByImportance NOTIFY
+ roomSortingChanged)
+ Q_PROPERTY(bool buttonsInTimeline READ buttonsInTimeline WRITE setButtonsInTimeline NOTIFY
+ buttonInTimelineChanged)
+ Q_PROPERTY(
+ bool readReceipts READ readReceipts WRITE setReadReceipts NOTIFY readReceiptsChanged)
+ Q_PROPERTY(bool desktopNotifications READ hasDesktopNotifications WRITE
+ setDesktopNotifications NOTIFY desktopNotificationsChanged)
+ Q_PROPERTY(
+ bool avatarCircles READ avatarCircles WRITE setAvatarCircles NOTIFY avatarCirclesChanged)
+ Q_PROPERTY(bool decryptSidebar READ decryptSidebar WRITE setDecryptSidebar NOTIFY
+ decryptSidebarChanged)
+ Q_PROPERTY(int timelineMaxWidth READ timelineMaxWidth WRITE setTimelineMaxWidth NOTIFY
+ timelineMaxWidthChanged)
+ Q_PROPERTY(double fontSize READ fontSize WRITE setFontSize NOTIFY fontSizeChanged)
+ Q_PROPERTY(QString font READ font WRITE setFontFamily NOTIFY fontChanged)
+ Q_PROPERTY(
+ QString emojiFont READ emojiFont WRITE setEmojiFontFamily NOTIFY emojiFontChanged)
+
public:
UserSettings();
@@ -44,104 +76,62 @@ public:
void load();
void applyTheme();
void setTheme(QString theme);
- void setMessageHoverHighlight(bool state)
- {
- isMessageHoverHighlightEnabled_ = state;
- save();
- }
- void setTray(bool state)
- {
- isTrayEnabled_ = state;
- save();
- }
-
- void setStartInTray(bool state)
- {
- isStartInTrayEnabled_ = state;
- save();
- }
-
+ void setMessageHoverHighlight(bool state);
+ void setEnlargeEmojiOnlyMessages(bool state);
+ void setTray(bool state);
+ void setStartInTray(bool state);
void setFontSize(double size);
void setFontFamily(QString family);
void setEmojiFontFamily(QString family);
-
- void setGroupView(bool state)
- {
- if (isGroupViewEnabled_ != state)
- emit groupViewStateChanged(state);
-
- isGroupViewEnabled_ = state;
- save();
- }
-
- void setMarkdownEnabled(bool state)
- {
- isMarkdownEnabled_ = state;
- save();
- }
-
- void setReadReceipts(bool state)
- {
- isReadReceiptsEnabled_ = state;
- save();
- }
-
- void setTypingNotifications(bool state)
- {
- isTypingNotificationsEnabled_ = state;
- save();
- }
-
- void setSortByImportance(bool state)
- {
- sortByImportance_ = state;
- emit roomSortingChanged();
- }
-
- void setButtonsInTimeline(bool state)
- {
- isButtonsInTimelineEnabled_ = state;
- save();
- }
-
- void setDesktopNotifications(bool state)
- {
- hasDesktopNotifications_ = state;
- save();
- }
-
- void setAvatarCircles(bool state)
- {
- avatarCircles_ = state;
- save();
- }
-
- void setDecryptSidebar(bool state)
- {
- decryptSidebar_ = state;
- save();
- }
+ void setGroupView(bool state);
+ void setMarkdown(bool state);
+ void setReadReceipts(bool state);
+ void setTypingNotifications(bool state);
+ void setSortByImportance(bool state);
+ void setButtonsInTimeline(bool state);
+ void setTimelineMaxWidth(int state);
+ void setDesktopNotifications(bool state);
+ void setAvatarCircles(bool state);
+ void setDecryptSidebar(bool state);
QString theme() const { return !theme_.isEmpty() ? theme_ : defaultTheme_; }
- bool isMessageHoverHighlightEnabled() const { return isMessageHoverHighlightEnabled_; }
- bool isTrayEnabled() const { return isTrayEnabled_; }
- bool isStartInTrayEnabled() const { return isStartInTrayEnabled_; }
- bool isGroupViewEnabled() const { return isGroupViewEnabled_; }
- bool isAvatarCirclesEnabled() const { return avatarCircles_; }
- bool isDecryptSidebarEnabled() const { return decryptSidebar_; }
- bool isMarkdownEnabled() const { return isMarkdownEnabled_; }
- bool isTypingNotificationsEnabled() const { return isTypingNotificationsEnabled_; }
- bool isSortByImportanceEnabled() const { return sortByImportance_; }
- bool isButtonsInTimelineEnabled() const { return isButtonsInTimelineEnabled_; }
- bool isReadReceiptsEnabled() const { return isReadReceiptsEnabled_; }
+ bool messageHoverHighlight() const { return messageHoverHighlight_; }
+ bool enlargeEmojiOnlyMessages() const { return enlargeEmojiOnlyMessages_; }
+ bool tray() const { return tray_; }
+ bool startInTray() const { return startInTray_; }
+ bool groupView() const { return groupView_; }
+ bool avatarCircles() const { return avatarCircles_; }
+ bool decryptSidebar() const { return decryptSidebar_; }
+ bool markdown() const { return markdown_; }
+ bool typingNotifications() const { return typingNotifications_; }
+ bool sortByImportance() const { return sortByImportance_; }
+ bool buttonsInTimeline() const { return buttonsInTimeline_; }
+ bool readReceipts() const { return readReceipts_; }
bool hasDesktopNotifications() const { return hasDesktopNotifications_; }
+ int timelineMaxWidth() const { return timelineMaxWidth_; }
double fontSize() const { return baseFontSize_; }
QString font() const { return font_; }
QString emojiFont() const { return emojiFont_; }
signals:
void groupViewStateChanged(bool state);
- void roomSortingChanged();
+ void roomSortingChanged(bool state);
+ void themeChanged(QString state);
+ void messageHoverHighlightChanged(bool state);
+ void enlargeEmojiOnlyMessagesChanged(bool state);
+ void trayChanged(bool state);
+ void startInTrayChanged(bool state);
+ void markdownChanged(bool state);
+ void typingNotificationsChanged(bool state);
+ void buttonInTimelineChanged(bool state);
+ void readReceiptsChanged(bool state);
+ void desktopNotificationsChanged(bool state);
+ void avatarCirclesChanged(bool state);
+ void decryptSidebarChanged(bool state);
+ void timelineMaxWidthChanged(int state);
+ void fontSizeChanged(double state);
+ void fontChanged(QString state);
+ void emojiFontChanged(QString state);
private:
// Default to system theme if QT_QPA_PLATFORMTHEME var is set.
@@ -150,18 +140,20 @@ private:
? "light"
: "system";
QString theme_;
- bool isMessageHoverHighlightEnabled_;
- bool isTrayEnabled_;
- bool isStartInTrayEnabled_;
- bool isGroupViewEnabled_;
- bool isMarkdownEnabled_;
- bool isTypingNotificationsEnabled_;
+ bool messageHoverHighlight_;
+ bool enlargeEmojiOnlyMessages_;
+ bool tray_;
+ bool startInTray_;
+ bool groupView_;
+ bool markdown_;
+ bool typingNotifications_;
bool sortByImportance_;
- bool isButtonsInTimelineEnabled_;
- bool isReadReceiptsEnabled_;
+ bool buttonsInTimeline_;
+ bool readReceipts_;
bool hasDesktopNotifications_;
bool avatarCircles_;
bool decryptSidebar_;
+ int timelineMaxWidth_;
double baseFontSize_;
QString font_;
QString emojiFont_;
@@ -211,9 +203,10 @@ private:
Toggle *timelineButtonsToggle_;
Toggle *typingNotifications_;
Toggle *messageHoverHighlight_;
+ Toggle *enlargeEmojiOnlyMessages_;
Toggle *sortByImportance_;
Toggle *readReceipts_;
- Toggle *markdownEnabled_;
+ Toggle *markdown_;
Toggle *desktopNotifications_;
Toggle *avatarCircles_;
Toggle *decryptSidebar_;
@@ -226,5 +219,7 @@ private:
QComboBox *fontSelectionCombo_;
QComboBox *emojiFontSelectionCombo_;
+ QSpinBox *timelineMaxWidthSpin_;
+
int sideMargin_ = 0;
};
diff --git a/src/Utils.cpp b/src/Utils.cpp
index 7f11a8cd..26ea124c 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -51,6 +51,14 @@ utils::localUser()
return QString::fromStdString(http::client()->user_id().to_string());
}
+bool
+utils::codepointIsEmoji(uint code)
+{
+ // TODO: Be more precise here.
+ return (code >= 0x2600 && code <= 0x27bf) || (code >= 0x1f300 && code <= 0x1f3ff) ||
+ (code >= 0x1f000 && code <= 0x1faff);
+}
+
QString
utils::replaceEmoji(const QString &body)
{
@@ -63,9 +71,7 @@ utils::replaceEmoji(const QString &body)
bool insideFontBlock = false;
for (auto &code : utf32_string) {
- // TODO: Be more precise here.
- if ((code >= 0x2600 && code <= 0x27bf) || (code >= 0x1f300 && code <= 0x1f3ff) ||
- (code >= 0x1f000 && code <= 0x1faff)) {
+ if (utils::codepointIsEmoji(code)) {
if (!insideFontBlock) {
fmtBody += QString("<font face=\"" + userFontFamily + "\">");
insideFontBlock = true;
@@ -136,13 +142,13 @@ utils::descriptiveTime(const QDateTime &then)
const auto days = then.daysTo(now);
if (days == 0)
- return then.time().toString(Qt::DefaultLocaleShortDate);
+ return QLocale::system().toString(then.time(), QLocale::ShortFormat);
else if (days < 2)
return QString(QCoreApplication::translate("descriptiveTime", "Yesterday"));
else if (days < 7)
return then.toString("dddd");
- return then.date().toString(Qt::DefaultLocaleShortDate);
+ return QLocale::system().toString(then.date(), QLocale::ShortFormat);
}
DescInfo
diff --git a/src/Utils.h b/src/Utils.h
index d3f66246..07a4a648 100644
--- a/src/Utils.h
+++ b/src/Utils.h
@@ -36,6 +36,9 @@ namespace utils {
using TimelineEvent = mtx::events::collections::TimelineEvents;
+bool
+codepointIsEmoji(uint code);
+
QString
replaceEmoji(const QString &body);
@@ -183,42 +186,6 @@ erase_if(ContainerT &items, const PredicateT &predicate)
}
}
-inline uint64_t
-event_timestamp(const mtx::events::collections::TimelineEvents &event)
-{
- return std::visit([](auto msg) { return msg.origin_server_ts; }, event);
-}
-
-inline nlohmann::json
-serialize_event(const mtx::events::collections::TimelineEvents &event)
-{
- return std::visit([](auto msg) { return json(msg); }, event);
-}
-
-inline mtx::events::EventType
-event_type(const mtx::events::collections::TimelineEvents &event)
-{
- return std::visit([](auto msg) { return msg.type; }, event);
-}
-
-inline std::string
-event_id(const mtx::events::collections::TimelineEvents &event)
-{
- return std::visit([](auto msg) { return msg.event_id; }, event);
-}
-
-inline QString
-eventId(const mtx::events::collections::TimelineEvents &event)
-{
- return QString::fromStdString(event_id(event));
-}
-
-inline QString
-event_sender(const mtx::events::collections::TimelineEvents &event)
-{
- return std::visit([](auto msg) { return QString::fromStdString(msg.sender); }, event);
-}
-
template<class T>
QString
message_body(const mtx::events::collections::TimelineEvents &event)
diff --git a/src/dialogs/CreateRoom.cpp b/src/dialogs/CreateRoom.cpp
index 06676d3d..be5b4638 100644
--- a/src/dialogs/CreateRoom.cpp
+++ b/src/dialogs/CreateRoom.cpp
@@ -112,7 +112,7 @@ CreateRoom::CreateRoom(QWidget *parent)
});
connect(visibilityCombo_,
- static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::activated),
+ static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
[this](const QString &text) {
if (text == "Private") {
request_.visibility = mtx::requests::Visibility::Private;
@@ -122,7 +122,7 @@ CreateRoom::CreateRoom(QWidget *parent)
});
connect(presetCombo_,
- static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::activated),
+ static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
[this](const QString &text) {
if (text == "Private Chat") {
request_.preset = mtx::requests::Preset::PrivateChat;
diff --git a/src/dialogs/InviteUsers.cpp b/src/dialogs/InviteUsers.cpp
index 691035ce..f85adb8f 100644
--- a/src/dialogs/InviteUsers.cpp
+++ b/src/dialogs/InviteUsers.cpp
@@ -1,5 +1,6 @@
#include <QDebug>
#include <QIcon>
+#include <QLabel>
#include <QListWidget>
#include <QListWidgetItem>
#include <QPushButton>
diff --git a/src/dialogs/InviteUsers.h b/src/dialogs/InviteUsers.h
index 952c97a5..684f60b4 100644
--- a/src/dialogs/InviteUsers.h
+++ b/src/dialogs/InviteUsers.h
@@ -1,13 +1,13 @@
#pragma once
#include <QFrame>
-#include <QLabel>
-#include <QListWidgetItem>
#include <QStringList>
class QPushButton;
+class QLabel;
class TextField;
class QListWidget;
+class QListWidgetItem;
namespace dialogs {
diff --git a/src/dialogs/ReadReceipts.cpp b/src/dialogs/ReadReceipts.cpp
index 0edd1ebf..7dcffc28 100644
--- a/src/dialogs/ReadReceipts.cpp
+++ b/src/dialogs/ReadReceipts.cpp
@@ -1,5 +1,6 @@
#include <QDebug>
#include <QIcon>
+#include <QLabel>
#include <QListWidgetItem>
#include <QPainter>
#include <QPushButton>
@@ -74,15 +75,17 @@ ReceiptItem::dateFormat(const QDateTime &then) const
auto days = then.daysTo(now);
if (days == 0)
- return tr("Today %1").arg(then.time().toString(Qt::DefaultLocaleShortDate));
+ return tr("Today %1")
+ .arg(QLocale::system().toString(then.time(), QLocale::ShortFormat));
else if (days < 2)
- return tr("Yesterday %1").arg(then.time().toString(Qt::DefaultLocaleShortDate));
+ return tr("Yesterday %1")
+ .arg(QLocale::system().toString(then.time(), QLocale::ShortFormat));
else if (days < 7)
return QString("%1 %2")
.arg(then.toString("dddd"))
- .arg(then.time().toString(Qt::DefaultLocaleShortDate));
+ .arg(QLocale::system().toString(then.time(), QLocale::ShortFormat));
- return then.toString(Qt::DefaultLocaleShortDate);
+ return QLocale::system().toString(then.time(), QLocale::ShortFormat);
}
ReadReceipts::ReadReceipts(QWidget *parent)
@@ -163,3 +166,10 @@ ReadReceipts::paintEvent(QPaintEvent *)
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
+
+void
+ReadReceipts::hideEvent(QHideEvent *event)
+{
+ userList_->clear();
+ QFrame::hideEvent(event);
+}
diff --git a/src/dialogs/ReadReceipts.h b/src/dialogs/ReadReceipts.h
index e298af0a..2e7a0217 100644
--- a/src/dialogs/ReadReceipts.h
+++ b/src/dialogs/ReadReceipts.h
@@ -2,12 +2,12 @@
#include <QDateTime>
#include <QFrame>
-#include <QHBoxLayout>
-#include <QLabel>
-#include <QListWidget>
-#include <QVBoxLayout>
class Avatar;
+class QLabel;
+class QListWidget;
+class QHBoxLayout;
+class QVBoxLayout;
namespace dialogs {
@@ -47,11 +47,7 @@ public slots:
protected:
void paintEvent(QPaintEvent *event) override;
- void hideEvent(QHideEvent *event) override
- {
- userList_->clear();
- QFrame::hideEvent(event);
- }
+ void hideEvent(QHideEvent *event) override;
private:
QLabel *topLabel_;
diff --git a/src/dialogs/RoomSettings.cpp b/src/dialogs/RoomSettings.cpp
index cc10ac91..26aece32 100644
--- a/src/dialogs/RoomSettings.cpp
+++ b/src/dialogs/RoomSettings.cpp
@@ -1,5 +1,6 @@
#include <QApplication>
#include <QComboBox>
+#include <QEvent>
#include <QFileDialog>
#include <QFontDatabase>
#include <QImageReader>
@@ -41,6 +42,17 @@ constexpr int WIDGET_SPACING = 15;
constexpr int TEXT_SPACING = 4;
constexpr int BUTTON_SPACING = 2 * TEXT_SPACING;
+bool
+ClickableFilter::eventFilter(QObject *obj, QEvent *event)
+{
+ if (event->type() == QEvent::MouseButtonRelease) {
+ emit clicked();
+ return true;
+ }
+
+ return QObject::eventFilter(obj, event);
+}
+
EditModal::EditModal(const QString &roomId, QWidget *parent)
: QWidget(parent)
, roomId_{roomId}
@@ -94,6 +106,28 @@ EditModal::EditModal(const QString &roomId, QWidget *parent)
}
void
+EditModal::topicEventSent()
+{
+ errorField_->hide();
+ close();
+}
+
+void
+EditModal::nameEventSent(const QString &name)
+{
+ errorField_->hide();
+ emit nameChanged(name);
+ close();
+}
+
+void
+EditModal::error(const QString &msg)
+{
+ errorField_->setText(msg);
+ errorField_->show();
+}
+
+void
EditModal::applyClicked()
{
// Check if the values are changed from the originals.
diff --git a/src/dialogs/RoomSettings.h b/src/dialogs/RoomSettings.h
index e41c866c..e0918afd 100644
--- a/src/dialogs/RoomSettings.h
+++ b/src/dialogs/RoomSettings.h
@@ -1,9 +1,7 @@
#pragma once
-#include <QEvent>
#include <QFrame>
#include <QImage>
-#include <QLabel>
#include <mtx/events/guest_access.hpp>
@@ -21,6 +19,8 @@ class QPixmap;
class TextField;
class TextField;
class Toggle;
+class QLabel;
+class QEvent;
class ClickableFilter : public QObject
{
@@ -35,15 +35,7 @@ signals:
void clicked();
protected:
- bool eventFilter(QObject *obj, QEvent *event) override
- {
- if (event->type() == QEvent::MouseButtonRelease) {
- emit clicked();
- return true;
- }
-
- return QObject::eventFilter(obj, event);
- }
+ bool eventFilter(QObject *obj, QEvent *event) override;
};
/// Convenience class which connects events emmited from threads
@@ -72,24 +64,9 @@ signals:
void nameChanged(const QString &roomName);
private slots:
- void topicEventSent()
- {
- errorField_->hide();
- close();
- }
-
- void nameEventSent(const QString &name)
- {
- errorField_->hide();
- emit nameChanged(name);
- close();
- }
-
- void error(const QString &msg)
- {
- errorField_->setText(msg);
- errorField_->show();
- }
+ void topicEventSent();
+ void nameEventSent(const QString &name);
+ void error(const QString &msg);
void applyClicked();
diff --git a/src/emoji/Category.cpp b/src/emoji/Category.cpp
index 7393b7bc..1e8df082 100644
--- a/src/emoji/Category.cpp
+++ b/src/emoji/Category.cpp
@@ -15,9 +15,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <QLabel>
+#include <QListView>
#include <QPainter>
#include <QScrollBar>
#include <QStyleOption>
+#include <QVBoxLayout>
#include "Config.h"
diff --git a/src/emoji/Category.h b/src/emoji/Category.h
index 2f39d621..79e616ee 100644
--- a/src/emoji/Category.h
+++ b/src/emoji/Category.h
@@ -18,13 +18,14 @@
#pragma once
#include <QColor>
-#include <QLabel>
-#include <QLayout>
-#include <QListView>
-#include <QStandardItemModel>
#include "ItemDelegate.h"
+class QLabel;
+class QListView;
+class QStandardItemModel;
+class QVBoxLayout;
+
namespace emoji {
class Category : public QWidget
diff --git a/src/popups/PopupItem.cpp b/src/popups/PopupItem.cpp
index 5513f942..b3784843 100644
--- a/src/popups/PopupItem.cpp
+++ b/src/popups/PopupItem.cpp
@@ -1,3 +1,4 @@
+#include <QLabel>
#include <QPaintEvent>
#include <QPainter>
#include <QStyleOption>
diff --git a/src/popups/PopupItem.h b/src/popups/PopupItem.h
index 7a710fdb..17a4f6bc 100644
--- a/src/popups/PopupItem.h
+++ b/src/popups/PopupItem.h
@@ -1,8 +1,5 @@
#pragma once
-#include <QHBoxLayout>
-#include <QLabel>
-#include <QPoint>
#include <QWidget>
#include "../AvatarProvider.h"
@@ -10,6 +7,8 @@
class Avatar;
struct SearchResult;
+class QLabel;
+class QHBoxLayout;
class PopupItem : public QWidget
{
diff --git a/src/popups/SuggestionsPopup.h b/src/popups/SuggestionsPopup.h
index 63c44538..73bfe6f7 100644
--- a/src/popups/SuggestionsPopup.h
+++ b/src/popups/SuggestionsPopup.h
@@ -1,8 +1,5 @@
#pragma once
-#include <QHBoxLayout>
-#include <QLabel>
-#include <QPoint>
#include <QWidget>
#include "CacheStructs.h"
diff --git a/src/popups/UserMentions.cpp b/src/popups/UserMentions.cpp
index 2e70dbd3..23a679f1 100644
--- a/src/popups/UserMentions.cpp
+++ b/src/popups/UserMentions.cpp
@@ -8,9 +8,9 @@
#include "Cache.h"
#include "ChatPage.h"
+#include "EventAccessors.h"
#include "Logging.h"
#include "UserMentions.h"
-//#include "timeline/TimelineItem.h"
using namespace popups;
@@ -75,12 +75,15 @@ UserMentions::initializeMentions(const QMap<QString, mtx::responses::Notificatio
for (const auto &item : notifs) {
for (const auto ¬if : item.notifications) {
- const auto event_id = QString::fromStdString(utils::event_id(notif.event));
+ const auto event_id =
+ QString::fromStdString(mtx::accessors::event_id(notif.event));
try {
const auto room_id = QString::fromStdString(notif.room_id);
- const auto user_id = utils::event_sender(notif.event);
- const auto body = utils::event_body(notif.event);
+ const auto user_id =
+ QString::fromStdString(mtx::accessors::sender(notif.event));
+ const auto body =
+ QString::fromStdString(mtx::accessors::body(notif.event));
pushItem(event_id,
user_id,
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index 371e9f58..95997eb8 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -219,6 +219,7 @@ TimelineModel::roleNames() const
{Section, "section"},
{Type, "type"},
{TypeString, "typeString"},
+ {IsOnlyEmoji, "isOnlyEmoji"},
{Body, "body"},
{FormattedBody, "formattedBody"},
{UserId, "userId"},
@@ -284,6 +285,22 @@ TimelineModel::data(const QString &id, int role) const
return QVariant(toRoomEventType(event));
case TypeString:
return QVariant(toRoomEventTypeString(event));
+ case IsOnlyEmoji: {
+ QString qBody = QString::fromStdString(body(event));
+
+ QVector<uint> utf32_string = qBody.toUcs4();
+ int emojiCount = 0;
+
+ for (auto &code : utf32_string) {
+ if (utils::codepointIsEmoji(code)) {
+ emojiCount++;
+ } else {
+ return QVariant(0);
+ }
+ }
+
+ return QVariant(emojiCount);
+ }
case Body:
return QVariant(utils::replaceEmoji(QString::fromStdString(body(event))));
case FormattedBody: {
@@ -386,6 +403,7 @@ TimelineModel::data(const QString &id, int role) const
// m.insert(names[Section], data(id, static_cast<int>(Section)));
m.insert(names[Type], data(id, static_cast<int>(Type)));
m.insert(names[TypeString], data(id, static_cast<int>(TypeString)));
+ m.insert(names[IsOnlyEmoji], data(id, static_cast<int>(IsOnlyEmoji)));
m.insert(names[Body], data(id, static_cast<int>(Body)));
m.insert(names[FormattedBody], data(id, static_cast<int>(FormattedBody)));
m.insert(names[UserId], data(id, static_cast<int>(UserId)));
@@ -810,7 +828,7 @@ TimelineModel::escapeEmoji(QString str) const
void
TimelineModel::viewRawMessage(QString id) const
{
- std::string ev = utils::serialize_event(events.value(id)).dump(4);
+ std::string ev = mtx::accessors::serialize_event(events.value(id)).dump(4);
auto dialog = new dialogs::RawMessage(QString::fromStdString(ev));
Q_UNUSED(dialog);
}
@@ -824,7 +842,7 @@ TimelineModel::viewDecryptedRawMessage(QString id) const
event = decryptEvent(*e).event;
}
- std::string ev = utils::serialize_event(event).dump(4);
+ std::string ev = mtx::accessors::serialize_event(event).dump(4);
auto dialog = new dialogs::RawMessage(QString::fromStdString(ev));
Q_UNUSED(dialog);
}
@@ -1849,6 +1867,8 @@ TimelineModel::formatMemberEvent(QString id)
rendered = tr("%1 changed their display name.").arg(name);
else if (avatarChanged)
rendered = tr("%1 changed their avatar.").arg(name);
+ else
+ rendered = tr("%1 changed some profile info.").arg(name);
// the case of nothing changed but join follows join shouldn't happen, so
// just show it as join
} else {
diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index ea7eaffd..3b01781f 100644
--- a/src/timeline/TimelineModel.h
+++ b/src/timeline/TimelineModel.h
@@ -142,6 +142,7 @@ public:
Section,
Type,
TypeString,
+ IsOnlyEmoji,
Body,
FormattedBody,
UserId,
diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp
index 0375ccc8..bf671cb0 100644
--- a/src/timeline/TimelineViewManager.cpp
+++ b/src/timeline/TimelineViewManager.cpp
@@ -21,7 +21,7 @@ Q_DECLARE_METATYPE(mtx::events::collections::TimelineEvents)
void
TimelineViewManager::updateEncryptedDescriptions()
{
- auto decrypt = settings->isDecryptSidebarEnabled();
+ auto decrypt = settings->decryptSidebar();
QHash<QString, QSharedPointer<TimelineModel>>::iterator i;
for (i = models.begin(); i != models.end(); ++i) {
auto ptr = i.value();
@@ -96,6 +96,7 @@ TimelineViewManager::TimelineViewManager(QSharedPointer<UserSettings> userSettin
#endif
container->setMinimumSize(200, 200);
view->rootContext()->setContextProperty("timelineManager", this);
+ view->rootContext()->setContextProperty("settings", settings.data());
updateColorPalette();
view->engine()->addImageProvider("MxcImage", imgProvider);
view->engine()->addImageProvider("colorimage", colorImgProvider);
@@ -121,7 +122,7 @@ TimelineViewManager::sync(const mtx::responses::Rooms &rooms)
const auto &room_model = models.value(QString::fromStdString(room_id));
room_model->addEvents(room.timeline);
- if (ChatPage::instance()->userSettings()->isTypingNotificationsEnabled()) {
+ if (ChatPage::instance()->userSettings()->typingNotifications()) {
std::vector<QString> typing;
typing.reserve(room.ephemeral.typing.size());
for (const auto &user : room.ephemeral.typing) {
@@ -141,7 +142,7 @@ TimelineViewManager::addRoom(const QString &room_id)
{
if (!models.contains(room_id)) {
QSharedPointer<TimelineModel> newRoom(new TimelineModel(this, room_id));
- newRoom->setDecryptDescription(settings->isDecryptSidebarEnabled());
+ newRoom->setDecryptDescription(settings->decryptSidebar());
connect(newRoom.data(),
&TimelineModel::newEncryptedImage,
@@ -225,7 +226,7 @@ TimelineViewManager::queueTextMessage(const QString &msg)
mtx::events::msg::Text text = {};
text.body = msg.trimmed().toStdString();
- if (settings->isMarkdownEnabled()) {
+ if (settings->markdown()) {
text.formatted_body = utils::markdownToHtml(msg).toStdString();
// Don't send formatted_body, when we don't need to
@@ -253,7 +254,7 @@ TimelineViewManager::queueTextMessage(const QString &msg)
// NOTE(Nico): rich replies always need a formatted_body!
text.format = "org.matrix.custom.html";
- if (settings->isMarkdownEnabled())
+ if (settings->markdown())
text.formatted_body =
utils::getFormattedQuoteBody(related, utils::markdownToHtml(msg))
.toStdString();
@@ -276,7 +277,7 @@ TimelineViewManager::queueEmoteMessage(const QString &msg)
mtx::events::msg::Emote emote;
emote.body = msg.trimmed().toStdString();
- if (html != msg.trimmed().toHtmlEscaped() && settings->isMarkdownEnabled()) {
+ if (html != msg.trimmed().toHtmlEscaped() && settings->markdown()) {
emote.formatted_body = html.toStdString();
emote.format = "org.matrix.custom.html";
}
diff --git a/src/ui/Avatar.cpp b/src/ui/Avatar.cpp
index cb77d1a8..70ebfcf2 100644
--- a/src/ui/Avatar.cpp
+++ b/src/ui/Avatar.cpp
@@ -1,4 +1,5 @@
#include <QPainter>
+#include <QPainterPath>
#include <QSettings>
#include "AvatarProvider.h"
diff --git a/src/ui/InfoMessage.cpp b/src/ui/InfoMessage.cpp
index 27bc0a5f..0b69564d 100644
--- a/src/ui/InfoMessage.cpp
+++ b/src/ui/InfoMessage.cpp
@@ -4,6 +4,7 @@
#include <QDateTime>
#include <QLocale>
#include <QPainter>
+#include <QPainterPath>
#include <QPen>
#include <QtGlobal>
diff --git a/src/ui/Painter.h b/src/ui/Painter.h
index 4d227a5a..2bb0981b 100644
--- a/src/ui/Painter.h
+++ b/src/ui/Painter.h
@@ -3,6 +3,7 @@
#include <QFontMetrics>
#include <QPaintDevice>
#include <QPainter>
+#include <QPainterPath>
#include <QtGlobal>
class Painter : public QPainter
@@ -163,5 +164,5 @@ public:
private:
Painter &_painter;
- QPainter::RenderHints hints_ = 0;
+ QPainter::RenderHints hints_ = {};
};
|