From f7c75a64fd87c7fa181ea6588c1a5ba02bcc17f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Blin?=
 <sebastien.blin@savoirfairelinux.com>
Date: Mon, 4 Jul 2022 13:15:20 -0400
Subject: [PATCH] utils: increase/decrease font size with Ctrl+{+,-,0}

Change-Id: Ide7294a97df683cd67ee93f72f1f11b9f4e6dc29
GitLab: #512
---
 resources/misc/projectcredits.html            |  4 +-
 src/app/appsettingsmanager.h                  |  1 +
 .../commoncomponents/TextMessageDelegate.qml  |  2 +-
 src/app/constant/JamiStrings.qml              |  1 +
 src/app/constant/JamiTheme.qml                | 69 +++++++++++--------
 src/app/mainview/MainView.qml                 | 43 +++++++++++-
 .../components/KeyboardShortcutTable.qml      | 12 ++++
 .../components/DeviceItemDelegate.qml         |  1 +
 .../components/MediaCodecDelegate.qml         |  2 +-
 .../components/SystemSettings.qml             | 30 ++++++++
 src/app/utilsadapter.cpp                      |  6 ++
 src/app/utilsadapter.h                        |  1 +
 12 files changed, 140 insertions(+), 32 deletions(-)

diff --git a/resources/misc/projectcredits.html b/resources/misc/projectcredits.html
index f905114eb..c5c4169e4 100644
--- a/resources/misc/projectcredits.html
+++ b/resources/misc/projectcredits.html
@@ -1,5 +1,5 @@
 <h3 align="center"><span style="font-weight:600"> CREATED BY:</span></h3>
-<p style="font-size:15px">Adrien Béraud<br>
+<p>Adrien Béraud<br>
 Albert Babí<br>
 Alexandre Lision<br>
 Alexandr Sergheev<br>
@@ -52,5 +52,5 @@ Trevor Tabah<br>
 Vsevolod Ivanov<br>
 Yang Wang<br></p>
 <h3 align="center"><span style="font-weight:600"> ARTWORK BY:</span></h3>
-<p style="font-size:15px">Charlotte Hoffmann<br>
+<p>Charlotte Hoffmann<br>
 Marianne Forget<br></p>
diff --git a/src/app/appsettingsmanager.h b/src/app/appsettingsmanager.h
index 928e416ac..797e752fc 100644
--- a/src/app/appsettingsmanager.h
+++ b/src/app/appsettingsmanager.h
@@ -45,6 +45,7 @@ extern const QString defaultDownloadPath;
     X(DisplayHyperlinkPreviews, true) \
     X(EnableExperimentalSwarm, false) \
     X(EnableDarkTheme, false) \
+    X(BaseZoom, 1.0) \
     X(AutoUpdate, true) \
     X(StartMinimized, false) \
     X(ShowChatviewHorizontally, true) \
