From 214d9add5870b78302bb73c7a3bbdee9f1f1fc8c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Blin?=
 <sebastien.blin@savoirfairelinux.com>
Date: Thu, 13 Aug 2020 13:05:17 -0400
Subject: [PATCH] shortcuts: re-add shortcuts and shortcuts view

Gitlab: #2
Change-Id: Ic04fe6f2dfd01c561799d1707601b48058a9c89c
---
 qml.qrc                                       |   2 +
 src/mainview/MainView.qml                     |  91 +++
 src/mainview/components/AccountComboBox.qml   |  14 +
 src/mainview/components/CallStackView.qml     |   6 -
 src/mainview/components/ContactSearchBar.qml  |   6 +
 .../components/ConversationSmartListView.qml  |  70 ++
 .../ConversationSmartListViewItemDelegate.qml |   4 +-
 src/mainview/components/IncomingCallPage.qml  |  20 +
 src/mainview/components/SidePanelTabBar.qml   |  50 +-
 src/settingsview/SettingsView.qml             |   2 +
 .../components/KeyBoardShortcutKey.qml        |  27 +
 .../components/KeyBoardShortcutTable.qml      | 619 ++++++++++++++++++
 src/utils.cpp                                 |  12 +
 src/utils.h                                   |   2 +
 14 files changed, 905 insertions(+), 20 deletions(-)
 create mode 100644 src/settingsview/components/KeyBoardShortcutKey.qml
 create mode 100644 src/settingsview/components/KeyBoardShortcutTable.qml

diff --git a/qml.qrc b/qml.qrc
index b60c0929e..1f2dde369 100644
--- a/qml.qrc
+++ b/qml.qrc
@@ -5,6 +5,8 @@
         <file>src/settingsview/components/LeftPanelView.qml</file>
         <file>src/settingsview/components/AvSettingPage.qml</file>
         <file>src/settingsview/components/GeneralSettingsPage.qml</file>
+        <file>src/settingsview/components/KeyBoardShortcutTable.qml</file>
+        <file>src/settingsview/components/KeyBoardShortcutKey.qml</file>
         <file>src/settingsview/components/PluginSettingsPage.qml</file>
         <file>src/settingsview/components/PluginListSettingsView.qml</file>
         <file>src/settingsview/components/PluginListPreferencesView.qml</file>
diff --git a/src/mainview/MainView.qml b/src/mainview/MainView.qml
index 932eda156..a553fbed9 100644
--- a/src/mainview/MainView.qml
+++ b/src/mainview/MainView.qml
@@ -708,4 +708,95 @@ Window {
         mainViewWindow.hide()
         mainViewWindow.closeApp()
     }
+
+    Shortcut {
+        sequence: "Ctrl+M"
+        context: Qt.ApplicationShortcut
+        onActivated: {
+            if (!inSettingsView) {
+                toggleSettingsView()
+            }
+            leftPanelSettingsView.btnMediaSettings.clicked()
+        }
+    }
+
+    Shortcut {
+        sequence: "Ctrl+G"
+        context: Qt.ApplicationShortcut
+        onActivated: {
+            if (!inSettingsView) {
+                toggleSettingsView()
+            }
+            leftPanelSettingsView.btnGeneralSettings.clicked()
+        }
+    }
+
+    Shortcut {
+        sequence: "Ctrl+I"
+        context: Qt.ApplicationShortcut
+        onActivated: {
+            if (!inSettingsView) {
+                toggleSettingsView()
+            }
+            leftPanelSettingsView.btnAccountSettings.clicked()
+        }
+    }
+
+    Shortcut {
+        sequence: "Ctrl+P"
+        context: Qt.ApplicationShortcut
+        onActivated: {
+            if (!inSettingsView) {
+                toggleSettingsView()
+            }
+            leftPanelSettingsView.btnPluginSettings.clicked()
+        }
+    }
+
+    Shortcut {
+        sequence: "F10"
+        context: Qt.ApplicationShortcut
+        onActivated: {
+            shortcutsTable.open()
+        }
+    }
+
+    Shortcut {
+        sequence: "F11"
+        context: Qt.ApplicationShortcut
+        onActivated: {
+            if (mainViewWindow.visibility !== 5) // 5 = FullScreen
+                mainViewWindow.visibility = "FullScreen"
+            else
+                mainViewWindow.visibility = "Windowed"
+        }
+    }
+
+    Shortcut {
+        sequence: "Ctrl+D"
+        context: Qt.ApplicationShortcut
+        onActivated: CallAdapter.hangUpThisCall()
+    }
+
+    Shortcut {
+        sequence: "Ctrl+Shift+A"
+        context: Qt.ApplicationShortcut
+        onActivated: {
+            ClientWrapper.utilsAdaptor.makePermanentCurrentConv()
+            communicationPageMessageWebView.setSendContactRequestButtonVisible(false)
+        }
+    }
+
+    Shortcut {
+        sequence: "Ctrl+Shift+N"
+        context: Qt.ApplicationShortcut
+        onActivated: mainViewWindowSidePanel.needToAddNewAccount()
+    }
+
+    KeyBoardShortcutTable {
+        id: shortcutsTable
+
+        x: Math.round((mainViewWindow.width - width) / 2)
+        y: Math.round((mainViewWindow.height - height) / 2)
+    }
 }
