Make settings update immediately in qml and allow limiting timeline width

Limiting improves readability on wide monitors.

The immediate update of the settings is done by just exposing settings
as properties and then setting the settings as a context property.
This commit is contained in:
Nicolas Werner 2020-05-26 22:27:05 +02:00
parent 4ee9e5c27c
commit f452bdf2b0
8 changed files with 259 additions and 115 deletions

View file

@ -6,7 +6,7 @@ Rectangle {
id: avatar
width: 48
height: 48
radius: settings.avatar_circles ? height/2 : 3
radius: settings.avatarCircles ? height/2 : 3
property alias url: img.source
property string displayName
@ -39,7 +39,7 @@ Rectangle {
anchors.fill: parent
width: avatar.width
height: avatar.height
radius: settings.avatar_circles ? height/2 : 3
radius: settings.avatarCircles ? height/2 : 3
}
}
}

View file

@ -30,7 +30,7 @@ Flow {
TextMetrics {
id: textMetrics
font.family: settings.emoji_font_family
font.family: settings.emojiFont
elide: Text.ElideRight
elideWidth: 150
text: reaction.text
@ -40,14 +40,14 @@ Flow {
anchors.baseline: reactionCounter.baseline
id: reactionText
text: textMetrics.elidedText + (textMetrics.elidedText == textMetrics.text ? "" : "…")
font.family: settings.emoji_font_family
font.family: settings.emojiFont
color: reaction.hovered ? colors.highlight : colors.text
maximumLineCount: 1
}
Rectangle {
id: divider
height: reactionCounter.implicitHeight * 1.4
height: Math.floor(reactionCounter.implicitHeight * 1.4)
width: 1
color: reaction.hovered ? colors.highlight : colors.text
}
@ -64,7 +64,7 @@ Flow {
background: Rectangle {
anchors.centerIn: parent
implicitWidth: reaction.implicitWidth
implicitHeight: reaction.implicitHeight
height: reaction.implicitHeight
border.color: (reaction.hovered || model.selfReacted )? colors.highlight : colors.text
color: colors.base
border.width: 1

View file

@ -25,13 +25,13 @@ MouseArea {
messageContextMenu.show(model.id, model.type, model.isEncrypted, row)
}
Rectangle {
color: (timelineSettings.message_hover_highlight && parent.containsMouse) ? colors.base : "transparent"
color: (settings.isMessageHoverHighlightEnabled && parent.containsMouse) ? colors.base : "transparent"
anchors.fill: row
}
RowLayout {
id: row
anchors.leftMargin: avatarSize + 4
anchors.leftMargin: avatarSize + 16
anchors.left: parent.left
anchors.right: parent.right
@ -78,7 +78,7 @@ MouseArea {
}
ImageButton {
visible: timelineSettings.buttons
visible: settings.buttonsInTimeline
Layout.alignment: Qt.AlignRight | Qt.AlignTop
Layout.preferredHeight: 16
width: 16
@ -94,7 +94,7 @@ MouseArea {
onClicked: chat.model.replyAction(model.id)
}
ImageButton {
visible: timelineSettings.buttons
visible: settings.buttonsInTimeline
Layout.alignment: Qt.AlignRight | Qt.AlignTop
Layout.preferredHeight: 16
width: 16

View file

@ -3,7 +3,6 @@ import QtQuick.Controls 2.3
import QtQuick.Layouts 1.2
import QtGraphicalEffects 1.0
import QtQuick.Window 2.2
import Qt.labs.settings 1.0
import im.nheko 1.0
@ -21,22 +20,6 @@ Page {
id: fontMetrics
}
Settings {
id: settings
category: "user"
property bool avatar_circles: true
property string emoji_font_family: "default"
property double font_size: Qt.application.font.pointSize
}
Settings {
id: timelineSettings
category: "user/timeline"
property bool buttons: true
property bool message_hover_highlight: false
property bool enlarge_emoji_only_msg: false
}
Menu {
id: messageContextMenu
modal: true
@ -113,12 +96,12 @@ Page {
visible: timelineManager.timeline != null
cacheBuffer: 500
cacheBuffer: 400
anchors.left: parent.left
anchors.right: parent.right
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.bottom: chatFooter.top
width: parent.width
anchors.leftMargin: 4
anchors.rightMargin: scrollbar.width
@ -160,7 +143,7 @@ Page {
id: scrollbar
parent: chat.parent
anchors.top: chat.top
anchors.left: chat.right
anchors.right: chat.right
anchors.bottom: chat.bottom
}
@ -175,7 +158,8 @@ Page {
id: wrapper
property Item section
width: chat.width
anchors.horizontalCenter: parent.horizontalCenter
width: (settings.timelineMaxWidth > 100 && (parent.width - settings.timelineMaxWidth) > 32) ? settings.timelineMaxWidth : (parent.width - 32)
height: section ? section.height + timelinerow.height : timelinerow.height
color: "transparent"
@ -245,7 +229,8 @@ Page {
}
Row {
height: userName.height
spacing: 4
spacing: 8
Avatar {
width: avatarSize
height: avatarSize

View file

@ -6,5 +6,5 @@ MatrixText {
width: parent ? parent.width : undefined
height: isReply ? Math.min(chat.height / 8, implicitHeight) : undefined
clip: true
font.pointSize: (timelineSettings.enlarge_emoji_only_msg && model.data.isOnlyEmoji > 0 && model.data.isOnlyEmoji < 4) ? settings.font_size * 3 : settings.font_size
font.pointSize: (settings.enlargeEmojiOnlyMessages && model.data.isOnlyEmoji > 0 && model.data.isOnlyEmoji < 4) ? settings.fontSize * 3 : settings.fontSize
}

View file

@ -30,6 +30,7 @@
#include <QScrollArea>
#include <QScroller>
#include <QSettings>
#include <QSpinBox>
#include <QStandardPaths>
#include <QString>
#include <QTextStream>
@ -56,6 +57,7 @@ UserSettings::load()
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();
timelineMaxWidth_ = settings.value("user/timeline/max_width", 0).toInt();
isMessageHoverHighlightEnabled_ =
settings.value("user/timeline/message_hover_highlight", false).toBool();
isEnlargeEmojiOnlyMessagesEnabled_ =
@ -73,34 +75,183 @@ UserSettings::load()
applyTheme();
}
void
UserSettings::setMessageHoverHighlight(bool state)
{
if (state == isMessageHoverHighlightEnabled_)
return;
isMessageHoverHighlightEnabled_ = state;
emit messageHoverHighlightChanged(state);
save();
}
void
UserSettings::setEnlargeEmojiOnlyMessages(bool state)
{
if (state == isEnlargeEmojiOnlyMessagesEnabled_)
return;
isEnlargeEmojiOnlyMessagesEnabled_ = state;
emit enlargeEmojiOnlyMessagesChanged(state);
save();
}
void
UserSettings::setTray(bool state)
{
if (state == isTrayEnabled_)
return;
isTrayEnabled_ = state;
emit trayChanged(state);
save();
}
void
UserSettings::setStartInTray(bool state)
{
if (state == isStartInTrayEnabled_)
return;
isStartInTrayEnabled_ = state;
emit startInTrayChanged(state);
save();
}
void
UserSettings::setGroupView(bool state)
{
if (isGroupViewEnabled_ != state)
emit groupViewStateChanged(state);
isGroupViewEnabled_ = state;
save();
}
void
UserSettings::setMarkdownEnabled(bool state)
{
if (state == isMarkdownEnabled_)
return;
isMarkdownEnabled_ = state;
emit markdownChanged(state);
save();
}
void
UserSettings::setReadReceipts(bool state)
{
if (state == isReadReceiptsEnabled_)
return;
isReadReceiptsEnabled_ = state;
emit readReceiptsChanged(state);
save();
}
void
UserSettings::setTypingNotifications(bool state)
{
if (state == isTypingNotificationsEnabled_)
return;
isTypingNotificationsEnabled_ = 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 == isButtonsInTimelineEnabled_)
return;
isButtonsInTimelineEnabled_ = 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
@ -171,6 +322,7 @@ UserSettings::save()
settings.setValue("buttons", isButtonsInTimelineEnabled_);
settings.setValue("message_hover_highlight", isMessageHoverHighlightEnabled_);
settings.setValue("enlarge_emoji_only_msg", isEnlargeEmojiOnlyMessagesEnabled_);
settings.setValue("max_width", timelineMaxWidth_);
settings.endGroup();
settings.setValue("avatar_circles", avatarCircles_);
@ -187,6 +339,8 @@ UserSettings::save()
settings.setValue("emoji_font_family", emojiFont_);
settings.endGroup();
settings.sync();
}
HorizontalLine::HorizontalLine(QWidget *parent)
@ -251,6 +405,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
fontSizeCombo_ = new QComboBox{this};
fontSelectionCombo_ = new QComboBox{this};
emojiFontSelectionCombo_ = new QComboBox{this};
timelineMaxWidthSpin_ = new QSpinBox{this};
if (!settings_->isTrayEnabled())
startInTrayToggle_->setDisabled(true);
@ -295,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);
@ -366,6 +525,10 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
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 "
@ -525,6 +688,11 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
settings_->setEnlargeEmojiOnlyMessages(!isDisabled);
});
connect(timelineMaxWidthSpin_,
qOverload<int>(&QSpinBox::valueChanged),
this,
[this](int newValue) { settings_->setTimelineMaxWidth(newValue); });
connect(
sessionKeysImportBtn, &QPushButton::clicked, this, &UserSettingsPage::importSessionKeys);
@ -560,6 +728,7 @@ UserSettingsPage::showEvent(QShowEvent *)
messageHoverHighlight_->setState(!settings_->isMessageHoverHighlightEnabled());
enlargeEmojiOnlyMessages_->setState(!settings_->isEnlargeEmojiOnlyMessagesEnabled());
deviceIdValue_->setText(QString::fromStdString(http::client()->device_id()));
timelineMaxWidthSpin_->setValue(settings_->timelineMaxWidth());
deviceFingerprintValue_->setText(
utils::humanReadableFingerprint(olm::client()->identity_keys().ed25519));

View file

@ -27,6 +27,7 @@ class Toggle;
class QLabel;
class QFormLayout;
class QComboBox;
class QSpinBox;
class QHBoxLayout;
class QVBoxLayout;
@ -38,6 +39,39 @@ class UserSettings : public QObject
{
Q_OBJECT
Q_PROPERTY(QString theme READ theme WRITE setTheme NOTIFY themeChanged)
Q_PROPERTY(bool isMessageHoverHighlightEnabled READ isMessageHoverHighlightEnabled WRITE
setMessageHoverHighlight NOTIFY messageHoverHighlightChanged)
Q_PROPERTY(bool enlargeEmojiOnlyMessages READ isEnlargeEmojiOnlyMessagesEnabled WRITE
setEnlargeEmojiOnlyMessages NOTIFY enlargeEmojiOnlyMessagesChanged)
Q_PROPERTY(bool trayEnabled READ isTrayEnabled WRITE setTray NOTIFY trayChanged)
Q_PROPERTY(bool startInTrayEnabled READ isStartInTrayEnabled WRITE setStartInTray NOTIFY
startInTrayChanged)
Q_PROPERTY(bool groupViewEnabled READ isGroupViewEnabled WRITE setGroupView NOTIFY
groupViewStateChanged)
Q_PROPERTY(
bool markdown READ isMarkdownEnabled WRITE setMarkdownEnabled NOTIFY markdownChanged)
Q_PROPERTY(bool typingNotifications READ isTypingNotificationsEnabled WRITE
setTypingNotifications NOTIFY typingNotificationsChanged)
Q_PROPERTY(bool sortByImportance READ isSortByImportanceEnabled WRITE setSortByImportance
NOTIFY roomSortingChanged)
Q_PROPERTY(bool buttonsInTimeline READ isButtonsInTimelineEnabled WRITE setButtonsInTimeline
NOTIFY buttonInTimelineChanged)
Q_PROPERTY(bool readReceipts READ isReadReceiptsEnabled WRITE setReadReceipts NOTIFY
readReceiptsChanged)
Q_PROPERTY(bool desktopNotifications READ hasDesktopNotifications WRITE
setDesktopNotifications NOTIFY desktopNotificationsChanged)
Q_PROPERTY(bool avatarCircles READ isAvatarCirclesEnabled WRITE setAvatarCircles NOTIFY
avatarCirclesChanged)
Q_PROPERTY(bool decryptSidebar READ isDecryptSidebarEnabled 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();
@ -45,88 +79,23 @@ public:
void load();
void applyTheme();
void setTheme(QString theme);
void setMessageHoverHighlight(bool state)
{
isMessageHoverHighlightEnabled_ = state;
save();
}
void setEnlargeEmojiOnlyMessages(bool state)
{
isEnlargeEmojiOnlyMessagesEnabled_ = 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 setMarkdownEnabled(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_; }
@ -145,13 +114,30 @@ public:
bool isButtonsInTimelineEnabled() const { return isButtonsInTimelineEnabled_; }
bool isReadReceiptsEnabled() const { return isReadReceiptsEnabled_; }
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.
@ -173,6 +159,7 @@ private:
bool hasDesktopNotifications_;
bool avatarCircles_;
bool decryptSidebar_;
int timelineMaxWidth_;
double baseFontSize_;
QString font_;
QString emojiFont_;
@ -238,5 +225,7 @@ private:
QComboBox *fontSelectionCombo_;
QComboBox *emojiFontSelectionCombo_;
QSpinBox *timelineMaxWidthSpin_;
int sideMargin_ = 0;
};

View file

@ -88,6 +88,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);