diff --git a/src/app/commoncomponents/TextMessageDelegate.qml b/src/app/commoncomponents/TextMessageDelegate.qml
index c816673f1..75e942b0a 100644
--- a/src/app/commoncomponents/TextMessageDelegate.qml
+++ b/src/app/commoncomponents/TextMessageDelegate.qml
@@ -62,7 +62,7 @@ SBSMessageBase {
             height: implicitHeight
             wrapMode: Label.WrapAtWordBoundaryOrAnywhere
             selectByMouse: true
-            font.pixelSize: 15
+            font.pixelSize: JamiTheme.chatviewFontSize
             font.family: 'Ubuntu'
             font.hintingPreference: Font.PreferNoHinting
             renderType: Text.NativeRendering
diff --git a/src/app/constant/JamiStrings.qml b/src/app/constant/JamiStrings.qml
index 06050a032..4415f275b 100644
--- a/src/app/constant/JamiStrings.qml
+++ b/src/app/constant/JamiStrings.qml
@@ -377,6 +377,7 @@ Item {
     property string downloadFolder: qsTr("Downloads directory")
     property string tipChooseDownloadFolder: qsTr("Choose download directory")
     property string recordCall: qsTr("Record call")
+    property string textZoom: qsTr("Text zoom")
 
     // ChatviewSettings
     property string chatview: qsTr("Chatview")
diff --git a/src/app/constant/JamiTheme.qml b/src/app/constant/JamiTheme.qml
index 9c7af7efa..99ae00b39 100644
--- a/src/app/constant/JamiTheme.qml
+++ b/src/app/constant/JamiTheme.qml
@@ -27,12 +27,26 @@ import net.jami.Enums 1.1
 Item {
     property bool darkTheme: UtilsAdapter.getAppValue(Settings.EnableDarkTheme)
 
+    Connections {
+        target: UtilsAdapter
+
+        function onChangeFontSize() {
+            baseZoom = UtilsAdapter.getAppValue(Settings.BaseZoom)
+        }
+    }
+
     // Jami theme colors
     function rgba256(r, g, b, a) {
         return Qt.rgba(r / 255, g / 255, b / 255, a / 100.)
     }
-    property real fontSizeOffset: Qt.platform.os.toString() === "osx" ? 3 : 0;
-    property real fontSizeOffsetSmall: Qt.platform.os.toString() === "osx" ? 1 : 0;
+
+    function calcSize(size) {
+        return Math.min(Math.max(5, baseZoom * size), 30)
+    }
+
+    property real baseZoom: UtilsAdapter.getAppValue(Settings.BaseZoom)
+    property real fontSizeOffset: (Qt.platform.os.toString() === "osx" ? 3 : 0)
+    property real fontSizeOffsetSmall: (Qt.platform.os.toString() === "osx" ? 1 : 0)
 
     // General
     property color blackColor: "#000000"
@@ -163,6 +177,7 @@ Item {
     property color chatviewTextColor: darkTheme ? "#f0f0f0" : "#000000"
     property color chatviewTextColorLight: "#f0f0f0"
     property color chatviewTextColorDark: "#353637"
+    property real chatviewFontSize: calcSize(15)
     property color timestampColor: darkTheme ? "#bbb" : "#777"
     property color messageOutTxtColor: "#000000"
     property color messageInBgColor: darkTheme ? "#28b1ed" : "#e5e5e5"
@@ -222,23 +237,23 @@ Item {
     // Sizes
     property real qrCodeImageSize: 256
     property real splitViewHandlePreferredWidth: 4
-    property real indicatorFontSize: 6
-    property real tinyFontSize: 7 + fontSizeOffset
-    property real textFontSize: 9 + fontSizeOffset
-    property real bigFontSize: 22
-    property real settingsFontSize: 11 + fontSizeOffset
-    property real buttonFontSize: 9
-    property real participantFontSize: 10
-    property real menuFontSize: 12 + fontSizeOffset
-    property real headerFontSize: 13 + fontSizeOffset
-    property real titleFontSize: 16 + fontSizeOffset
-    property real tinyCreditsTextSize: 13 + fontSizeOffset
-    property real creditsTextSize: 15 + fontSizeOffset
-    property real primaryRadius: 4
-    property real smartlistItemFontSize: 10.5 + fontSizeOffset
-    property real smartlistItemInfoFontSize: 9 + fontSizeOffsetSmall
-    property real filterItemFontSize: smartlistItemFontSize
-    property real filterBadgeFontSize: 8.25
+    property real indicatorFontSize: calcSize(6)
+    property real tinyFontSize: calcSize(7 + fontSizeOffset)
+    property real textFontSize: calcSize(9 + fontSizeOffset)
+    property real bigFontSize: calcSize(22)
+    property real settingsFontSize: calcSize(11 + fontSizeOffset)
+    property real buttonFontSize: calcSize(9)
+    property real participantFontSize: calcSize(10)
+    property real menuFontSize: calcSize(12 + fontSizeOffset)
+    property real headerFontSize: calcSize(13 + fontSizeOffset)
+    property real titleFontSize: calcSize(16 + fontSizeOffset)
+    property real tinyCreditsTextSize: calcSize(13 + fontSizeOffset)
+    property real creditsTextSize: calcSize(15 + fontSizeOffset)
+    property real primaryRadius: calcSize(4)
+    property real smartlistItemFontSize: calcSize(10.5 + fontSizeOffset)
+    property real smartlistItemInfoFontSize: calcSize(9 + fontSizeOffsetSmall)
+    property real filterItemFontSize: calcSize(smartlistItemFontSize)
+    property real filterBadgeFontSize: calcSize(8.25)
     property real accountListItemHeight: 64
     property real accountListAvatarSize: 40
     property real smartListItemHeight: 64
@@ -256,8 +271,8 @@ Item {
     property int participantCallInStatusDelegateRadius: 5
     property real participantCallInStatusOpacity: 0.77
     property int participantCallInAvatarSize: 60
-    property int participantCallInNameFontSize: 11
-    property int participantCallInStatusFontSize: 8
+    property int participantCallInNameFontSize: calcSize(11)
+    property int participantCallInStatusFontSize: calcSize(8)
     property int participantCallInStatusTextWidthLimit: 80
     property int participantCallInStatusTextWidth: 40
     property int mosaicButtonRadius: 5
@@ -265,7 +280,7 @@ Item {
     property real mosaicButtonOpacity: 0.77
     property int mosaicButtonTextPreferredWidth: 40
     property int mosaicButtonTextPreferredHeight: 16
-    property int mosaicButtonTextPointSize: 8 + fontSizeOffsetSmall
+    property int mosaicButtonTextPointSize: calcSize(8 + fontSizeOffsetSmall)
     property int mosaicButtonPreferredWidth: 70
     property int mosaicButtonMaxWidth: 100
     property real avatarPresenceRatio: 0.26
@@ -321,7 +336,7 @@ Item {
     property real chatViewFooterTextAreaMaximumHeight: 130
     property real chatViewScrollToBottomButtonBottomMargin: 8
 
-    property real usernameBlockFontSize : 12
+    property real usernameBlockFontSize : calcSize(12)
     property real usernameBlockLineHeight : 14
     property real usernameBlockPadding : contactMessageAvatarSize  + 8
 
@@ -337,7 +352,7 @@ Item {
     property real filesToSendDelegateHeight: 100
     property real filesToSendDelegateRadius: 7
     property real filesToSendDelegateButtonSize: 16
-    property real filesToSendDelegateFontPointSize: textFontSize + 2
+    property real filesToSendDelegateFontPointSize: calcSize(textFontSize + 2)
 
     // SBSMessageBase
     property int sbsMessageBasePreferredPadding: 12
@@ -364,11 +379,11 @@ Item {
     property real wizardButtonWidth: 400
 
     // MaterialLineEdit
-    property real materialLineEditPointSize: 10 + fontSizeOffset
+    property real materialLineEditPointSize: calcSize(10 + fontSizeOffset)
     property real materialLineEditPadding: 16
 
     // UsernameLineEdit
-    property real usernameLineEditPointSize: 9 + fontSizeOffset
+    property real usernameLineEditPointSize:calcSize(9 + fontSizeOffset)
     property real usernameLineEditlookupInterval: 200
 
     // JamiScrollBar
@@ -394,7 +409,7 @@ Item {
     property int aboutBtnSize: 24
 
     // Messages point size
-    property real contactEventPointSize: 10 + fontSizeOffset
+    property real contactEventPointSize: calcSize(10 + fontSizeOffset)
     property int contactMessageAvatarSize: 24
 
 
diff --git a/src/app/mainview/MainView.qml b/src/app/mainview/MainView.qml
index e2a7fee3a..a14a26117 100644
--- a/src/app/mainview/MainView.qml
+++ b/src/app/mainview/MainView.qml
@@ -20,9 +20,10 @@ import QtQuick
 import QtQuick.Controls
 import QtQuick.Layouts
 
-import net.jami.Models 1.1
 import net.jami.Adapters 1.1
 import net.jami.Constants 1.1
+import net.jami.Enums 1.1
+import net.jami.Models 1.1
 
 // Import qml component files.
 import "components"
@@ -526,6 +527,46 @@ Rectangle {
         }
     }
 
+    Shortcut {
+        sequence: "Ctrl++"
+        context: Qt.ApplicationShortcut
+        onActivated: {
+            UtilsAdapter.setAppValue(Settings.BaseZoom, parseFloat(UtilsAdapter.getAppValue(Settings.BaseZoom)) + 0.1)
+        }
+    }
+
+    Shortcut {
+        sequence: "Ctrl+="
+        context: Qt.ApplicationShortcut
+        onActivated: {
+            UtilsAdapter.setAppValue(Settings.BaseZoom, parseFloat(UtilsAdapter.getAppValue(Settings.BaseZoom)) + 0.1)
+        }
+    }
+
+    Shortcut {
+        sequence: "Ctrl+-"
+        context: Qt.ApplicationShortcut
+        onActivated: {
+            UtilsAdapter.setAppValue(Settings.BaseZoom, parseFloat(UtilsAdapter.getAppValue(Settings.BaseZoom)) - 0.1)
+        }
+    }
+
+    Shortcut {
+        sequence: "Ctrl+_"
+        context: Qt.ApplicationShortcut
+        onActivated: {
+            UtilsAdapter.setAppValue(Settings.BaseZoom, parseFloat(UtilsAdapter.getAppValue(Settings.BaseZoom)) - 0.1)
+        }
+    }
+
+    Shortcut {
+        sequence: "Ctrl+0"
+        context: Qt.ApplicationShortcut
+        onActivated: {
+            UtilsAdapter.setAppValue(Settings.BaseZoom, 1.0)
+        }
+    }
+
     Shortcut {
         sequence: "Ctrl+G"
         context: Qt.ApplicationShortcut
diff --git a/src/app/mainview/components/KeyboardShortcutTable.qml b/src/app/mainview/components/KeyboardShortcutTable.qml
index a42c92854..7c64d6b13 100644
--- a/src/app/mainview/components/KeyboardShortcutTable.qml
+++ b/src/app/mainview/components/KeyboardShortcutTable.qml
@@ -64,6 +64,18 @@ Window {
             shortcut: "F11"
             description: qsTr("Full screen")
         }
+        ListElement {
+            shortcut: "Ctrl + +"
+            description: qsTr("Increase font size")
+        }
+        ListElement {
+            shortcut: "Ctrl + -"
+            description: qsTr("Decrease font size")
+        }
+        ListElement {
+            shortcut: "Ctrl + 0"
+            description: qsTr("Reset font size")
+        }
     }
 
     ListModel {
diff --git a/src/app/settingsview/components/DeviceItemDelegate.qml b/src/app/settingsview/components/DeviceItemDelegate.qml
index 5a5c29c2b..22dcc53f3 100644
--- a/src/app/settingsview/components/DeviceItemDelegate.qml
+++ b/src/app/settingsview/components/DeviceItemDelegate.qml
@@ -120,6 +120,7 @@ ItemDelegate {
                 Layout.leftMargin: editDeviceName.leftPadding
 
                 elide: Text.ElideRight
+                font.pointSize: JamiTheme.tinyFontSize
                 color: JamiTheme.textColor
                 text: deviceId === "" ? qsTr("Device Id") : deviceId
             }
diff --git a/src/app/settingsview/components/MediaCodecDelegate.qml b/src/app/settingsview/components/MediaCodecDelegate.qml
index eafd75263..a228a871e 100644
--- a/src/app/settingsview/components/MediaCodecDelegate.qml
+++ b/src/app/settingsview/components/MediaCodecDelegate.qml
@@ -107,7 +107,7 @@ ItemDelegate {
             elide: Text.ElideRight
             horizontalAlignment: Text.AlignLeft
             verticalAlignment: Text.AlignVCenter
-            font.pointSize: 8
+            font.pointSize: JamiTheme.textFontSize
             font.kerning: true
         }
     }
diff --git a/src/app/settingsview/components/SystemSettings.qml b/src/app/settingsview/components/SystemSettings.qml
index 1e48934ff..dfa0d5097 100644
--- a/src/app/settingsview/components/SystemSettings.qml
+++ b/src/app/settingsview/components/SystemSettings.qml
@@ -189,4 +189,34 @@ ColumnLayout {
             UtilsAdapter.setAppValue(Settings.Key.LANG, comboModel.get(modelIndex).id)
         }
     }
+
+
+    Connections {
+        target: UtilsAdapter
+
+        function onChangeFontSize() {
+            zoomSpinBox.valueField = Math.round(UtilsAdapter.getAppValue(Settings.BaseZoom) * 100.0)
+        }
+    }
+
+    SettingSpinBox {
+        id: zoomSpinBox
+        Layout.fillWidth: true
+        Layout.leftMargin: JamiTheme.preferredMarginSize
+
+        title: JamiStrings.textZoom
+        itemWidth: root.itemWidth
+
+        valueField: Math.round(UtilsAdapter.getAppValue(Settings.BaseZoom) * 100.0)
+
+        onNewValue: {
+            // here, avoid validator cause it can be painful for the user to change
+            // values by modifying the whole field.
+            if (valueField < 10)
+                valueField = 10
+            else if (valueField > 200)
+                valueField = 200
+            UtilsAdapter.setAppValue(Settings.BaseZoom, Math.round(valueField / 100.0))
+        }
+    }
 }
diff --git a/src/app/utilsadapter.cpp b/src/app/utilsadapter.cpp
index c029bfb8b..ca30ded4e 100644
--- a/src/app/utilsadapter.cpp
+++ b/src/app/utilsadapter.cpp
@@ -361,12 +361,18 @@ UtilsAdapter::getAppValue(const Settings::Key key)
 void
 UtilsAdapter::setAppValue(const Settings::Key key, const QVariant& value)
 {
+    if (key == Settings::Key::BaseZoom) {
+        if (value.toDouble() < 0.1 || value.toDouble() > 2.0)
+            return;
+    }
     settingsManager_->setValue(key, value);
     // If we change the lang preference, reload the translations
     if (key == Settings::Key::LANG)
         settingsManager_->loadTranslations();
     else if (key == Settings::Key::EnableExperimentalSwarm)
         Q_EMIT showExperimentalSwarm();
+    else if (key == Settings::Key::BaseZoom)
+        Q_EMIT changeFontSize();
 }
 
 QString
diff --git a/src/app/utilsadapter.h b/src/app/utilsadapter.h
index 8d520a07a..1fbe37f94 100644
--- a/src/app/utilsadapter.h
+++ b/src/app/utilsadapter.h
@@ -111,6 +111,7 @@ public:
 Q_SIGNALS:
     void debugMessageReceived(const QString& message);
     void showExperimentalSwarm();
+    void changeFontSize();
 
 private:
     QClipboard* clipboard_;
-- 
GitLab