diff --git a/src/mainview/components/AccountComboBox.qml b/src/mainview/components/AccountComboBox.qml
index 358095127..0252b8d7f 100644
--- a/src/mainview/components/AccountComboBox.qml
+++ b/src/mainview/components/AccountComboBox.qml
@@ -271,6 +271,14 @@ ComboBox {
     popup: AccountComboBoxPopup {
         id: comboBoxPopup
 
+        Shortcut {
+            sequence: "Ctrl+J"
+            context: Qt.ApplicationShortcut
+            onActivated: comboBoxPopup.visible ?
+                comboBoxPopup.close() :
+                comboBoxPopup.open()
+        }
+
         onAccountNeedToChange: {
             accountComboBox.accountChanged(index)
         }
@@ -279,4 +287,10 @@ ComboBox {
             accountComboBox.newAccountButtonClicked()
         }
     }
+
+    Shortcut {
+        sequence: "Ctrl+,"
+        context: Qt.ApplicationShortcut
+        onActivated: settingBtnClicked()
+    }
 }
diff --git a/src/mainview/components/CallStackView.qml b/src/mainview/components/CallStackView.qml
index c4901c69f..210de1b68 100644
--- a/src/mainview/components/CallStackView.qml
+++ b/src/mainview/components/CallStackView.qml
@@ -31,12 +31,6 @@ Rectangle {
 
     anchors.fill: parent
 
-    Shortcut {
-        sequence: "Ctrl+D"
-        context: Qt.ApplicationShortcut
-        onActivated: CallAdapter.hangUpThisCall()
-    }
-
     /*
      * When selected conversation is changed,
      * these values will also be changed.
diff --git a/src/mainview/components/ContactSearchBar.qml b/src/mainview/components/ContactSearchBar.qml
index 3a1f52f70..ef75bbcd9 100644
--- a/src/mainview/components/ContactSearchBar.qml
+++ b/src/mainview/components/ContactSearchBar.qml
@@ -110,4 +110,10 @@ Rectangle {
                         contactSearchBar.text)
         }
     }
+
+    Shortcut {
+        sequence: "Ctrl+F"
+        context: Qt.ApplicationShortcut
+        onActivated: contactSearchBar.forceActiveFocus()
+    }
 }
diff --git a/src/mainview/components/ConversationSmartListView.qml b/src/mainview/components/ConversationSmartListView.qml
index 65177c190..f850c1173 100644
--- a/src/mainview/components/ConversationSmartListView.qml
+++ b/src/mainview/components/ConversationSmartListView.qml
@@ -97,4 +97,74 @@ ListView {
     }
 
     ScrollIndicator.vertical: ScrollIndicator {}
+
+    Shortcut {
+        sequence: "Ctrl+Shift+X"
+        context: Qt.ApplicationShortcut
+        enabled: conversationSmartListView.visible
+        onActivated: {
+            CallAdapter.placeCall()
+        }
+    }
+
+    Shortcut {
+        sequence: "Ctrl+Shift+C"
+        context: Qt.ApplicationShortcut
+        enabled: conversationSmartListView.visible
+        onActivated: {
+            CallAdapter.placeAudioOnlyCall()
+        }
+    }
+
+    Shortcut {
+        sequence: "Ctrl+Shift+L"
+        context: Qt.ApplicationShortcut
+        enabled: conversationSmartListView.visible
+        onActivated: {
+            ClientWrapper.utilsAdaptor.clearConversationHistory(ClientWrapper.utilsAdaptor.getCurrAccId(),
+                                                  ClientWrapper.utilsAdaptor.getCurrConvId())
+        }
+    }
+
+    Shortcut {
+        sequence: "Ctrl+Shift+B"
+        context: Qt.ApplicationShortcut
+        enabled: conversationSmartListView.visible
+        onActivated: {
+            ClientWrapper.utilsAdaptor.removeConversation(ClientWrapper.utilsAdaptor.getCurrAccId(),
+                                            ClientWrapper.utilsAdaptor.getCurrConvId(), true)
+            conversationSmartListView.needToBackToWelcomePage()
+        }
+    }
+
+    Shortcut {
+        sequence: "Ctrl+Shift+Delete"
+        context: Qt.ApplicationShortcut
+        enabled: conversationSmartListView.visible
+        onActivated: {
+            ClientWrapper.utilsAdaptor.removeConversation(ClientWrapper.utilsAdaptor.getCurrAccId(),
+                                            ClientWrapper.utilsAdaptor.getCurrConvId(), false)
+        }
+    }
+
+    Shortcut {
+        sequence: "Ctrl+Down"
+        context: Qt.ApplicationShortcut
+        enabled: conversationSmartListView.visible
+        onActivated: {
+            if (currentIndex + 1 >= count) return
+            conversationSmartListView.currentIndex += 1
+        }
+    }
+
+    Shortcut {
+        sequence: "Ctrl+Up"
+        context: Qt.ApplicationShortcut
+        enabled: conversationSmartListView.visible
+        onActivated: {
+            if (currentIndex <= 0) return
+            conversationSmartListView.currentIndex -= 1
+        }
+    }
+
 }
diff --git a/src/mainview/components/ConversationSmartListViewItemDelegate.qml b/src/mainview/components/ConversationSmartListViewItemDelegate.qml
index 3538200a1..4e2fe3cc5 100644
--- a/src/mainview/components/ConversationSmartListViewItemDelegate.qml
+++ b/src/mainview/components/ConversationSmartListViewItemDelegate.qml
@@ -57,6 +57,8 @@ ItemDelegate {
                     return InCall ? Qt.lighter(JamiTheme.selectionBlue,
                                                1.8) : JamiTheme.releaseColor
                 })
+                conversationSmartListView.needToSelectItems(UID)
+                conversationSmartListView.needToGrabFocus()
             }
         }
 
@@ -200,8 +202,6 @@ ItemDelegate {
                 smartListContextMenu.openMenu()
             } else if (mouse.button === Qt.LeftButton) {
                 conversationSmartListView.currentIndex = index
-                conversationSmartListView.needToSelectItems(UID)
-                conversationSmartListView.needToGrabFocus()
             }
         }
         onEntered: {
diff --git a/src/mainview/components/IncomingCallPage.qml b/src/mainview/components/IncomingCallPage.qml
index eafbaffe9..89b5ffa6f 100644
--- a/src/mainview/components/IncomingCallPage.qml
+++ b/src/mainview/components/IncomingCallPage.qml
@@ -339,4 +339,24 @@ Window {
     }
 
     color: "transparent"
+
+    Shortcut {
+        sequence: "Ctrl+Y"
+        context: Qt.ApplicationShortcut
+        onActivated: {
+            incomingCallPage.close()
+            CallAdapter.acceptACall(responsibleAccountId,
+                                    responsibleConvUid)
+        }
+    }
+
+    Shortcut {
+        sequence: "Ctrl+Shift+D"
+        context: Qt.ApplicationShortcut
+        onActivated: {
+            incomingCallPage.close()
+            CallAdapter.refuseACall(responsibleAccountId,
+                                    responsibleConvUid)
+        }
+    }
 }
diff --git a/src/mainview/components/SidePanelTabBar.qml b/src/mainview/components/SidePanelTabBar.qml
index 0d27f7eed..f145a2691 100644
--- a/src/mainview/components/SidePanelTabBar.qml
+++ b/src/mainview/components/SidePanelTabBar.qml
@@ -76,6 +76,16 @@ TabBar {
             height: tabBar.height
             color: JamiTheme.backgroundColor
 
+            function showConversations() {
+                ConversationsAdapter.setConversationFilter("")
+                contactSearchBar.setPlaceholderString(
+                            JamiTheme.contactSearchBarPlaceHolderConversationText)
+                pageOne.down = true
+                pageTwo.down = false
+                setCurrentUidSmartListModelIndex()
+                forceReselectConversationSmartListCurrentIndex()
+            }
+
             Image {
                 id: imgRectOne
                 anchors.horizontalCenter: buttonRectOne.horizontalCenter
@@ -127,13 +137,7 @@ TabBar {
                 anchors.fill: parent
                 hoverEnabled: true
                 onPressed: {
-                    ConversationsAdapter.setConversationFilter("")
-                    contactSearchBar.setPlaceholderString(
-                                JamiTheme.contactSearchBarPlaceHolderConversationText)
-                    pageOne.down = true
-                    pageTwo.down = false
-                    setCurrentUidSmartListModelIndex()
-                    forceReselectConversationSmartListCurrentIndex()
+                    buttonRectOne.showConversations()
                 }
                 onReleased: {
                     buttonRectOne.color = JamiTheme.backgroundColor
@@ -145,6 +149,15 @@ TabBar {
                     buttonRectOne.color = JamiTheme.backgroundColor
                 }
             }
+
+            Shortcut {
+                sequence: "Ctrl+L"
+                context: Qt.ApplicationShortcut
+                enabled: buttonRectOne.visible
+                onActivated: {
+                    buttonRectOne.showConversations()
+                }
+            }
         }
     }
 
@@ -184,6 +197,14 @@ TabBar {
             height: tabBar.height
             color: JamiTheme.backgroundColor
 
+            function showRequests() {
+                ConversationsAdapter.setConversationFilter("PENDING")
+                contactSearchBar.setPlaceholderString(
+                            JamiTheme.contactSearchBarPlaceHolderInivitionText)
+                pageTwo.down = true
+                pageOne.down = false
+            }
+
             Image {
                 id: imgRectTwo
                 anchors.horizontalCenter: buttonRectTwo.horizontalCenter
@@ -237,11 +258,7 @@ TabBar {
                 anchors.fill: parent
                 hoverEnabled: true
                 onPressed: {
-                    ConversationsAdapter.setConversationFilter("PENDING")
-                    contactSearchBar.setPlaceholderString(
-                                JamiTheme.contactSearchBarPlaceHolderInivitionText)
-                    pageTwo.down = true
-                    pageOne.down = false
+                    buttonRectTwo.showRequests()
                 }
                 onReleased: {
                     buttonRectTwo.color = JamiTheme.backgroundColor
@@ -253,6 +270,15 @@ TabBar {
                     buttonRectTwo.color = JamiTheme.backgroundColor
                 }
             }
+
+            Shortcut {
+                sequence: "Ctrl+R"
+                context: Qt.ApplicationShortcut
+                enabled: buttonRectTwo.visible
+                onActivated: {
+                    buttonRectTwo.showRequests()
+                }
+            }
         }
     }
 }
diff --git a/src/settingsview/SettingsView.qml b/src/settingsview/SettingsView.qml
index 45b358a95..d502c773f 100644
--- a/src/settingsview/SettingsView.qml
+++ b/src/settingsview/SettingsView.qml
@@ -188,6 +188,8 @@ Rectangle {
                         return pageIdAvSettingPage
                     case SettingsView.Plugin:
                         return pageIdPluginSettingsPage
+                    case SettingsView.Plugin:
+                        return pageIdPluginSettingsPage
                 }
             }
 
diff --git a/src/settingsview/components/KeyBoardShortcutKey.qml b/src/settingsview/components/KeyBoardShortcutKey.qml
new file mode 100644
index 000000000..c03c9719e
--- /dev/null
+++ b/src/settingsview/components/KeyBoardShortcutKey.qml
@@ -0,0 +1,27 @@
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+
+Item {
+    property alias text: shortcutText.text
+    Rectangle{
+        id: keyRect
+        width: t_metrics.tightBoundingRect.width + 10
+        height: t_metrics.tightBoundingRect.height + 10
+        color: "#525252"
+        radius: 5
+        anchors.centerIn: parent
+        Text {
+            id : shortcutText
+            anchors.centerIn: parent
+            anchors.leftMargin: 10
+            font.family: "Arial"
+            font.pointSize: 12
+            color: "white"
+        }
+        TextMetrics {
+            id:     t_metrics
+            font:   shortcutText.font
+            text:   shortcutText.text
+        }
+    }
+}
diff --git a/src/settingsview/components/KeyBoardShortcutTable.qml b/src/settingsview/components/KeyBoardShortcutTable.qml
new file mode 100644
index 000000000..d21789ca0
--- /dev/null
+++ b/src/settingsview/components/KeyBoardShortcutTable.qml
@@ -0,0 +1,619 @@
+/*
+ * Copyright (C) 2019-2020 by Savoir-faire Linux
+ * Author: Mingrui Zhang   <mingrui.zhang@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Layouts 1.3
+
+Dialog {
+    id: root
+    modal: true
+
+    width: rectangle.width + 24
+    height: rectangle.height + 24
+
+    Rectangle {
+        id: rectangle
+
+        property int minWidth: 1200
+        property int minHeight: 500
+
+        implicitWidth: minWidth
+        implicitHeight: minHeight
+        color: "white"
+        radius: 30
+
+        Rectangle {
+            width: 500
+            height: t_metrics_title.tightBoundingRect.height + 15
+            color: "#e0e0e0"
+            radius: 8
+            anchors.top: parent.top
+            anchors.topMargin: 10
+            anchors.horizontalCenter: parent.horizontalCenter
+            Text {
+                id : titleText
+                anchors.centerIn: parent
+                anchors.leftMargin: 10
+                font.family: "Arial"
+                font.pointSize: 12
+                font.bold: true
+                text: "Shortcuts"
+                color: "black"
+            }
+            TextMetrics {
+                id:     t_metrics_title
+                font:   titleText.font
+                text:   titleText.text
+            }
+        }
+
+        ListModel {
+            id: keyboardGeneralShortcutsModel
+            ListElement {
+                Shortcut: "Ctrl+J"
+                Description: qsTr("Open account list")
+                KeyLength: 2
+            }
+            ListElement {
+                Shortcut: "Ctrl+L"
+                Description: qsTr("Focus conversations list")
+                KeyLength: 2
+            }
+            ListElement {
+                Shortcut: "Ctrl+R"
+                Description: qsTr("Focus requests list")
+                KeyLength: 2
+            }
+            ListElement {
+                Shortcut: "Ctrl+↑"
+                Description: qsTr("Focus the previous conversation")
+                KeyLength: 2
+            }
+            ListElement {
+                Shortcut: "Ctrl+↓"
+                Description: qsTr("Focus the next conversation")
+                KeyLength: 2
+            }
+            ListElement {
+                Shortcut: "Ctrl+F"
+                Description: qsTr("Focus search bar")
+                KeyLength: 2
+            }
+            ListElement {
+                Shortcut: "F11"
+                Description: qsTr("Toggle fullscreen")
+                KeyLength: 1
+            }
+        }
+        ListModel {
+            id: keyboardConversationShortcutsModel
+            ListElement {
+                Shortcut: "Shift+Ctrl+C"
+                Description: qsTr("Start an audio call")
+                KeyLength: 3
+            }
+            ListElement {
+                Shortcut: "Shift+Ctrl+X"
+                Description: qsTr("Start an video call")
+                KeyLength: 3
+            }
+            ListElement {
+                Shortcut: "Shift+Ctrl+L"
+                Description: qsTr("Clear history")
+                KeyLength: 3
+            }
+            ListElement {
+                Shortcut: "Shift+Ctrl+B"
+                Description: qsTr("Block contact")
+                KeyLength: 3
+            }
+            ListElement {
+                Shortcut: "Shift+Ctrl+A"
+                Description: qsTr("Accept contact request")
+                KeyLength: 3
+            }
+        }
+        ListModel {
+            id: keyboardSettingsShortcutsModel
+            ListElement {
+                Shortcut: "Ctrl+M"
+                Description: qsTr("Toggle media settings")
+                KeyLength: 2
+            }
+            ListElement {
+                Shortcut: "Ctrl+G"
+                Description: qsTr("Toggle general settings")
+                KeyLength: 2
+            }
+            ListElement {
+                Shortcut: "Ctrl+I"
+                Description: qsTr("Toggle account settings")
+                KeyLength: 2
+            }
+            ListElement {
+                Shortcut: "Ctrl+Shift+N"
+                Description: qsTr("Open account creation's wizard")
+                KeyLength: 3
+            }
+            ListElement {
+                Shortcut: "F10"
+                Description: qsTr("Open this window")
+                KeyLength: 1
+            }
+        }
+        ListModel {
+            id: keyboardCallsShortcutsModel
+            ListElement {
+                Shortcut: "Ctrl+Y"
+                Description: qsTr("Answer an incoming call")
+                KeyLength: 2
+            }
+            ListElement {
+                Shortcut: "Ctrl+D"
+                Description: qsTr("Hangup current call")
+                KeyLength: 2
+            }
+            ListElement {
+                Shortcut: "Ctrl+Shift+D"
+                Description: qsTr("Decline the call request")
+                KeyLength: 2
+            }
+        }
+        Component {
+            id: shortcutDelegateWithThreeKeys
+
+            Rectangle {
+                id: cellRectWithThreeKeys
+
+                implicitWidth: minWidth /2
+                implicitHeight: 50
+                anchors.left: parent.left
+                anchors.leftMargin: 50
+                color: "white"
+                border.color: "white"
+                Rectangle {
+                    id: containerRectWithThreeKeys
+
+                    implicitWidth: parent.width - 10
+                    implicitHeight: 50
+                    anchors.horizontalCenter: parent.horizontalCenter
+                    anchors.verticalCenter: parent.verticalCenter
+
+                    Component.onCompleted: {
+                        var componentKeyOne = Qt.createComponent("KeyBoardShortcutKey.qml")
+                        if (componentKeyOne.status === Component.Ready) {
+                            var objectKeyOne = componentKeyOne.createObject(containerRectWithThreeKeys)
+                            objectKeyOne.anchors.verticalCenter = containerRectWithThreeKeys.verticalCenter
+                            objectKeyOne.anchors.left = containerRectWithThreeKeys.left
+                            objectKeyOne.text = Qt.binding(function() { return modelData.Shortcut.split("+")[0] })
+                        }
+                        if (modelData.Shortcut.split("+").length === 1)
+                            return
+                        var componentPlusSign = Qt.createQmlObject('import QtQuick 2.0;' +
+                                                                'Text {anchors.verticalCenter: containerRectWithThreeKeys.verticalCenter;' +
+                                                                'anchors.verticalCenterOffset: -2;' +
+                                                                'anchors.left: containerRectWithThreeKeys.left;' +
+                                                                'anchors.leftMargin: 30;' +
+                                                                'color: "#525252";' +
+                                                                'font.bold: true;' +
+                                                                'font.pointSize : 12;' +
+                                                                'text: "+"}',
+                                                                containerRectWithThreeKeys)
+
+                        var componentKeyTwo = Qt.createComponent("KeyBoardShortcutKey.qml")
+                        if (componentKeyTwo.status === Component.Ready) {
+                            var objectKeyTwo = componentKeyTwo.createObject(containerRectWithThreeKeys)
+                            objectKeyTwo.anchors.verticalCenter = containerRectWithThreeKeys.verticalCenter
+                            objectKeyTwo.anchors.left = containerRectWithThreeKeys.left
+                            objectKeyTwo.anchors.leftMargin = componentPlusSign.anchors.leftMargin + 42
+                            objectKeyTwo.text = Qt.binding(function() { return modelData.Shortcut.split("+")[1] })
+                        }
+
+                        if (modelData.Shortcut.split("+").length === 2)
+                            return
+                        var componentPlusSignTwo = Qt.createQmlObject('import QtQuick 2.0;' +
+                                                                    'Text {anchors.verticalCenter: containerRectWithThreeKeys.verticalCenter;' +
+                                                                    'anchors.verticalCenterOffset: -2;' +
+                                                                    'anchors.left: containerRectWithThreeKeys.left;' +
+                                                                    'anchors.leftMargin: 97;' +
+                                                                    'color: "#525252";' +
+                                                                    'font.bold: true;' +
+                                                                    'font.pointSize : 12;' +
+                                                                    'text: "+"}',
+                                                                    containerRectWithThreeKeys)
+
+                        var componentKeyThree = Qt.createComponent("KeyBoardShortcutKey.qml")
+                        if (componentKeyThree.status === Component.Ready) {
+                            var objectKeyThree = componentKeyThree.createObject(containerRectWithThreeKeys)
+                            objectKeyThree.anchors.verticalCenter = containerRectWithThreeKeys.verticalCenter
+                            objectKeyThree.anchors.left = containerRectWithThreeKeys.left
+                            objectKeyThree.anchors.leftMargin = componentPlusSignTwo.anchors.leftMargin + 35
+                            objectKeyThree.text = Qt.binding(function() { return modelData.Shortcut.split("+")[2] })
+                        }
+                    }
+                }
+            }
+        }
+        Component {
+            id: descriptionDelegate
+
+            Rectangle {
+                implicitWidth: minWidth /2
+                implicitHeight: 50
+
+                color: "white"
+                border.color: "white"
+                Text {
+                    id : descriptionText
+                    anchors.verticalCenter: parent.verticalCenter
+                    anchors.left: parent.left
+                    anchors.leftMargin: 10
+                    font.family: "Arial"
+                    font.pointSize: 10
+                    text: styleData.value
+                }
+            }
+        }
+
+        Column {
+            spacing: 2
+            id: columnAll
+            anchors.rightMargin: 20
+            anchors.leftMargin: 20
+            anchors.bottomMargin: 20
+            anchors.topMargin: 50
+
+            width: minWidth
+            height: minHeight - 100
+            anchors.fill: parent
+
+            StackLayout {
+                // pages
+                implicitWidth: parent.width
+                implicitHeight: parent.height - tabBar.height
+                currentIndex: tabBar.currentIndex
+                Item {
+                    id: tabOne
+                    Rectangle {
+                        implicitWidth: parent.width / 2
+                        implicitHeight: parent.height
+                        anchors.left: parent.left
+                        TableView {
+                            id: generalTableView
+                            anchors.fill: parent
+                            horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
+                            TableViewColumn {
+                                role: "Description"
+                                width: generalTableView.width / 2
+                                delegate: descriptionDelegate
+                            }
+                            TableViewColumn {
+                                role: "Shortcut"
+                                width: generalTableView.width / 2
+                                delegate: Component{
+                                    Loader {
+                                        property variant modelData: model
+                                        sourceComponent: shortcutDelegateWithThreeKeys
+                                    }
+                                }
+                            }
+                            model: keyboardGeneralShortcutsModel
+                            rowDelegate: Rectangle {
+                                height: 50
+                                color: "white"
+                            }
+                            style: TableViewStyle {
+                                alternateBackgroundColor: "white"
+                                frame: Rectangle {
+                                    border{
+                                        color: "transparent" // color of the border
+                                    }
+                                }
+                                headerDelegate: Rectangle {
+                                    // Only first column's header is shown
+                                    height: [t_metrics_general.tightBoundingRect.height + 10, 0][styleData.column % 2]
+                                    width: [parent.width, 0][styleData.column % 2]
+                                    color: "white"
+                                    radius: 10
+                                    anchors.top: parent.top
+                                    anchors.topMargin: 5
+                                    Text {
+                                        id : generalShortcutText
+                                        anchors.verticalCenter: parent.verticalCenter
+                                        anchors.left: parent.left
+                                        anchors.leftMargin: 10
+                                        font.family: "Arial"
+                                        font.pointSize: 12
+                                        text: styleData.column % 2 ? "" : "General"
+                                        color: "black"
+                                    }
+                                    TextMetrics {
+                                        id:     t_metrics_general
+                                        font:   generalShortcutText.font
+                                        text:   generalShortcutText.text
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    Rectangle {
+                        implicitWidth: parent.width / 2
+                        implicitHeight: parent.height
+                        anchors.right: parent.right
+
+                        TableView {
+                            id: conversationsTableView
+                            anchors.fill: parent
+                            horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
+                            TableViewColumn {
+                                role: "Description"
+                                width: conversationsTableView.width / 2
+                                delegate: descriptionDelegate
+                            }
+                            TableViewColumn {
+                                role: "Shortcut"
+                                width: conversationsTableView.width / 2
+                                delegate: Component{
+                                    Loader {
+                                        property variant modelData: model
+                                        sourceComponent: shortcutDelegateWithThreeKeys
+                                    }
+                                }
+                            }
+                            model: keyboardConversationShortcutsModel
+                            rowDelegate: Rectangle {
+                                height: 50
+                                color: "white"
+                            }
+                            style: TableViewStyle {
+                                alternateBackgroundColor: "white"
+                                frame: Rectangle {
+                                    border{
+                                        color: "transparent" // color of the border
+                                    }
+                                }
+                                headerDelegate: Rectangle {
+                                    // Only first column's header is shown
+                                    height: [t_metrics_conversations.tightBoundingRect.height + 10, 0][styleData.column % 2]
+                                    width: [parent.width, 0][styleData.column % 2]
+                                    color: "white"
+                                    radius: 10
+                                    anchors.top: parent.top
+                                    anchors.topMargin: 5
+                                    Text {
+                                        id : conversationsShortcutText
+                                        anchors.verticalCenter: parent.verticalCenter
+                                        anchors.left: parent.left
+                                        anchors.leftMargin: 10
+                                        font.family: "Arial"
+                                        font.pointSize: 12
+                                        text: styleData.column % 2 ? "" : "Conversations"
+                                        color: "black"
+                                    }
+                                    TextMetrics {
+                                        id:     t_metrics_conversations
+                                        font:   conversationsShortcutText.font
+                                        text:   conversationsShortcutText.text
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                Item {
+                    id: tabTwo
+                    Rectangle {
+                        implicitWidth: parent.width / 2
+                        implicitHeight: parent.height
+                        anchors.left: parent.left
+                        TableView {
+                            id: callsTableView
+                            anchors.fill: parent
+                            horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
+                            TableViewColumn {
+                                role: "Description"
+                                width: callsTableView.width / 2
+                                delegate: descriptionDelegate
+                            }
+                            TableViewColumn {
+                                role: "Shortcut"
+                                width: callsTableView.width / 2
+                                delegate: Component{
+                                    Loader {
+                                        property variant modelData: model
+                                        sourceComponent: shortcutDelegateWithThreeKeys
+                                    }
+                                }
+                            }
+                            model: keyboardCallsShortcutsModel
+                            rowDelegate: Rectangle {
+                                height: 50
+                                color: "white"
+                            }
+                            style: TableViewStyle {
+                                alternateBackgroundColor: "white"
+                                frame: Rectangle {
+                                    border{
+                                        color: "transparent" // color of the border
+                                    }
+                                }
+                                headerDelegate: Rectangle {
+                                    // Only first column's header is shown
+                                    height: [t_metrics_calls.tightBoundingRect.height + 10, 0][styleData.column % 2]
+                                    width: [parent.width, 0][styleData.column % 2]
+                                    color: "white"
+                                    radius: 10
+                                    anchors.top: parent.top
+                                    anchors.topMargin: 5
+                                    Text {
+                                        id : callsShortcutText
+                                        anchors.verticalCenter: parent.verticalCenter
+                                        anchors.left: parent.left
+                                        anchors.leftMargin: 10
+                                        font.family: "Arial"
+                                        font.pointSize: 12
+                                        text: styleData.column % 2 ? "" : "Calls"
+                                        color: "black"
+                                    }
+                                    // make sure that calls and settings header are parallel
+                                    TextMetrics {
+                                        id:     t_metrics_calls
+                                        font:   callsShortcutText.font
+                                        text:   "Settings"
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    Rectangle {
+                        implicitWidth: parent.width / 2
+                        implicitHeight: parent.height
+                        anchors.right: parent.right
+                        TableView {
+                            id: settingsTableView
+                            anchors.fill: parent
+                            horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
+                            TableViewColumn {
+                                role: "Description"
+                                width: settingsTableView.width / 2
+                                delegate: descriptionDelegate
+                            }
+                            TableViewColumn {
+                                role: "Shortcut"
+                                width: settingsTableView.width / 2
+                                delegate: Component{
+                                    Loader {
+                                        property variant modelData: model
+                                        sourceComponent: shortcutDelegateWithThreeKeys
+                                    }
+                                }
+                            }
+                            model: keyboardSettingsShortcutsModel
+                            rowDelegate: Rectangle {
+                                height: 50
+                                color: "white"
+                            }
+                            style: TableViewStyle {
+                                alternateBackgroundColor: "white"
+                                frame: Rectangle {
+                                    border{
+                                        color: "transparent" // color of the border
+                                    }
+                                }
+                                headerDelegate: Rectangle {
+                                    // Only first column's header is shown
+                                    height: [t_metrics_settings.tightBoundingRect.height + 10, 0][styleData.column % 2]
+                                    width: [parent.width, 0][styleData.column % 2]
+                                    color: "white"
+                                    radius: 10
+                                    anchors.top: parent.top
+                                    anchors.topMargin: 5
+                                    Text {
+                                        id : settingsShortcutText
+                                        anchors.verticalCenter: parent.verticalCenter
+                                        anchors.left: parent.left
+                                        anchors.leftMargin: 10
+                                        font.family: "Arial"
+                                        font.pointSize: 12
+                                        text: styleData.column % 2 ? "" : "Settings"
+                                        color: "black"
+                                    }
+                                    TextMetrics {
+                                        id:     t_metrics_settings
+                                        font:   settingsShortcutText.font
+                                        text:   settingsShortcutText.text
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        TabBar {
+            id: tabBar
+            anchors.horizontalCenter: parent.horizontalCenter
+            anchors.bottom: parent.bottom
+            anchors.bottomMargin: 15
+            width: 240
+            currentIndex: 0
+            TabButton {
+                id: pageOne
+                width: tabBar.width / 2
+                text: qsTr("1")
+                down: true
+                // customize tab button
+                contentItem: Text {
+                    text: pageOne.text
+                    font: pageOne.font
+                    opacity: enabled ? 1.0 : 0.3
+                    horizontalAlignment: Text.AlignHCenter
+                    verticalAlignment: Text.AlignVCenter
+                    elide: Text.ElideRight
+                }
+                // customize tab button
+                background: Rectangle {
+                    id: buttonRectOne
+                    implicitWidth: tabBar.width / 2
+                    implicitHeight: tabBar.height
+                    radius: 10
+                    color: pageOne.down ? "#e0e0e0" :"#fdfdfd"
+                    MouseArea {
+                        anchors.fill: parent
+                        hoverEnabled: true
+                        onPressed: { buttonRectOne.color = "#c0c0c0"; tabBar.currentIndex = 0; pageOne.down = true; pageTwo.down = false;}
+                        onReleased: { buttonRectOne.color = "#e0e0e0"; }
+                        onEntered: { buttonRectOne.color = "#c7c7c7"; }
+                        onExited: { buttonRectOne.color = Qt.binding(function() { return pageOne.down ? "#e0e0e0" :"#fdfdfd" }); }
+                    }
+                }
+            }
+            TabButton {
+                id: pageTwo
+                text: qsTr("2")
+                width: tabBar.width / 2
+                contentItem: Text {
+                    text: pageTwo.text
+                    font: pageTwo.font
+                    opacity: enabled ? 1.0 : 0.3
+                    horizontalAlignment: Text.AlignHCenter
+                    verticalAlignment: Text.AlignVCenter
+                    elide: Text.ElideRight
+                }
+
+                background: Rectangle {
+                    id: buttonRectTwo
+                    implicitWidth: tabBar.width / 2
+                    implicitHeight: tabBar.height
+                    radius: 10
+                    color: pageTwo.down ? "#e0e0e0" :"#fdfdfd"
+                    MouseArea {
+                        anchors.fill: parent
+                        hoverEnabled: true
+                        onPressed: { buttonRectTwo.color = "#c0c0c0"; tabBar.currentIndex = 1; pageTwo.down = true; pageOne.down = false;}
+                        onReleased: { buttonRectTwo.color = "#e0e0e0"; }
+                        onEntered: { buttonRectTwo.color = "#c7c7c7"; }
+                        onExited: { buttonRectTwo.color = Qt.binding(function() { return pageTwo.down ? "#e0e0e0" :"#fdfdfd" }); }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/src/utils.cpp b/src/utils.cpp
index 2723ff39d..edfbbef50 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -988,6 +988,18 @@ UtilsAdapter::getCurrAccId()
     return LRCInstance::getCurrAccId();
 }
 
+const QString
+UtilsAdapter::getCurrConvId()
+{
+    return LRCInstance::getCurrentConvUid();
+}
+
+void
+UtilsAdapter::makePermanentCurrentConv()
+{
+    LRCInstance::getCurrentConversationModel()->makePermanent(LRCInstance::getCurrentConvUid());
+}
+
 const QStringList
 UtilsAdapter::getCurrAccList()
 {
diff --git a/src/utils.h b/src/utils.h
index 4ffc5f283..584662f0d 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -497,6 +497,8 @@ public:
     Q_INVOKABLE const QString getBestId(const QString &accountId, const QString &uid);
 
     Q_INVOKABLE const QString getCurrAccId();
+    Q_INVOKABLE const QString getCurrConvId();
+    Q_INVOKABLE void makePermanentCurrentConv();
     Q_INVOKABLE const QStringList getCurrAccList();
     Q_INVOKABLE int getAccountListSize();
     Q_INVOKABLE void setCurrentCall(const QString &accountId, const QString &convUid);
-- 
GitLab