-
Andreas Traczyk authored
- simplifies the settings menu - removes the IconButton component Gitlab: #14 Change-Id: Ib5cdc01dde47835befcdfa34aff35e5351a3b09d
Andreas Traczyk authored- simplifies the settings menu - removes the IconButton component Gitlab: #14 Change-Id: Ib5cdc01dde47835befcdfa34aff35e5351a3b09d
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
MainView.qml 20.94 KiB
/*
* Copyright (C) 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 <https://www.gnu.org/licenses/>.
*/
import QtQuick 2.14
import QtQuick.Window 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import QtQuick.Controls.Universal 2.12
import QtGraphicalEffects 1.14
import net.jami.Models 1.0
import net.jami.Adapters 1.0
// Import qml component files.
import "components"
import "../wizardview"
import "../settingsview"
import "../settingsview/components"
Window {
id: mainViewWindow
objectName: "mainViewWindow"
property int minWidth: settingsViewPreferredWidth
property int minHeight: 400
property int mainViewWindowPreferredWidth: 650
property int mainViewWindowPreferredHeight: 600
property int sidePanelViewStackPreferredWidth: 250
property int mainViewStackPreferredWidth: 250
property int settingsViewPreferredWidth: 445
property int onWidthChangedTriggerDistance: 5
property int savedSidePanelViewMinWidth: 0
property int savedSidePanelViewMaxWidth: 0
property int savedWelcomeViewMinWidth: 0
property int savedWelcomeViewMaxWidth: 0
property bool sidePanelOnly: !mainViewStack.visible
// To calculate tab bar bottom border hidden rect left margin.
property int tabBarLeftMargin: 8
property int tabButtonShrinkSize: 8
property bool inSettingsView: false
// For updating msgWebView
property string currentConvUID: ""
signal closeApp
signal noAccountIsAvailable
property string currentAccountId: AccountAdapter.currentAccountId
onCurrentAccountIdChanged: {
var index = UtilsAdapter.getCurrAccList().indexOf(currentAccountId)
mainViewWindowSidePanel.refreshAccountComboBox(index)
if (inSettingsView) {
settingsView.accountListChanged()
settingsView.setSelected(settingsView.selectedMenu, true)
} else {
backToMainView(true)
}
}
function isPageInStack(objectName, stackView) {
var foundItem = stackView.find(function (item, index) {
return item.objectName === objectName
})
return foundItem ? true : false
}
function showWelcomeView() {
currentConvUID = ""
callStackView.needToCloseInCallConversationAndPotentialWindow()
mainViewWindowSidePanel.deselectConversationSmartList()
if (isPageInStack("callStackViewObject", sidePanelViewStack) ||
isPageInStack("communicationPageMessageWebView", sidePanelViewStack) ||
isPageInStack("communicationPageMessageWebView", mainViewStack) ||
isPageInStack("callStackViewObject", mainViewStack)) {
sidePanelViewStack.pop(StackView.Immediate)
mainViewStack.pop(welcomePage, StackView.Immediate)
}
recordBox.visible = false
}
function pushCallStackView() {
if (sidePanelOnly) {
sidePanelViewStack.pop(StackView.Immediate)
sidePanelViewStack.push(callStackView, StackView.Immediate)
} else {
sidePanelViewStack.pop(StackView.Immediate)
mainViewStack.pop(welcomePage, StackView.Immediate)
mainViewStack.push(callStackView, StackView.Immediate)
}
}
function pushCommunicationMessageWebView() {
if (sidePanelOnly) {
sidePanelViewStack.pop(StackView.Immediate)
sidePanelViewStack.push(communicationPageMessageWebView, StackView.Immediate)
} else {
mainViewStack.pop(welcomePage, StackView.Immediate)
mainViewStack.push(communicationPageMessageWebView, StackView.Immediate)
}
}
function startWizard() {
mainViewStackLayout.currentIndex = 1
}
function currentAccountIsCalling() {
return UtilsAdapter.hasCall(AccountAdapter.currentAccountId)
}
// Only called onWidthChanged
function recursionStackViewItemMove(stackOne, stackTwo, depth=1) {
// Move all items (expect the bottom item) to stacktwo by the same order in stackone.
if (stackOne.depth === depth) {
return
}
var tempItem = stackOne.pop(StackView.Immediate)
recursionStackViewItemMove(stackOne, stackTwo, depth)
stackTwo.push(tempItem, StackView.Immediate)
}
// Back to WelcomeView required, but can also check, i. e., on account switch or
// settings exit, if there is need to switch to a current call
function backToMainView(checkCurrentCall = false) {
if (inSettingsView)
return
if (checkCurrentCall && currentAccountIsCalling()) {
var callConv = UtilsAdapter.getCallConvForAccount(
AccountAdapter.currentAccountId)
ConversationsAdapter.selectConversation(
AccountAdapter.currentAccountId, callConv)
} else {
showWelcomeView()
}
}
function toggleSettingsView() {
inSettingsView = !inSettingsView
if (inSettingsView) {
if (sidePanelOnly)
sidePanelViewStack.push(settingsMenu, StackView.Immediate)
else {
mainViewStack.pop(welcomePage, StackView.Immediate)
mainViewStack.push(settingsView, StackView.Immediate)
sidePanelViewStack.push(settingsMenu, StackView.Immediate)
var windowCurrentMinimizedSize = settingsViewPreferredWidth
+ sidePanelViewStackPreferredWidth + onWidthChangedTriggerDistance
if (mainViewWindow.width < windowCurrentMinimizedSize)
mainViewWindow.width = windowCurrentMinimizedSize
}
} else {
sidePanelViewStack.pop(StackView.Immediate)
mainViewStack.pop(StackView.Immediate)
backToMainView(true)
}
}
// ConversationSmartListViewItemDelegate provides UI information
function setMainView(currentUserDisplayName, currentUserAlias, currentUID,
callStackViewShouldShow, isAudioOnly, callState) {
if (!(communicationPageMessageWebView.jsLoaded)) {
communicationPageMessageWebView.jsLoadedChanged.connect(
function(currentUserDisplayName, currentUserAlias, currentUID,
callStackViewShouldShow, isAudioOnly, callState) {
return function() {
setMainView(currentUserDisplayName, currentUserAlias, currentUID,
callStackViewShouldShow, isAudioOnly, callState)
}
}(currentUserDisplayName, currentUserAlias, currentUID,
callStackViewShouldShow, isAudioOnly, callState))
return
}
if (callStackViewShouldShow) {
if (inSettingsView) {
toggleSettingsView()
}
MessagesAdapter.setupChatView(currentUID)
communicationPageMessageWebView.headerUserAliasLabelText = currentUserAlias
communicationPageMessageWebView.headerUserUserNameLabelText = currentUserDisplayName
callStackView.setLinkedWebview(communicationPageMessageWebView)
callStackView.responsibleAccountId = AccountAdapter.currentAccountId
callStackView.responsibleConvUid = currentUID
callStackView.updateCorrespondingUI()
if (callState === Call.Status.IN_PROGRESS || callState === Call.Status.PAUSED) {
UtilsAdapter.setCurrentCall(AccountAdapter.currentAccountId, currentUID)
if (isAudioOnly)
callStackView.showAudioCallPage()
else
callStackView.showVideoCallPage()
} else if (callState === Call.Status.INCOMING_RINGING) {
callStackView.showIncomingCallPage(AccountAdapter.currentAccountId,
currentUID)
} else {
callStackView.showOutgoingCallPage(callState)
}
pushCallStackView()
} else if (!inSettingsView) {
if (currentConvUID !== currentUID) {
callStackView.needToCloseInCallConversationAndPotentialWindow()
MessagesAdapter.setupChatView(currentUID)
communicationPageMessageWebView.headerUserAliasLabelText = currentUserAlias
communicationPageMessageWebView.headerUserUserNameLabelText = currentUserDisplayName
pushCommunicationMessageWebView()
communicationPageMessageWebView.focusMessageWebView()
currentConvUID = currentUID
} else if (isPageInStack("callStackViewObject", sidePanelViewStack)
|| isPageInStack("callStackViewObject", mainViewStack)) {
callStackView.needToCloseInCallConversationAndPotentialWindow()
pushCommunicationMessageWebView()
communicationPageMessageWebView.focusMessageWebView()
}
}
}
title: JamiStrings.appTitle
visible: true
width: mainViewWindowPreferredWidth
height: mainViewWindowPreferredHeight
minimumWidth: minWidth
minimumHeight: minHeight
Connections {
target: CallAdapter
// selectConversation causes UI update
function onCallSetupMainViewRequired(accountId, convUid) {
ConversationsAdapter.selectConversation(accountId, convUid)
}
}
StackLayout {
id: mainViewStackLayout
anchors.fill: parent
currentIndex: 0
SplitView {
id: splitView
Layout.fillWidth: true
Layout.fillHeight: true
width: mainViewWindow.width
height: mainViewWindow.height
handle: Rectangle {
implicitWidth: JamiTheme.splitViewHandlePreferredWidth
implicitHeight: splitView.height
color:"white"
Rectangle {
implicitWidth: 1
implicitHeight: splitView.height
color: SplitHandle.pressed ? JamiTheme.pressColor :
(SplitHandle.hovered ? JamiTheme.hoverColor :
JamiTheme.tabbarBorderColor)
}
}
Rectangle {
id: mainViewSidePanelRect
SplitView.minimumWidth: sidePanelViewStackPreferredWidth
SplitView.maximumWidth: (sidePanelOnly ? splitView.width :
splitView.width - sidePanelViewStackPreferredWidth)
SplitView.fillHeight: true
// AccountComboBox is always visible
AccountComboBox {
id: accountComboBox
anchors.top: mainViewSidePanelRect.top
width: mainViewSidePanelRect.width
height: 64
visible: (mainViewWindowSidePanel.visible || settingsMenu.visible)
currentIndex: 0
Connections {
target: AccountAdapter
function onUpdateConversationForAddedContact() {
MessagesAdapter.updateConversationForAddedContact()
mainViewWindowSidePanel.clearContactSearchBar()
mainViewWindowSidePanel.forceReselectConversationSmartListCurrentIndex()
}
function onAccountStatusChanged() {
accountComboBox.resetAccountListModel()
}
}
onSettingBtnClicked: {
toggleSettingsView()
}
Component.onCompleted: {
AccountAdapter.setQmlObject(this)
}
}
StackView {
id: sidePanelViewStack
initialItem: mainViewWindowSidePanel
anchors.top: accountComboBox.visible ? accountComboBox.bottom :
mainViewSidePanelRect.top
width: mainViewSidePanelRect.width
height: accountComboBox.visible ? mainViewSidePanelRect.height - accountComboBox.height :
mainViewSidePanelRect.height
clip: true
}
}
StackView {
id: mainViewStack
initialItem: welcomePage
SplitView.maximumWidth: sidePanelOnly ?
splitView.width :
splitView.width - sidePanelViewStackPreferredWidth
SplitView.minimumWidth: sidePanelViewStackPreferredWidth
SplitView.fillHeight: true
clip: true
}
}
WizardView {
id: wizardView
Layout.fillWidth: true
Layout.fillHeight: true
onNeedToShowMainViewWindow: {
mainViewStackLayout.currentIndex = 0
backToMainView()
}
onWizardViewIsClosed: {
mainViewStackLayout.currentIndex = 0
backToMainView()
}
}
}
AccountListModel {
id: accountListModel
}
SettingsMenu {
id: settingsMenu
objectName: "settingsMenu"
visible: false
width: mainViewSidePanelRect.width
height: mainViewSidePanelRect.height
onItemSelected: {
settingsView.setSelected(index)
if (sidePanelOnly)
sidePanelViewStack.push(settingsView, StackView.Immediate)
}
}
SidePanel {
id: mainViewWindowSidePanel
Connections {
target: ConversationsAdapter
function onNavigateToWelcomePageRequested() {
backToMainView()
}
}
}
CallStackView {
id: callStackView
visible: false
objectName: "callStackViewObject"
}
WelcomePage {
id: welcomePage
visible: false
}
SettingsView {
id: settingsView
visible: false
onSettingsViewWindowNeedToShowMainViewWindow: {
AccountAdapter.accountChanged(0)
toggleSettingsView()
}
onSettingsViewWindowNeedToShowNewWizardWindow: {
mainViewWindow.noAccountIsAvailable()
}
onSettingsBackArrowClicked: sidePanelViewStack.pop(StackView.Immediate)
}
MessageWebView {
id: communicationPageMessageWebView
objectName: "communicationPageMessageWebView"
signal toSendMessageContentSaved(string arg)
signal toMessagesCleared
signal toMessagesLoaded
visible: false
Connections {
target: MessagesAdapter
function onNeedToUpdateSmartList() {
mainViewWindowSidePanel.forceUpdateConversationSmartListView()
}
function onNavigateToWelcomePageRequested() {
backToMainView()
}
}
Component.onCompleted: {
recordBox.x = Qt.binding(function() {
var i = ((mainViewStack.visible && mainViewStack.width > 1000) ?
Math.round((mainViewStack.width-1000)*0.5) :
0)
return mainViewStack.visible ?
sidePanelViewStack.width + recordBox.x_offset + i :
recordBox.x_offset + i
})
recordBox.y = Qt.binding(function() {
return mainViewStack.visible ? mainViewStack.height + recordBox.y_offset :
sidePanelViewStack.height + recordBox.y_offset
})
// Set qml MessageWebView object pointer to c++.
MessagesAdapter.setQmlObject(this)
}
}
onWidthChanged: {
// Hide unnecessary stackview when width is changed.
var widthToCompare = sidePanelViewStackPreferredWidth +
(inSettingsView ? settingsViewPreferredWidth : mainViewStackPreferredWidth)
if (mainViewWindow.width < widthToCompare - onWidthChangedTriggerDistance
&& mainViewStack.visible) {
mainViewStack.visible = false
// The find callback function is called for each item in the stack.
var inWelcomeViewStack = mainViewStack.find(
function (item, index) {
return index > 0
})
if (inSettingsView) {
mainViewStack.pop(StackView.Immediate)
sidePanelViewStack.push(settingsView, StackView.Immediate)
}
else if (inWelcomeViewStack)
recursionStackViewItemMove(mainViewStack, sidePanelViewStack)
mainViewWindow.update()
} else if (mainViewWindow.width >= widthToCompare + onWidthChangedTriggerDistance
&& !mainViewStack.visible) {
mainViewStack.visible = true
var inSidePanelViewStack = sidePanelViewStack.find(
function (item, index) {
return index > 0
})
if (inSettingsView) {
if (sidePanelViewStack.currentItem.objectName !== settingsMenu.objectName)
sidePanelViewStack.pop(StackView.Immediate)
mainViewStack.push(settingsView, StackView.Immediate)
} else if (inSidePanelViewStack) {
recursionStackViewItemMove(sidePanelViewStack, mainViewStack)
if (currentAccountIsCalling())
pushCallStackView()
}
mainViewWindow.update()
}
}
AboutPopUp {
id: aboutPopUpDialog
}
WelcomePageQrDialog {
id: qrDialog
}
RecordBox{
id: recordBox
visible: false
}
UserProfile {
id: userProfile
}
onClosing: {
close.accepted = false
mainViewWindow.hide()
mainViewWindow.closeApp()
}
Shortcut {
sequence: "Ctrl+M"
context: Qt.ApplicationShortcut
onActivated: {
if (!inSettingsView) {
toggleSettingsView()
}
settingsMenu.btnMediaSettings.clicked()
}
}
Shortcut {
sequence: "Ctrl+G"
context: Qt.ApplicationShortcut
onActivated: {
if (!inSettingsView) {
toggleSettingsView()
}
settingsMenu.btnGeneralSettings.clicked()
}
}
Shortcut {
sequence: "Ctrl+I"
context: Qt.ApplicationShortcut
onActivated: {
if (!inSettingsView) {
toggleSettingsView()
}
settingsMenu.btnAccountSettings.clicked()
}
}
Shortcut {
sequence: "Ctrl+P"
context: Qt.ApplicationShortcut
onActivated: {
if (!inSettingsView) {
toggleSettingsView()
}
settingsMenu.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()
onActivatedAmbiguously: CallAdapter.hangUpThisCall()
}
Shortcut {
sequence: "Ctrl+Shift+A"
context: Qt.ApplicationShortcut
onActivated: {
UtilsAdapter.makePermanentCurrentConv()
communicationPageMessageWebView.setSendContactRequestButtonVisible(false)
}
}
Shortcut {
sequence: "Ctrl+Shift+N"
context: Qt.ApplicationShortcut
onActivated: startWizard()
}
KeyBoardShortcutTable {
id: shortcutsTable
}
}