linphone-desktop/linphone-app/ui/views/App/Main/MainWindow.qml
Julien Wadel 59ea9c69e5 Make an option for displaying only usernames instead of the whole SIP address.
Move options button in waiting room because of readability.
Add a confirmation before calling a group from conversation.
Make an option to set RLS URI.
Avoid to close smart search bar when changing focus. It will now close only on empty text, esc keybutton or by manually closing it (cross icon when text has been entered)
Hide "adding contact" if search box is empty.
Add a switch in accounts selection to easily register them.
Update SDK to 5.2.81

# Conflicts:
#	linphone-app/src/components/search/SearchSipAddressesModel.cpp
#	linphone-sdk
2023-07-26 16:49:02 +02:00

463 lines
14 KiB
QML

import QtQuick 2.7
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import Qt.labs.platform 1.0
import Common 1.0
import Linphone 1.0
import Utils 1.0
import App.Styles 1.0
import ColorsList 1.0
import UtilsCpp 1.0
import 'MainWindow.js' as Logic
import 'qrc:/ui/scripts/Utils/utils.js' as Utils
// =============================================================================
ApplicationWindow {
id: window
property string _currentView
property var _lockedInfo
property SmartSearchBar mainSearchBar : (mainLoader.item ? mainLoader.item.mainSearchBar : null)
// ---------------------------------------------------------------------------
function lockView (info) {
Logic.lockView(info)
}
function unlockView () {
Logic.unlockView()
}
function setView (view, props, callback) {
Logic.setView(view, props, callback)
}
// ---------------------------------------------------------------------------
// Window properties.
// ---------------------------------------------------------------------------
minimumHeight: MainWindowStyle.minimumHeight
minimumWidth: MainWindowStyle.minimumWidth
title: Utils.capitalizeFirstLetter(applicationName)
// ---------------------------------------------------------------------------
onActiveFocusItemChanged: Logic.handleActiveFocusItemChanged(activeFocusItem)
onClosing: Logic.handleClosing(close)
// ---------------------------------------------------------------------------
Connections {
target: CoreManager
onCoreManagerInitialized: mainLoader.active = true
}
Shortcut {
sequence: StandardKey.Close
onActivated: window.hide()
}
// ---------------------------------------------------------------------------
Loader {
id: mainLoader
active: false
anchors.fill: parent
sourceComponent: ColumnLayout {
// Workaround to get these properties in `MainWindow.js`.
readonly property alias contactsEntry: contactsEntry
readonly property alias conferencesEntry: conferencesEntry
readonly property alias contentLoader: contentLoader
readonly property alias menu: menu
readonly property alias timeline: timeline
readonly property alias mainSearchBar: toolBar.mainSearchBar
spacing: 0
// -----------------------------------------------------------------------
AuthenticationNotifier {
onAuthenticationRequested: Logic.handleAuthenticationRequested(authInfo, realm, sipAddress, userId)
}
// -----------------------------------------------------------------------
// Toolbar properties.
// -----------------------------------------------------------------------
ToolBar {
id: toolBar
property alias mainSearchBar : smartSearchBar
Layout.fillWidth: true
Layout.preferredHeight: MainWindowStyle.toolBar.height
hoverEnabled : true
background: MainWindowStyle.toolBar.background
RowLayout {
anchors {
fill: parent
leftMargin: MainWindowStyle.toolBar.leftMargin
rightMargin: MainWindowStyle.toolBar.rightMargin
}
spacing: MainWindowStyle.toolBar.spacing
ActionButton {
icon: (leftPanel.visible?'panel_shown':'panel_hidden')
//: 'Hide Timeline' : Tooltip for a button that hide the timeline
tooltipText : (leftPanel.visible?qsTr('hideTimeline')
//: 'Open Timeline' : Tooltip for a button that open the timeline
:qsTr('openTimeline'))
iconSize: MainWindowStyle.panelButtonSize
//autoIcon: true
onClicked: leftPanel.visible = !leftPanel.visible
}
ActionButton {
id: home
isCustom: true
backgroundRadius: 4
colorSet: MainWindowStyle.buttons.home
//: 'Open Home' : Tooltip for a button that open the home view
tooltipText : qsTr('openHome')
//autoIcon: true
onClicked: setView('Home')
}
AccountStatus {
id: accountStatus
betterIcon:true
Layout.preferredHeight: parent.height
Layout.preferredWidth: MainWindowStyle.accountStatus.width
Layout.fillWidth: false
TooltipArea {
text: UtilsCpp.toDisplayString(AccountSettingsModel.sipAddress, SettingsModel.sipDisplayMode)
hoveringCursor: Qt.PointingHandCursor
}
onClicked: {
CoreManager.forceRefreshRegisters()
Logic.manageAccounts()
}
}
ColumnLayout {
Layout.preferredWidth: MainWindowStyle.autoAnswerStatus.width
visible: SettingsModel.autoAnswerStatus
Icon {
icon: SettingsModel.autoAnswerStatus
? 'auto_answer_custom'
: ''
iconSize: MainWindowStyle.autoAnswerStatus.iconSize
overwriteColor: MainWindowStyle.autoAnswerStatus.text.colorModel.color
}
Text {
clip: true
color: MainWindowStyle.autoAnswerStatus.text.colorModel.color
font {
bold: true
pointSize: MainWindowStyle.autoAnswerStatus.text.pointSize
}
text: qsTr('autoAnswerStatus')
visible: SettingsModel.autoAnswerStatus
width: parent.width
}
}
SmartSearchBar {
id: smartSearchBar
Layout.fillWidth: true
maxMenuHeight: MainWindowStyle.searchBox.maxHeight
placeholderText: qsTr('mainSearchBarPlaceholder')
tooltipText: qsTr('smartSearchBarTooltip')
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
onAddContact: window.setView('ContactEdit', {
sipAddress: sipAddress
})
onEntryClicked: {
if (SettingsModel.contactsEnabled) {
window.setView('ContactEdit', { sipAddress: entry.sipAddress })
} else {
CallsListModel.createChatRoom( '', false, [entry.sipAddress], true )
}
}
onLaunchCall: CallsListModel.launchAudioCall(sipAddress, '')
onLaunchChat: CallsListModel.launchChat( sipAddress,0 )
onLaunchSecureChat: CallsListModel.launchChat( sipAddress,1 )
onLaunchVideoCall: CallsListModel.launchVideoCall(sipAddress, '')
}
ActionButton {
isCustom: true
backgroundRadius: 90
colorSet: MainWindowStyle.buttons.telKeyad
onClicked: telKeypad.visible = !telKeypad.visible
toggled: telKeypad.visible
}
ActionButton {
Layout.leftMargin: 30
isCustom: true
backgroundRadius: 4
colorSet: MainWindowStyle.buttons.newChatGroup
//: 'Start a chat room' : Tooltip to illustrate a button
tooltipText : qsTr('newChatRoom')
visible: (SettingsModel.standardChatEnabled || SettingsModel.secureChatEnabled)
enabled: SettingsModel.groupChatEnabled
onClicked: {
window.detachVirtualWindow()
window.attachVirtualWindow(Qt.resolvedUrl('Dialogs/NewChatRoom.qml')
,{})
}
TooltipArea{
visible: !SettingsModel.groupChatEnabled
maxWidth: smartSearchBar.width
delay:0
//: 'Conference URI is not set. You have to change it in your account settings in order to create new group chats.' : Tooltip to warn the user to change a setting to activate an action.
text: qsTr('newChatRoomUriMissing')
}
}
ActionButton {
isCustom: true
backgroundRadius: 4
colorSet: MainWindowStyle.buttons.newConference
visible: SettingsModel.conferenceEnabled
enabled: SettingsModel.videoConferenceEnabled
tooltipText:qsTr('newConferenceButton')
onClicked: {
window.detachVirtualWindow()
window.attachVirtualWindow(Utils.buildAppDialogUri('NewConference')
,{}, function (status) {
if( status){
setView('Conferences')
}
})
}
TooltipArea{
visible: !SettingsModel.videoConferenceEnabled
maxWidth: smartSearchBar.width
delay:0
//: 'Video conference URI is not set. You have to change it in your account settings in order to create new meetings.' : Tooltip to warn the user to change a setting to activate an action.
text: qsTr('newConferenceUriMissing')
}
}
ActionButton {
isCustom: true
backgroundRadius: 4
colorSet: MainWindowStyle.buttons.burgerMenu
visible: Qt.platform.os !== 'osx'
toggled: menuBar.isOpenned
onClicked: toggled ? menuBar.close() : menuBar.open()// a bit useless as Menu will depopup on losing focus but this code is kept for giving idea
MainWindowMenuBar {
id: menuBar
onDisplayRecordings: {
timeline.model.unselectAll()
setView('Recordings')
}
}
}
}
}
// -----------------------------------------------------------------------
// Content.
// -----------------------------------------------------------------------
RowLayout {
Layout.fillHeight: true
Layout.fillWidth: true
spacing: 0
// Main menu.
ColumnLayout {
id:leftPanel
Layout.maximumWidth: MainWindowStyle.menu.width
Layout.preferredWidth: MainWindowStyle.menu.width
spacing: 0
ApplicationMenu {
id: menu
defaultSelectedEntry: null
entryHeight: MainWindowStyle.menu.height+10
entryWidth: MainWindowStyle.menu.width
ApplicationMenuEntry {
id: contactsEntry
icon: MainWindowStyle.menu.contacts.icon
iconSize: MainWindowStyle.menu.contacts.iconSize
overwriteColor: isSelected ? MainWindowStyle.menu.contacts.selectedColor.color : MainWindowStyle.menu.contacts.colorModel.color
name: LdapListModel.count > 0
//: 'Local contacts' : Contacts section label in main window when we have to specify that they are local to the application.
? qsTr('localContactsEntry').toUpperCase()
//: 'Contacts' : Contacts section label in main waindow.
: qsTr('contactsEntry').toUpperCase()
visible: SettingsModel.contactsEnabled
onSelected: {
ContactsListModel.update()
timeline.model.unselectAll()
setView('Contacts')
}
onClicked:{
ContactsListModel.update()
setView('Contacts')
}
Icon{
anchors.right:parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: 10
icon: MainWindowStyle.menu.direction.icon
overwriteColor: contactsEntry.overwriteColor
iconSize: MainWindowStyle.menu.direction.iconSize
}
}
ApplicationMenuEntry {
id: conferencesEntry
icon: MainWindowStyle.menu.conferences.icon
iconSize: MainWindowStyle.menu.conferences.iconSize
overwriteColor: isSelected ? MainWindowStyle.menu.conferences.selectedColor.color : MainWindowStyle.menu.conferences.colorModel.color
//: 'Meetings' : Meeting title for main window.
name: qsTr('mainWindowConferencesTitle').toUpperCase()
visible: SettingsModel.videoConferenceEnabled && SettingsModel.conferenceEnabled
onSelected: {
timeline.model.unselectAll()
setView('Conferences')
}
onClicked:{
setView('Conferences')
}
Icon{
anchors.right:parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: 10
icon: MainWindowStyle.menu.direction.icon
overwriteColor: conferencesEntry.overwriteColor
iconSize: MainWindowStyle.menu.direction.iconSize
}
}
}
// History.
Timeline {
id: timeline
Layout.fillHeight: true
Layout.fillWidth: true
model: TimelineProxyModel{
listSource: TimelineProxyModel.Main
onListSourceChanged: console.log("listSourceChanged")
}
onEntrySelected:{
if( entry ) {
if( entry.selected){
console.debug("Load conversation from entry selected on timeline")
window.setView('Conversation', {
chatRoomModel:entry.chatRoomModel
})
}
}else{
window.setView('Home', {})
}
menu.resetSelectedEntry()
}
onShowHistoryRequest: {
timeline.model.unselectAll()
window.setView('HistoryView')
}
}
}
// Main content.
Item{
Layout.fillHeight: true
Layout.fillWidth: true
Loader {
id: contentLoader
objectName: '__contentLoader'
anchors.fill: parent
source: 'Home.qml'
Component.onCompleted: if(accountStatus.noAccountConfigured) source= 'Assistant.qml' // default proxy = 1. Do not use this set diretly in source because of bindings that will override next setSource
}
TelKeypad {
anchors.right: parent.right
anchors.top: parent.top
id: telKeypad
onSendDtmf: smartSearchBar.text += dtmf
visible: SettingsModel.showTelKeypadAutomatically
}
}
}
}
}
Loader{
id: customMenuBar
active:Qt.platform.os === 'osx'
sourceComponent:MainWindowTopMenuBar{
onDisplayRecordings: {
if(mainLoader.item)
mainLoader.item.timeline.model.unselectAll()
setView('Recordings')
}
}
}
Component.onCompleted: if(Qt.platform.os === 'osx') menuBar = customMenuBar
// ---------------------------------------------------------------------------
// Url handlers.
// ---------------------------------------------------------------------------
Connections {
target: UrlHandlers
onSip: {
mainSearchBar.text = sipAddress
}
}
Connections{
target: App
onRequestFetchConfig: {
window.attachVirtualWindow(Utils.buildCommonDialogUri('ConfirmDialog'), {
flat: true,
//: 'Do you want to download and apply configuration from this URL?' : text to confirm to fetch a specified URL
descriptionText: '<b>'+qsTr('confirmFetchUri')
+'</b><br/><br/>'+filePath,
}, function (status) {
if (status) {
App.setFetchConfig(filePath)
}
})
}
}
}