asynchronous actions buttons to improve performances

This commit is contained in:
gaelle 2025-02-25 15:55:34 +01:00
parent 586dca5cd0
commit 3629732fde
5 changed files with 1298 additions and 1061 deletions

View file

@ -2,18 +2,14 @@ import QtQuick
import QtQuick.Controls.Basic as Control import QtQuick.Controls.Basic as Control
import QtQuick.Effects import QtQuick.Effects
import Linphone import Linphone
import 'qrc:/qt/qml/Linphone/view/Style/buttonStyle.js' as ButtonStyle import "qrc:/qt/qml/Linphone/view/Style/buttonStyle.js" as ButtonStyle
Button { Button {
id: mainItem id: mainItem
property alias popup: popup property alias popup: popup
property bool shadowEnabled: mainItem.activeFocus || hovered property bool shadowEnabled: mainItem.activeFocus || hovered
property alias popupBackgroundColor: popupBackground.color property alias popupBackgroundColor: popupBackground.color
property color backgroundColor: checked property color backgroundColor: checked ? pressedColor : hovered ? hoveredColor : color
? pressedColor
: hovered
? hoveredColor
: color
style: ButtonStyle.popupButton style: ButtonStyle.popupButton
checked: popup.visible checked: popup.visible
implicitWidth: 24 * DefaultStyle.dp implicitWidth: 24 * DefaultStyle.dp
@ -38,17 +34,26 @@ Button {
return item.activeFocusOnTab return item.activeFocusOnTab
} }
function getPreviousItem(index) { function getPreviousItem(index) {
return _getPreviousItem(popup.contentItem instanceof FocusScope ? popup.contentItem.children[0] : popup.contentItem, index) return _getPreviousItem(
popup.contentItem
instanceof FocusScope ? popup.contentItem.children[0] : popup.contentItem,
index)
} }
function getNextItem(index) { function getNextItem(index) {
return _getNextItem(popup.contentItem instanceof FocusScope ? popup.contentItem.children[0] : popup.contentItem, index) return _getNextItem(
popup.contentItem
instanceof FocusScope ? popup.contentItem.children[0] : popup.contentItem,
index)
} }
function _getPreviousItem(content, index) { function _getPreviousItem(content, index) {
if(content.visibleChildren.length == 0) return null if (content.visibleChildren.length == 0)
return null
--index --index
while (index >= 0) { while (index >= 0) {
if( isFocusable(content.children[index]) && content.children[index].visible) return content.children[index] if (isFocusable(content.children[index])
&& content.children[index].visible)
return content.children[index]
--index --index
} }
return _getPreviousItem(content, content.children.length) return _getPreviousItem(content, content.children.length)
@ -56,22 +61,27 @@ Button {
function _getNextItem(content, index) { function _getNextItem(content, index) {
++index ++index
while (index < content.children.length) { while (index < content.children.length) {
if( isFocusable(content.children[index]) && content.children[index].visible) return content.children[index] if (isFocusable(content.children[index])
&& content.children[index].visible)
return content.children[index]
++index ++index
} }
return _getNextItem(content, -1) return _getNextItem(content, -1)
} }
Keys.onPressed: (event) => { Keys.onPressed: event => {
if (mainItem.checked) { if (mainItem.checked) {
if( event.key == Qt.Key_Escape || event.key == Qt.Key_Left || event.key == Qt.Key_Space){ if (event.key == Qt.Key_Escape
|| event.key == Qt.Key_Left
|| event.key == Qt.Key_Space) {
mainItem.close() mainItem.close()
mainItem.forceActiveFocus() mainItem.forceActiveFocus()
event.accepted = true event.accepted = true
} else if (event.key == Qt.Key_Up) { } else if (event.key == Qt.Key_Up) {
getPreviousItem(0).forceActiveFocus() getPreviousItem(0).forceActiveFocus()
event.accepted = true event.accepted = true
}else if(event.key == Qt.Key_Tab || event.key == Qt.Key_Down){ } else if (event.key == Qt.Key_Tab
|| event.key == Qt.Key_Down) {
getNextItem(-1).forceActiveFocus() getNextItem(-1).forceActiveFocus()
event.accepted = true event.accepted = true
} }
@ -108,24 +118,39 @@ Button {
colorizationColor: mainItem.contentImageColor colorizationColor: mainItem.contentImageColor
} }
onPressed: { onPressed: {
if (popup.visible) popup.close() if (popup.visible)
else popup.open() popup.close()
else
popup.open()
} }
Control.Popup { Control.Popup {
id: popup id: popup
x: 0 x: 0
y: mainItem.height y: mainItem.height
closePolicy: Popup.CloseOnPressOutsideParent | Popup.CloseOnPressOutside | Popup.CloseOnEscape visible: false
closePolicy: Popup.CloseOnPressOutsideParent | Popup.CloseOnPressOutside
| Popup.CloseOnEscape
padding: 10 * DefaultStyle.dp padding: 10 * DefaultStyle.dp
parent: mainItem // Explicit define for coordinates references. parent: mainItem // Explicit define for coordinates references.
function updatePosition() { function updatePosition() {
if (!visible) return if (!visible)
return
var popupHeight = popup.height + popup.padding var popupHeight = popup.height + popup.padding
var popupWidth = popup.width + popup.padding var popupWidth = popup.width + popup.padding
var winPosition = mainItem.Window.contentItem ? mainItem.Window.contentItem.mapToItem(mainItem,0 , 0) : {x:0,y:0} var winPosition = mainItem.Window.contentItem ? mainItem.Window.contentItem.mapToItem(
mainItem, 0,
0) : {
"x": 0,
"y": 0
}
// Stay inside main window // Stay inside main window
y = Math.max( Math.min( winPosition.y + mainItem.Window.height - popupHeight, mainItem.height), winPosition.y) y = Math.max(Math.min(
x = Math.max( Math.min( winPosition.x + mainItem.Window.width - popupWidth, 0), winPosition.x) winPosition.y + mainItem.Window.height - popupHeight,
mainItem.height), winPosition.y)
x = Math.max(
Math.min(
winPosition.x + mainItem.Window.width - popupWidth,
0), winPosition.x)
// Avoid overlapping with popup button by going to the right (todo: check if left is better?) // Avoid overlapping with popup button by going to the right (todo: check if left is better?)
if (y < mainItem.height && y + popupHeight > 0) { if (y < mainItem.height && y + popupHeight > 0) {
x += mainItem.width x += mainItem.width
@ -138,8 +163,12 @@ Button {
Connections { Connections {
target: mainItem.Window target: mainItem.Window
function onHeightChanged(){ Qt.callLater(popup.updatePosition)} function onHeightChanged() {
function onWidthChanged(){ Qt.callLater(popup.updatePosition)} Qt.callLater(popup.updatePosition)
}
function onWidthChanged() {
Qt.callLater(popup.updatePosition)
}
} }
background: Item { background: Item {

View file

@ -5,8 +5,8 @@ import QtQuick.Controls.Basic as Control
import Linphone import Linphone
import UtilsCpp import UtilsCpp
import SettingsCpp import SettingsCpp
import 'qrc:/qt/qml/Linphone/view/Style/buttonStyle.js' as ButtonStyle import "qrc:/qt/qml/Linphone/view/Style/buttonStyle.js" as ButtonStyle
import 'qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js' as Utils import "qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js" as Utils
ListView { ListView {
id: mainItem id: mainItem
@ -17,7 +17,7 @@ ListView {
property string searchText: searchBar?.text property string searchText: searchBar?.text
property double busyIndicatorSize: 60 * DefaultStyle.dp property double busyIndicatorSize: 60 * DefaultStyle.dp
signal resultsReceived() signal resultsReceived
onResultsReceived: { onResultsReceived: {
loading = false loading = false
@ -29,7 +29,9 @@ ListView {
id: callHistoryProxy id: callHistoryProxy
filterText: mainItem.searchText filterText: mainItem.searchText
onFilterTextChanged: maxDisplayItems = initialDisplayItems onFilterTextChanged: maxDisplayItems = initialDisplayItems
initialDisplayItems: Math.max(20, 2 * mainItem.height / (56 * DefaultStyle.dp)) initialDisplayItems: Math.max(
20,
2 * mainItem.height / (56 * DefaultStyle.dp))
displayItemsStep: 3 * initialDisplayItems / 2 displayItemsStep: 3 * initialDisplayItems / 2
onModelReset: { onModelReset: {
mainItem.resultsReceived() mainItem.resultsReceived()
@ -38,7 +40,7 @@ ListView {
flickDeceleration: 10000 flickDeceleration: 10000
spacing: 10 * DefaultStyle.dp spacing: 10 * DefaultStyle.dp
Keys.onPressed: (event) => { Keys.onPressed: event => {
if (event.key == Qt.Key_Escape) { if (event.key == Qt.Key_Escape) {
console.log("Back") console.log("Back")
searchBar.forceActiveFocus() searchBar.forceActiveFocus()
@ -46,13 +48,17 @@ ListView {
} }
} }
Component.onCompleted: cacheBuffer = Math.max(contentHeight,0)//contentHeight>0 ? contentHeight : 0// cache all items Component.onCompleted: cacheBuffer = Math.max(
contentHeight,
0) //contentHeight>0 ? contentHeight : 0// cache all items
// remove binding loop // remove binding loop
onContentHeightChanged: Qt.callLater(function () { onContentHeightChanged: Qt.callLater(function () {
if (mainItem) mainItem.cacheBuffer = Math?.max(contentHeight,0) || 0 if (mainItem)
mainItem.cacheBuffer = Math?.max(contentHeight, 0) || 0
}) })
onActiveFocusChanged: if(activeFocus && currentIndex < 0 && count > 0) currentIndex = 0 onActiveFocusChanged: if (activeFocus && currentIndex < 0 && count > 0)
currentIndex = 0
onCountChanged: { onCountChanged: {
if (currentIndex < 0 && count > 0) { if (currentIndex < 0 && count > 0) {
mainItem.currentIndex = 0 // Select first item after loading model mainItem.currentIndex = 0 // Select first item after loading model
@ -93,11 +99,11 @@ ListView {
alwaysRunToEnd: true alwaysRunToEnd: true
} }
} }
//---------------------------------------------------------------- //----------------------------------------------------------------
onVisibleChanged: { onVisibleChanged: {
if (!visible) currentIndex = -1 if (!visible)
currentIndex = -1
} }
// Qt bug: sometimes, containsMouse may not be send and update on each MouseArea. // Qt bug: sometimes, containsMouse may not be send and update on each MouseArea.
@ -115,7 +121,8 @@ ListView {
spacing: 10 * DefaultStyle.dp spacing: 10 * DefaultStyle.dp
Avatar { Avatar {
id: historyAvatar id: historyAvatar
property var contactObj: UtilsCpp.findFriendByAddress(modelData.core.remoteAddress) property var contactObj: UtilsCpp.findFriendByAddress(
modelData.core.remoteAddress)
contact: contactObj?.value || null contact: contactObj?.value || null
displayNameVal: modelData.core.displayName displayNameVal: modelData.core.displayName
secured: securityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified secured: securityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
@ -144,29 +151,29 @@ ListView {
EffectImage { EffectImage {
id: statusIcon id: statusIcon
imageSource: modelData.core.status === LinphoneEnums.CallStatus.Declined imageSource: modelData.core.status === LinphoneEnums.CallStatus.Declined
|| modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere || modelData.core.status
=== LinphoneEnums.CallStatus.DeclinedElsewhere
|| modelData.core.status === LinphoneEnums.CallStatus.Aborted || modelData.core.status === LinphoneEnums.CallStatus.Aborted
|| modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted || modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted ? AppIcons.arrowElbow : modelData.core.isOutgoing ? AppIcons.arrowUpRight : AppIcons.arrowDownLeft
? AppIcons.arrowElbow colorizationColor: modelData.core.status
: modelData.core.isOutgoing === LinphoneEnums.CallStatus.Declined
? AppIcons.arrowUpRight || modelData.core.status
: AppIcons.arrowDownLeft === LinphoneEnums.CallStatus.DeclinedElsewhere
colorizationColor: modelData.core.status === LinphoneEnums.CallStatus.Declined || modelData.core.status
|| modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere === LinphoneEnums.CallStatus.Aborted
|| modelData.core.status === LinphoneEnums.CallStatus.Aborted || modelData.core.status
|| modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted === LinphoneEnums.CallStatus.EarlyAborted
|| modelData.core.status === LinphoneEnums.CallStatus.Missed || modelData.core.status === LinphoneEnums.CallStatus.Missed ? DefaultStyle.danger_500main : modelData.core.isOutgoing ? DefaultStyle.info_500_main : DefaultStyle.success_500main
? DefaultStyle.danger_500main
: modelData.core.isOutgoing
? DefaultStyle.info_500_main
: DefaultStyle.success_500main
Layout.preferredWidth: 12 * DefaultStyle.dp Layout.preferredWidth: 12 * DefaultStyle.dp
Layout.preferredHeight: 12 * DefaultStyle.dp Layout.preferredHeight: 12 * DefaultStyle.dp
transform: Rotation { transform: Rotation {
angle: modelData.core.isOutgoing && (modelData.core.status === LinphoneEnums.CallStatus.Declined angle: modelData.core.isOutgoing
|| modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere && (modelData.core.status === LinphoneEnums.CallStatus.Declined
|| modelData.core.status
=== LinphoneEnums.CallStatus.DeclinedElsewhere
|| modelData.core.status === LinphoneEnums.CallStatus.Aborted || modelData.core.status === LinphoneEnums.CallStatus.Aborted
|| modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted) ? 180 : 0 || modelData.core.status
=== LinphoneEnums.CallStatus.EarlyAborted) ? 180 : 0
origin { origin {
x: statusIcon.width / 2 x: statusIcon.width / 2
y: statusIcon.height / 2 y: statusIcon.height / 2
@ -191,10 +198,10 @@ ListView {
onClicked: { onClicked: {
if (modelData.core.isConference) { if (modelData.core.isConference) {
var callsWindow = UtilsCpp.getCallsWindow() var callsWindow = UtilsCpp.getCallsWindow()
callsWindow.setupConference(modelData.core.conferenceInfo) callsWindow.setupConference(
modelData.core.conferenceInfo)
UtilsCpp.smartShowWindow(callsWindow) UtilsCpp.smartShowWindow(callsWindow)
} } else {
else {
UtilsCpp.createCall(modelData.core.remoteAddress) UtilsCpp.createCall(modelData.core.remoteAddress)
} }
} }
@ -214,8 +221,10 @@ ListView {
anchors.fill: parent anchors.fill: parent
opacity: 0.7 opacity: 0.7
radius: 8 * DefaultStyle.dp radius: 8 * DefaultStyle.dp
color: mainItem.currentIndex === index ? DefaultStyle.main2_200 : DefaultStyle.main2_100 color: mainItem.currentIndex
visible: mainItem.lastMouseContainsIndex === index || mainItem.currentIndex === index === index ? DefaultStyle.main2_200 : DefaultStyle.main2_100
visible: mainItem.lastMouseContainsIndex === index
|| mainItem.currentIndex === index
} }
onPressed: { onPressed: {
mainItem.currentIndex = model.index mainItem.currentIndex = model.index

View file

@ -6,7 +6,7 @@ import Linphone
import UtilsCpp 1.0 import UtilsCpp 1.0
import ConstantsCpp 1.0 import ConstantsCpp 1.0
import SettingsCpp import SettingsCpp
import 'qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js' as Utils import "qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js" as Utils
Flickable { Flickable {
id: mainItem id: mainItem
@ -26,7 +26,8 @@ Flickable {
property bool selectionEnabled: true // Contact can be selected property bool selectionEnabled: true // Contact can be selected
property bool multiSelectionEnabled: false //Multiple items can be selected. property bool multiSelectionEnabled: false //Multiple items can be selected.
property list<string> selectedContacts // List of default address on selected contacts. property list<string> selectedContacts
// List of default address on selected contacts.
//property FriendGui selectedContact//: model.getAt(currentIndex) || null //property FriendGui selectedContact//: model.getAt(currentIndex) || null
property FriendGui highlightedContact property FriendGui highlightedContact
@ -38,7 +39,8 @@ Flickable {
// set searchBarText without specifying a model to bold // set searchBarText without specifying a model to bold
// matching names // matching names
property string searchBarText property string searchBarText
property string searchText// Binding is done on searchBarTextChanged property string searchText
// Binding is done on searchBarTextChanged
property ConferenceInfoGui confInfoGui property ConferenceInfoGui confInfoGui
property bool haveFavorites: false property bool haveFavorites: false
@ -54,19 +56,19 @@ Flickable {
contentHeight: contentsLayout.height contentHeight: contentsLayout.height
rightMargin: itemsRightMargin rightMargin: itemsRightMargin
signal contactStarredChanged() signal contactStarredChanged
signal contactDeletionRequested(FriendGui contact) signal contactDeletionRequested(FriendGui contact)
signal contactAddedToSelection(string address) signal contactAddedToSelection(string address)
signal contactRemovedFromSelection(string address) signal contactRemovedFromSelection(string address)
signal contactSelected(FriendGui contact) signal contactSelected(FriendGui contact)
function selectContact(address) { function selectContact(address) {
var index = contactsProxy.loadUntil(address)// Be sure to have this address in proxy if it exists var index = contactsProxy.loadUntil(
address) // Be sure to have this address in proxy if it exists
if (index != -1) { if (index != -1) {
contactsList.selectIndex(index) contactsList.selectIndex(index)
} }
return index return index
} }
function addContactToSelection(address) { function addContactToSelection(address) {
if (multiSelectionEnabled) { if (multiSelectionEnabled) {
@ -104,16 +106,26 @@ Flickable {
} }
function findNextList(item, count, direction) { function findNextList(item, count, direction) {
if(count == 3) return null if (count == 3)
return null
var nextItem var nextItem
switch (item) { switch (item) {
case suggestionsList:nextItem=(direction > 0 ? favoritesList : contactsList);break; case suggestionsList:
case contactsList:nextItem=(direction > 0 ? suggestionsList : favoritesList);break; nextItem = (direction > 0 ? favoritesList : contactsList)
case favoritesList:nextItem=(direction > 0 ? contactsList : suggestionsList);break; break
default: return null case contactsList:
nextItem = (direction > 0 ? suggestionsList : favoritesList)
break
case favoritesList:
nextItem = (direction > 0 ? contactsList : suggestionsList)
break
default:
return null
} }
if( nextItem.model.count > 0) return nextItem if (nextItem.model.count > 0)
else return findNextList(nextItem, count+1, direction) return nextItem
else
return findNextList(nextItem, count + 1, direction)
} }
function updatePosition(list) { function updatePosition(list) {
@ -142,17 +154,27 @@ Flickable {
loading = true loading = true
} }
Keys.onPressed: (event)=> { Keys.onPressed: event => {
if (!event.accepted) { if (!event.accepted) {
if(event.key == Qt.Key_Up || event.key == Qt.Key_Down){ if (event.key == Qt.Key_Up
|| event.key == Qt.Key_Down) {
var newItem var newItem
var direction = (event.key == Qt.Key_Up ? -1 : 1) var direction = (event.key == Qt.Key_Up ? -1 : 1)
if(suggestionsList.activeFocus) newItem = findNextList(suggestionsList, 0, direction) if (suggestionsList.activeFocus)
else if(contactsList.activeFocus) newItem = findNextList(contactsList, 0, direction) newItem = findNextList(suggestionsList, 0,
else if(favoritesList.activeFocus) newItem = findNextList(favoritesList, 0, direction) direction)
else newItem = findNextList(suggestionsList, 0, direction) else if (contactsList.activeFocus)
newItem = findNextList(contactsList, 0,
direction)
else if (favoritesList.activeFocus)
newItem = findNextList(favoritesList, 0,
direction)
else
newItem = findNextList(suggestionsList, 0,
direction)
if (newItem) { if (newItem) {
newItem.selectIndex(direction > 0 ? -1 : newItem.model.count - 1) newItem.selectIndex(
direction > 0 ? -1 : newItem.model.count - 1)
event.accepted = true event.accepted = true
} }
} }
@ -161,7 +183,8 @@ Flickable {
Component.onCompleted: { Component.onCompleted: {
if (confInfoGui) { if (confInfoGui) {
for (var i = 0; i < confInfoGui.core.participants.length; ++i) { for (var i = 0; i < confInfoGui.core.participants.length; ++i) {
selectedContacts.push(confInfoGui.core.getParticipantAddressAt(i)); selectedContacts.push(
confInfoGui.core.getParticipantAddressAt(i))
} }
} }
} }
@ -181,7 +204,6 @@ Flickable {
sourceFlags: mainItem.sourceFlags sourceFlags: mainItem.sourceFlags
onModelReset: { onModelReset: {
mainItem.resetSelections() mainItem.resetSelections()
} }
onResultsProcessed: { onResultsProcessed: {
mainItem.loading = false mainItem.loading = false
@ -197,8 +219,11 @@ Flickable {
} }
onAtYEndChanged: if (atYEnd) { onAtYEndChanged: if (atYEnd) {
if( (contactsProxy.haveMore && contactList.expanded ) || mainItem.hideSuggestions) contactsProxy.displayMore() if ((contactsProxy.haveMore && contactList.expanded)
else suggestionsProxy.displayMore() || mainItem.hideSuggestions)
contactsProxy.displayMore()
else
suggestionsProxy.displayMore()
} }
Behavior on contentY { Behavior on contentY {
NumberAnimation { NumberAnimation {
@ -252,19 +277,29 @@ Flickable {
itemsRightMargin: mainItem.itemsRightMargin itemsRightMargin: mainItem.itemsRightMargin
onHighlightedContactChanged: mainItem.highlightedContact = highlightedContact onHighlightedContactChanged: mainItem.highlightedContact = highlightedContact
onContactSelected: (contactGui) => { onContactSelected: contactGui => {
mainItem.contactSelected(contactGui) mainItem.contactSelected(contactGui)
} }
onUpdatePosition: mainItem.updatePosition(favoritesList) onUpdatePosition: mainItem.updatePosition(favoritesList)
onContactDeletionRequested: (contact) => {mainItem.contactDeletionRequested(contact)} onContactDeletionRequested: contact => {
onAddContactToSelection: (address) => {mainItem.addContactToSelection(address)} mainItem.contactDeletionRequested(
onRemoveContactFromSelection: (index) => {mainItem.removeContactFromSelection(index)} contact)
}
onAddContactToSelection: address => {
mainItem.addContactToSelection(address)
}
onRemoveContactFromSelection: index => {
mainItem.removeContactFromSelection(
index)
}
property MagicSearchProxy proxy: MagicSearchProxy { property MagicSearchProxy proxy: MagicSearchProxy {
parentProxy: mainItem.mainModel parentProxy: mainItem.mainModel
filterType: MagicSearchProxy.FilteringTypes.Favorites filterType: MagicSearchProxy.FilteringTypes.Favorites
} }
model : mainItem.showFavorites && (mainItem.searchBarText == ''|| mainItem.searchBarText == '*')? proxy : [] model: mainItem.showFavorites
&& (mainItem.searchBarText == ''
|| mainItem.searchBarText == '*') ? proxy : []
} }
ContactListView { ContactListView {
@ -286,22 +321,34 @@ Flickable {
title: qsTr('Contacts') title: qsTr('Contacts')
onHighlightedContactChanged: mainItem.highlightedContact = highlightedContact onHighlightedContactChanged: mainItem.highlightedContact = highlightedContact
onContactSelected: (contactGui) => { onContactSelected: contactGui => {
mainItem.contactSelected(contactGui) mainItem.contactSelected(contactGui)
} }
onUpdatePosition: mainItem.updatePosition(contactsList) onUpdatePosition: mainItem.updatePosition(contactsList)
onContactDeletionRequested: (contact) => {mainItem.contactDeletionRequested(contact)} onContactDeletionRequested: contact => {
onAddContactToSelection: (address) => {mainItem.addContactToSelection(address)} mainItem.contactDeletionRequested(
onRemoveContactFromSelection: (index) => {mainItem.removeContactFromSelection(index)} contact)
}
onAddContactToSelection: address => {
mainItem.addContactToSelection(address)
}
onRemoveContactFromSelection: index => {
mainItem.removeContactFromSelection(
index)
}
model: MagicSearchProxy { model: MagicSearchProxy {
id: contactsProxy id: contactsProxy
parentProxy: mainItem.mainModel parentProxy: mainItem.mainModel
filterType: MagicSearchProxy.FilteringTypes.App filterType: MagicSearchProxy.FilteringTypes.App
| (mainItem.searchText != '*' && mainItem.searchText != '' || SettingsCpp.syncLdapContacts ? MagicSearchProxy.FilteringTypes.Ldap | MagicSearchProxy.FilteringTypes.CardDAV: 0) | (mainItem.searchText != '*'
initialDisplayItems: Math.max(20, 2 * mainItem.height / (63 * DefaultStyle.dp)) && mainItem.searchText != ''
|| SettingsCpp.syncLdapContacts ? MagicSearchProxy.FilteringTypes.Ldap | MagicSearchProxy.FilteringTypes.CardDAV : 0)
initialDisplayItems: Math.max(
20,
2 * mainItem.height / (63 * DefaultStyle.dp))
displayItemsStep: 3 * initialDisplayItems / 2 displayItemsStep: 3 * initialDisplayItems / 2
onLocalFriendCreated: (index) => { onLocalFriendCreated: index => {
contactsList.selectIndex(index) contactsList.selectIndex(index)
} }
} }
@ -311,7 +358,8 @@ Flickable {
visible: contentHeight > 0 visible: contentHeight > 0
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: implicitHeight Layout.preferredHeight: implicitHeight
Layout.topMargin: contactsList.height + favoritesList.height > 0 ? 4 * DefaultStyle.dp : 0 Layout.topMargin: contactsList.height + favoritesList.height
> 0 ? 4 * DefaultStyle.dp : 0
interactive: false interactive: false
showInitials: false showInitials: false
highlightText: mainItem.highlightText highlightText: mainItem.highlightText
@ -325,18 +373,30 @@ Flickable {
itemsRightMargin: mainItem.itemsRightMargin itemsRightMargin: mainItem.itemsRightMargin
onHighlightedContactChanged: mainItem.highlightedContact = highlightedContact onHighlightedContactChanged: mainItem.highlightedContact = highlightedContact
onContactSelected: (contactGui) => { onContactSelected: contactGui => {
mainItem.contactSelected(contactGui) mainItem.contactSelected(contactGui)
} }
onUpdatePosition: mainItem.updatePosition(suggestionsList) onUpdatePosition: mainItem.updatePosition(suggestionsList)
onContactDeletionRequested: (contact) => {mainItem.contactDeletionRequested(contact)} onContactDeletionRequested: contact => {
onAddContactToSelection: (address) => {mainItem.addContactToSelection(address)} mainItem.contactDeletionRequested(
onRemoveContactFromSelection: (index) => {mainItem.removeContactFromSelection(index)} contact)
}
onAddContactToSelection: address => {
mainItem.addContactToSelection(address)
}
onRemoveContactFromSelection: index => {
mainItem.removeContactFromSelection(
index)
}
model: MagicSearchProxy { model: MagicSearchProxy {
id: suggestionsProxy id: suggestionsProxy
parentProxy: mainItem.mainModel parentProxy: mainItem.mainModel
filterType: mainItem.hideSuggestions ? MagicSearchProxy.FilteringTypes.None : MagicSearchProxy.FilteringTypes.Other filterType: mainItem.hideSuggestions ? MagicSearchProxy.FilteringTypes.None : MagicSearchProxy.FilteringTypes.Other
initialDisplayItems: contactsProxy.haveMore && contactsList.expanded ? 0 : Math.max(20, 2 * mainItem.height / (63 * DefaultStyle.dp)) initialDisplayItems: contactsProxy.haveMore
&& contactsList.expanded ? 0 : Math.max(
20,
2 * mainItem.height
/ (63 * DefaultStyle.dp))
onInitialDisplayItemsChanged: maxDisplayItems = initialDisplayItems onInitialDisplayItemsChanged: maxDisplayItems = initialDisplayItems
displayItemsStep: 3 * initialDisplayItems / 2 displayItemsStep: 3 * initialDisplayItems / 2
onModelReset: maxDisplayItems = initialDisplayItems onModelReset: maxDisplayItems = initialDisplayItems

View file

@ -6,7 +6,7 @@ import Linphone
import UtilsCpp 1.0 import UtilsCpp 1.0
import ConstantsCpp 1.0 import ConstantsCpp 1.0
import SettingsCpp import SettingsCpp
import 'qrc:/qt/qml/Linphone/view/Style/buttonStyle.js' as ButtonStyle import "qrc:/qt/qml/Linphone/view/Style/buttonStyle.js" as ButtonStyle
FocusScope { FocusScope {
id: mainItem id: mainItem
@ -16,21 +16,25 @@ FocusScope {
property bool showDefaultAddress: true // Display address below display name. property bool showDefaultAddress: true // Display address below display name.
property bool showActions: false // Display actions layout (call buttons) property bool showActions: false // Display actions layout (call buttons)
property bool showContactMenu: true // Display the dot menu for contacts. property bool showContactMenu: true // Display the dot menu for contacts.
property string highlightText // Bold characters in Display name. property string highlightText
// Bold characters in Display name.
property bool displayNameCapitalization: true // Capitalize display name. property bool displayNameCapitalization: true // Capitalize display name.
property bool selectionEnabled: true // Contact can be selected property bool selectionEnabled: true // Contact can be selected
property bool multiSelectionEnabled: false //Multiple items can be selected. property bool multiSelectionEnabled: false //Multiple items can be selected.
property list<string> selectedContacts // List of default address on selected contacts. property list<string> selectedContacts
// List of default address on selected contacts.
property bool isSelected: false // selected in list => currentIndex == index property bool isSelected: false // selected in list => currentIndex == index
property bool isLastHovered: false property bool isLastHovered: false
property var previousInitial // Use directly previous initial property var previousInitial
// Use directly previous initial
property int itemsRightMargin: 39 * DefaultStyle.dp property int itemsRightMargin: 39 * DefaultStyle.dp
property var displayName: searchResultItem.core.fullName property var displayName: searchResultItem.core.fullName
property string initial: displayName ? displayName[0].toLocaleLowerCase(ConstantsCpp.DefaultLocale) : '' property string initial: displayName ? displayName[0].toLocaleLowerCase(
ConstantsCpp.DefaultLocale) : ''
signal clicked(var mouse) signal clicked(var mouse)
signal contactDeletionRequested(FriendGui contact) signal contactDeletionRequested(FriendGui contact)
@ -72,11 +76,14 @@ FocusScope {
ColumnLayout { ColumnLayout {
spacing: 0 spacing: 0
Text { Text {
text: UtilsCpp.boldTextPart(mainItem.displayName, mainItem.highlightText) text: UtilsCpp.boldTextPart(mainItem.displayName,
mainItem.highlightText)
font { font {
pixelSize: mainItem.showDefaultAddress ? 16 * DefaultStyle.dp : 14 * DefaultStyle.dp pixelSize: mainItem.showDefaultAddress ? 16 * DefaultStyle.dp : 14
* DefaultStyle.dp
capitalization: mainItem.displayNameCapitalization ? Font.Capitalize : Font.MixedCase capitalization: mainItem.displayNameCapitalization ? Font.Capitalize : Font.MixedCase
weight: mainItem.showDefaultAddress ? 800 * DefaultStyle.dp : 400 * DefaultStyle.dp weight: mainItem.showDefaultAddress ? 800 * DefaultStyle.dp : 400
* DefaultStyle.dp
} }
maximumLineCount: 1 maximumLineCount: 1
Layout.fillWidth: true Layout.fillWidth: true
@ -95,16 +102,27 @@ FocusScope {
} }
} }
} }
Item{Layout.fillWidth: true} Item {
RowLayout { Layout.fillWidth: true
}
Loader {
id: buttonsLayoutLoader
asynchronous: true
active: mainItem.showActions || mainItem.showContactMenu
|| mainItem.multiSelectionEnabled
Layout.rightMargin: active ? 10 * DefaultStyle.dp : 0
sourceComponent: RowLayout {
id: actionsRow id: actionsRow
z: 1 z: 1
visible: actionButtons || friendPopup.visible || mainItem.multiSelectionEnabled visible: actionButtons.visible || friendPopup.visible
|| mainItem.multiSelectionEnabled
spacing: visible ? 16 * DefaultStyle.dp : 0 spacing: visible ? 16 * DefaultStyle.dp : 0
Layout.rightMargin: visible ? 10 * DefaultStyle.dp : 0 enabled: visible
EffectImage { EffectImage {
id: isSelectedCheck id: isSelectedCheck
visible: mainItem.multiSelectionEnabled && (mainItem.selectedContacts.indexOf(searchResultItem.core.defaultAddress) != -1) visible: mainItem.multiSelectionEnabled
&& (mainItem.selectedContacts.indexOf(
searchResultItem.core.defaultAddress) != -1)
Layout.preferredWidth: 24 * DefaultStyle.dp Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp Layout.preferredHeight: 24 * DefaultStyle.dp
imageSource: AppIcons.check imageSource: AppIcons.check
@ -124,7 +142,8 @@ FocusScope {
focus: visible focus: visible
radius: 40 * DefaultStyle.dp radius: 40 * DefaultStyle.dp
style: ButtonStyle.grey style: ButtonStyle.grey
onClicked: UtilsCpp.createCall(searchResultItem.core.defaultFullAddress) onClicked: UtilsCpp.createCall(
searchResultItem.core.defaultFullAddress)
KeyNavigation.left: chatButton KeyNavigation.left: chatButton
KeyNavigation.right: videoCallButton KeyNavigation.right: videoCallButton
} }
@ -138,19 +157,25 @@ FocusScope {
focus: visible && !callButton.visible focus: visible && !callButton.visible
radius: 40 * DefaultStyle.dp radius: 40 * DefaultStyle.dp
style: ButtonStyle.grey style: ButtonStyle.grey
onClicked: UtilsCpp.createCall(searchResultItem.core.defaultFullAddress, {'localVideoEnabled': true}) onClicked: UtilsCpp.createCall(
searchResultItem.core.defaultFullAddress,
{
"localVideoEnabled": true
})
KeyNavigation.left: callButton KeyNavigation.left: callButton
KeyNavigation.right: chatButton KeyNavigation.right: chatButton
} }
IconButton { IconButton {
id: chatButton id: chatButton
visible: actionButtons.visible && !SettingsCpp.disableChatFeature visible: actionButtons.visible
&& !SettingsCpp.disableChatFeature
Layout.preferredWidth: 45 * DefaultStyle.dp Layout.preferredWidth: 45 * DefaultStyle.dp
Layout.preferredHeight: 45 * DefaultStyle.dp Layout.preferredHeight: 45 * DefaultStyle.dp
icon.width: 24 * DefaultStyle.dp icon.width: 24 * DefaultStyle.dp
icon.height: 24 * DefaultStyle.dp icon.height: 24 * DefaultStyle.dp
icon.source: AppIcons.chatTeardropText icon.source: AppIcons.chatTeardropText
focus: visible && !callButton.visible && !videoCallButton.visible focus: visible && !callButton.visible
&& !videoCallButton.visible
radius: 40 * DefaultStyle.dp radius: 40 * DefaultStyle.dp
style: ButtonStyle.grey style: ButtonStyle.grey
KeyNavigation.left: videoCallButton KeyNavigation.left: videoCallButton
@ -162,19 +187,26 @@ FocusScope {
z: 1 z: 1
popup.x: 0 popup.x: 0
popup.padding: 10 * DefaultStyle.dp popup.padding: 10 * DefaultStyle.dp
visible: mainItem.showContactMenu && (contactArea.containsMouse || hovered || popup.opened) visible: mainItem.showContactMenu
&& (contactArea.containsMouse || hovered
|| popup.opened)
enabled: visible
popup.contentItem: ColumnLayout { popup.contentItem: ColumnLayout {
IconLabelButton { IconLabelButton {
visible: searchResultItem.core.isStored && !searchResultItem.core.readOnly visible: searchResultItem.core.isStored
text: searchResultItem.core.starred ? qsTr("Enlever des favoris") : qsTr("Mettre en favori") && !searchResultItem.core.readOnly
text: searchResultItem.core.starred ? qsTr(
"Enlever des favoris") : qsTr(
"Mettre en favori")
icon.source: searchResultItem.core.starred ? AppIcons.heartFill : AppIcons.heart icon.source: searchResultItem.core.starred ? AppIcons.heartFill : AppIcons.heart
spacing: 10 * DefaultStyle.dp spacing: 10 * DefaultStyle.dp
textColor: DefaultStyle.main2_500main textColor: DefaultStyle.main2_500main
hoveredImageColor: searchResultItem.core.starred ? DefaultStyle.main1_700 : DefaultStyle.danger_700 hoveredImageColor: searchResultItem.core.starred ? DefaultStyle.main1_700 : DefaultStyle.danger_700
contentImageColor: searchResultItem.core.starred ? DefaultStyle.danger_500main : DefaultStyle.main2_600 contentImageColor: searchResultItem.core.starred ? DefaultStyle.danger_500main : DefaultStyle.main2_600
onClicked: { onClicked: {
searchResultItem.core.lSetStarred(!searchResultItem.core.starred) searchResultItem.core.lSetStarred(
!searchResultItem.core.starred)
friendPopup.close() friendPopup.close()
} }
style: ButtonStyle.noBackground style: ButtonStyle.noBackground
@ -186,14 +218,25 @@ FocusScope {
textColor: DefaultStyle.main2_500main textColor: DefaultStyle.main2_500main
onClicked: { onClicked: {
var vcard = searchResultItem.core.getVCard() var vcard = searchResultItem.core.getVCard()
var username = searchResultItem.core.givenName + searchResultItem.core.familyName var username = searchResultItem.core.givenName
var filepath = UtilsCpp.createVCardFile(username, vcard) + searchResultItem.core.familyName
if (filepath == "") UtilsCpp.showInformationPopup(qsTr("Erreur"), qsTr("La création du fichier vcard a échoué"), false) var filepath = UtilsCpp.createVCardFile(
else mainWindow.showInformationPopup(qsTr("VCard créée"), qsTr("VCard du contact enregistrée dans %1").arg(filepath)) username, vcard)
UtilsCpp.shareByEmail(qsTr("Partage de contact"), vcard, filepath) if (filepath == "")
UtilsCpp.showInformationPopup(
qsTr("Erreur"), qsTr(
"La création du fichier vcard a échoué"),
false)
else
mainWindow.showInformationPopup(
qsTr("VCard créée"), qsTr(
"VCard du contact enregistrée dans %1").arg(
filepath))
UtilsCpp.shareByEmail(
qsTr("Partage de contact"),
vcard, filepath)
} }
style: ButtonStyle.noBackground style: ButtonStyle.noBackground
} }
IconLabelButton { IconLabelButton {
text: qsTr("Supprimer") text: qsTr("Supprimer")
@ -201,7 +244,8 @@ FocusScope {
spacing: 10 * DefaultStyle.dp spacing: 10 * DefaultStyle.dp
visible: !searchResultItem.core.readOnly visible: !searchResultItem.core.readOnly
onClicked: { onClicked: {
mainItem.contactDeletionRequested(searchResultItem) mainItem.contactDeletionRequested(
searchResultItem)
friendPopup.close() friendPopup.close()
} }
style: ButtonStyle.noBackgroundRed style: ButtonStyle.noBackgroundRed
@ -210,6 +254,7 @@ FocusScope {
} }
} }
} }
}
MouseArea { MouseArea {
id: contactArea id: contactArea
@ -219,7 +264,7 @@ FocusScope {
hoverEnabled: true hoverEnabled: true
acceptedButtons: Qt.AllButtons acceptedButtons: Qt.AllButtons
z: -1 z: -1
focus: !actionButtons.visible focus: !buttonsLayoutLoader.active
onContainsMouseChanged: { onContainsMouseChanged: {
mainItem.containsMouseChanged(containsMouse) mainItem.containsMouseChanged(containsMouse)
} }
@ -228,17 +273,20 @@ FocusScope {
radius: 8 * DefaultStyle.dp radius: 8 * DefaultStyle.dp
opacity: 0.7 opacity: 0.7
color: mainItem.isSelected ? DefaultStyle.main2_200 : DefaultStyle.main2_100 color: mainItem.isSelected ? DefaultStyle.main2_200 : DefaultStyle.main2_100
visible: mainItem.isLastHovered || friendPopup.hovered || mainItem.isSelected || friendPopup.visible visible: mainItem.isLastHovered || mainItem.isSelected
} }
Keys.onPressed: (event)=> { Keys.onPressed: event => {
if (event.key == Qt.Key_Space || event.key == Qt.Key_Enter || event.key == Qt.Key_Return) { if (event.key == Qt.Key_Space
|| event.key == Qt.Key_Enter
|| event.key == Qt.Key_Return) {
contactArea.clicked(undefined) contactArea.clicked(undefined)
event.accepted = true; event.accepted = true
} }
} }
onClicked: (mouse) => { onClicked: mouse => {
forceActiveFocus() forceActiveFocus()
if (mouse && mouse.button == Qt.RightButton && mainItem.showContactMenu) { if (mouse && mouse.button == Qt.RightButton
&& mainItem.showContactMenu) {
friendPopup.open() friendPopup.open()
} else { } else {
mainItem.clicked(mouse) mainItem.clicked(mouse)

View file

@ -1,7 +1,8 @@
/** /**
* Qml template used for welcome and login/register pages * Qml template used for welcome and login/register pages
**/ **/
import QtCore import QtCore
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
@ -11,23 +12,22 @@ import QtQuick.Effects
import Linphone import Linphone
import UtilsCpp import UtilsCpp
import SettingsCpp import SettingsCpp
import 'qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js' as Utils import "qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js" as Utils
import 'qrc:/qt/qml/Linphone/view/Style/buttonStyle.js' as ButtonStyle import "qrc:/qt/qml/Linphone/view/Style/buttonStyle.js" as ButtonStyle
Item { Item {
id: mainItem id: mainItem
property var callObj property var callObj
property var contextualMenuOpenedComponent: undefined property var contextualMenuOpenedComponent: undefined
signal addAccountRequest() signal addAccountRequest
signal openNewCallRequest() signal openNewCallRequest
signal callCreated() signal callCreated
signal openCallHistory() signal openCallHistory
signal openNumPadRequest() signal openNumPadRequest
signal displayContactRequested(string contactAddress) signal displayContactRequested(string contactAddress)
signal createContactRequested(string name, string address) signal createContactRequested(string name, string address)
signal accountRemoved() signal accountRemoved
function goToNewCall() { function goToNewCall() {
tabbar.currentIndex = 0 tabbar.currentIndex = 0
@ -48,7 +48,8 @@ Item {
} }
function openContextualMenuComponent(component) { function openContextualMenuComponent(component) {
if (mainItem.contextualMenuOpenedComponent && mainItem.contextualMenuOpenedComponent != component) { if (mainItem.contextualMenuOpenedComponent
&& mainItem.contextualMenuOpenedComponent != component) {
mainStackView.pop() mainStackView.pop()
mainItem.contextualMenuOpenedComponent = undefined mainItem.contextualMenuOpenedComponent = undefined
} }
@ -64,15 +65,19 @@ Item {
mainItem.contextualMenuOpenedComponent = undefined mainItem.contextualMenuOpenedComponent = undefined
} }
function openAccountSettings(account: AccountGui) { function openAccountSettings(account) {
var page = accountSettingsPageComponent.createObject(parent, {"account": account}); var page = accountSettingsPageComponent.createObject(parent, {
"account": account
})
openContextualMenuComponent(page) openContextualMenuComponent(page)
} }
AccountProxy { AccountProxy {
id: accountProxy id: accountProxy
sourceModel: AppCpp.accounts sourceModel: AppCpp.accounts
onDefaultAccountChanged: if (tabbar.currentIndex === 0 && defaultAccount) defaultAccount.core?.lResetMissedCalls() onDefaultAccountChanged: if (tabbar.currentIndex === 0
&& defaultAccount)
defaultAccount.core?.lResetMissedCalls()
} }
CallProxy { CallProxy {
@ -97,12 +102,10 @@ Item {
property string remoteName: currentCall ? currentCall.core.remoteName : "" property string remoteName: currentCall ? currentCall.core.remoteName : ""
contentItem: MediumButton { contentItem: MediumButton {
style: ButtonStyle.toast style: ButtonStyle.toast
text: currentCallNotif.currentCall text: currentCallNotif.currentCall ? currentCallNotif.currentCall.core.conference ? ("Réunion en cours : ") + currentCallNotif.currentCall.core.conference.core.subject : (("Appel en cours : ") + currentCallNotif.remoteName) : "appel en cours"
? currentCallNotif.currentCall.core.conference
? ("Réunion en cours : ") + currentCallNotif.currentCall.core.conference.core.subject
: (("Appel en cours : ") + currentCallNotif.remoteName) : "appel en cours"
onClicked: { onClicked: {
var callsWindow = UtilsCpp.getCallsWindow(currentCallNotif.currentCall) var callsWindow = UtilsCpp.getCallsWindow(
currentCallNotif.currentCall)
UtilsCpp.smartShowWindow(callsWindow) UtilsCpp.smartShowWindow(callsWindow)
} }
} }
@ -123,20 +126,35 @@ Item {
when: mainItem.contextualMenuOpenedComponent != undefined when: mainItem.contextualMenuOpenedComponent != undefined
value: -1 value: -1
} }
model: [ model: [{
{icon: AppIcons.phone, selectedIcon: AppIcons.phoneSelected, label: qsTr("Appels")}, "icon": AppIcons.phone,
{icon: AppIcons.adressBook, selectedIcon: AppIcons.adressBookSelected, label: qsTr("Contacts")}, "selectedIcon": AppIcons.phoneSelected,
{icon: AppIcons.chatTeardropText, selectedIcon: AppIcons.chatTeardropTextSelected, label: qsTr("Conversations"), visible: !SettingsCpp.disableChatFeature}, "label": qsTr("Appels")
{icon: AppIcons.videoconference, selectedIcon: AppIcons.videoconferenceSelected, label: qsTr("Réunions"), visible: !SettingsCpp.disableMeetingsFeature} }, {
] "icon": AppIcons.adressBook,
"selectedIcon": AppIcons.adressBookSelected,
"label": qsTr("Contacts")
}, {
"icon": AppIcons.chatTeardropText,
"selectedIcon": AppIcons.chatTeardropTextSelected,
"label": qsTr("Conversations"),
"visible": !SettingsCpp.disableChatFeature
}, {
"icon": AppIcons.videoconference,
"selectedIcon": AppIcons.videoconferenceSelected,
"label": qsTr("Réunions"),
"visible": !SettingsCpp.disableMeetingsFeature
}]
onCurrentIndexChanged: { onCurrentIndexChanged: {
if (currentIndex == -1) return if (currentIndex == -1)
if (currentIndex === 0 && accountProxy.defaultAccount) accountProxy.defaultAccount.core?.lResetMissedCalls() return
if (currentIndex === 0 && accountProxy.defaultAccount)
accountProxy.defaultAccount.core?.lResetMissedCalls()
if (mainItem.contextualMenuOpenedComponent) { if (mainItem.contextualMenuOpenedComponent) {
closeContextualMenuComponent() closeContextualMenuComponent()
} }
} }
Keys.onPressed: (event)=>{ Keys.onPressed: event => {
if (event.key == Qt.Key_Right) { if (event.key == Qt.Key_Right) {
mainStackView.currentItem.forceActiveFocus() mainStackView.currentItem.forceActiveFocus()
} }
@ -144,9 +162,15 @@ Item {
Component.onCompleted: { Component.onCompleted: {
if (SettingsCpp.shortcutCount > 0) { if (SettingsCpp.shortcutCount > 0) {
var shortcuts = SettingsCpp.shortcuts var shortcuts = SettingsCpp.shortcuts
shortcuts.forEach((shortcut) => { shortcuts.forEach(shortcut => {
model.push({icon: shortcut.icon, selectedIcon: shortcut.icon, label: shortcut.name, colored: true, link:shortcut.link}) model.push({
}); "icon": shortcut.icon,
"selectedIcon": shortcut.icon,
"label": shortcut.name,
"colored": true,
"link": shortcut.link
})
})
} }
initButtons() initButtons()
currentIndex = SettingsCpp.getLastActiveTabIndex() currentIndex = SettingsCpp.getLastActiveTabIndex()
@ -181,8 +205,10 @@ Item {
} }
onTextChanged: { onTextChanged: {
if (text.length != 0) listPopup.open() if (text.length != 0)
else listPopup.close() listPopup.open()
else
listPopup.close()
} }
KeyNavigation.down: contactList //contactLoader.item?.count > 0 || !contactLoader.item?.footerItem? contactLoader.item : contactLoader.item?.footerItem KeyNavigation.down: contactList //contactLoader.item?.count > 0 || !contactLoader.item?.footerItem? contactLoader.item : contactLoader.item?.footerItem
KeyNavigation.up: contactList //contactLoader.item?.footerItem ? contactLoader.item?.footerItem : contactLoader.item KeyNavigation.up: contactList //contactLoader.item?.footerItem ? contactLoader.item?.footerItem : contactLoader.item
@ -192,11 +218,14 @@ Item {
width: magicSearchBar.width width: magicSearchBar.width
property int maxHeight: 400 * DefaultStyle.dp property int maxHeight: 400 * DefaultStyle.dp
property bool displayScrollbar: contactList.height > maxHeight property bool displayScrollbar: contactList.height > maxHeight
height: Math.min(contactList.contentHeight, maxHeight) + topPadding + bottomPadding height: Math.min(
contactList.contentHeight,
maxHeight) + topPadding + bottomPadding
y: magicSearchBar.height y: magicSearchBar.height
closePolicy: Popup.CloseOnEscape // closePolicy: Popup.CloseOnEscape
topPadding: 20 * DefaultStyle.dp topPadding: 20 * DefaultStyle.dp
bottomPadding: contactList.haveContacts ? 20 * DefaultStyle.dp : 10 * DefaultStyle.dp bottomPadding: contactList.haveContacts ? 20 * DefaultStyle.dp : 10
* DefaultStyle.dp
rightPadding: 8 * DefaultStyle.dp rightPadding: 8 * DefaultStyle.dp
leftPadding: 20 * DefaultStyle.dp leftPadding: 20 * DefaultStyle.dp
visible: magicSearchBar.text.length != 0 visible: magicSearchBar.text.length != 0
@ -210,7 +239,6 @@ Item {
anchors.fill: parent anchors.fill: parent
border.color: DefaultStyle.main1_500_main border.color: DefaultStyle.main1_500_main
border.width: contactList.activeFocus ? 2 : 0 border.width: contactList.activeFocus ? 2 : 0
} }
MultiEffect { MultiEffect {
source: popupBg source: popupBg
@ -224,7 +252,8 @@ Item {
contentItem: AllContactListView { contentItem: AllContactListView {
id: contactList id: contactList
width: listPopup.width - listPopup.leftPadding - listPopup.rightPadding width: listPopup.width - listPopup.leftPadding
- listPopup.rightPadding
itemsRightMargin: 5 * DefaultStyle.dp //(Actions have already 10 of margin) itemsRightMargin: 5 * DefaultStyle.dp //(Actions have already 10 of margin)
showInitials: false showInitials: false
showContactMenu: false showContactMenu: false
@ -283,8 +312,12 @@ Item {
delegate: Item { delegate: Item {
Connections { Connections {
target: modelData.core target: modelData.core
function onShowMwiChanged() {voicemail.updateCumulatedMwi()} function onShowMwiChanged() {
function onVoicemailAddressChanged(){voicemail.updateCumulatedMwi()} voicemail.updateCumulatedMwi()
}
function onVoicemailAddressChanged() {
voicemail.updateCumulatedMwi()
}
} }
} }
} }
@ -312,10 +345,15 @@ Item {
if (accountProxy.count > 1) { if (accountProxy.count > 1) {
avatarButton.popup.open() avatarButton.popup.open()
} else { } else {
if (accountProxy.defaultAccount.core.voicemailAddress.length > 0) if (accountProxy.defaultAccount.core.voicemailAddress.length
UtilsCpp.createCall(accountProxy.defaultAccount.core.voicemailAddress) > 0)
UtilsCpp.createCall(
accountProxy.defaultAccount.core.voicemailAddress)
else else
UtilsCpp.showInformationPopup(qsTr("Erreur"), qsTr("L'URI de messagerie vocale n'est pas définie."), false) UtilsCpp.showInformationPopup(
qsTr("Erreur"), qsTr(
"L'URI de messagerie vocale n'est pas définie."),
false)
} }
} }
} }
@ -351,10 +389,11 @@ Item {
id: popupFocus id: popupFocus
implicitHeight: settingsButtons.implicitHeight implicitHeight: settingsButtons.implicitHeight
implicitWidth: settingsButtons.implicitWidth implicitWidth: settingsButtons.implicitWidth
Keys.onPressed: (event)=> { Keys.onPressed: event => {
if (event.key == Qt.Key_Left || event.key == Qt.Key_Escape) { if (event.key == Qt.Key_Left
|| event.key == Qt.Key_Escape) {
settingsMenuButton.popup.close() settingsMenuButton.popup.close()
event.accepted = true; event.accepted = true
} }
} }
@ -371,23 +410,33 @@ Item {
icon.height: 32 * DefaultStyle.dp icon.height: 32 * DefaultStyle.dp
text: qsTr("Mon compte") text: qsTr("Mon compte")
icon.source: AppIcons.manageProfile icon.source: AppIcons.manageProfile
onClicked: openAccountSettings(accountProxy.defaultAccount ? accountProxy.defaultAccount : accountProxy.firstAccount()) onClicked: openAccountSettings(
KeyNavigation.up: visibleChildren.length != 0 ? settingsMenuButton.getPreviousItem(0) : null accountProxy.defaultAccount ? accountProxy.defaultAccount : accountProxy.firstAccount())
KeyNavigation.down: visibleChildren.length != 0 ? settingsMenuButton.getNextItem(0) : null KeyNavigation.up: visibleChildren.length
!= 0 ? settingsMenuButton.getPreviousItem(
0) : null
KeyNavigation.down: visibleChildren.length
!= 0 ? settingsMenuButton.getNextItem(
0) : null
} }
IconLabelButton { IconLabelButton {
id: dndButton id: dndButton
Layout.fillWidth: true Layout.fillWidth: true
icon.width: 32 * DefaultStyle.dp icon.width: 32 * DefaultStyle.dp
icon.height: 32 * DefaultStyle.dp icon.height: 32 * DefaultStyle.dp
text: SettingsCpp.dnd ? qsTr("Désactiver ne pas déranger") : qsTr("Activer ne pas déranger") text: SettingsCpp.dnd ? qsTr("Désactiver ne pas déranger") : qsTr(
"Activer ne pas déranger")
icon.source: AppIcons.bellDnd icon.source: AppIcons.bellDnd
onClicked: { onClicked: {
settingsMenuButton.popup.close() settingsMenuButton.popup.close()
SettingsCpp.dnd = !SettingsCpp.dnd SettingsCpp.dnd = !SettingsCpp.dnd
} }
KeyNavigation.up: visibleChildren.length != 0 ? settingsMenuButton.getPreviousItem(1) : null KeyNavigation.up: visibleChildren.length
KeyNavigation.down: visibleChildren.length != 0 ? settingsMenuButton.getNextItem(1) : null != 0 ? settingsMenuButton.getPreviousItem(
1) : null
KeyNavigation.down: visibleChildren.length
!= 0 ? settingsMenuButton.getNextItem(
1) : null
} }
IconLabelButton { IconLabelButton {
id: settingsButton id: settingsButton
@ -397,9 +446,14 @@ Item {
icon.height: 32 * DefaultStyle.dp icon.height: 32 * DefaultStyle.dp
text: qsTr("Paramètres") text: qsTr("Paramètres")
icon.source: AppIcons.settings icon.source: AppIcons.settings
onClicked: openContextualMenuComponent(settingsPageComponent) onClicked: openContextualMenuComponent(
KeyNavigation.up: visibleChildren.length != 0 ? settingsMenuButton.getPreviousItem(2) : null settingsPageComponent)
KeyNavigation.down: visibleChildren.length != 0 ? settingsMenuButton.getNextItem(2) : null KeyNavigation.up: visibleChildren.length
!= 0 ? settingsMenuButton.getPreviousItem(
2) : null
KeyNavigation.down: visibleChildren.length
!= 0 ? settingsMenuButton.getNextItem(
2) : null
} }
IconLabelButton { IconLabelButton {
id: recordsButton id: recordsButton
@ -409,8 +463,12 @@ Item {
icon.height: 32 * DefaultStyle.dp icon.height: 32 * DefaultStyle.dp
text: qsTr("Enregistrements") text: qsTr("Enregistrements")
icon.source: AppIcons.micro icon.source: AppIcons.micro
KeyNavigation.up: visibleChildren.length != 0 ? settingsMenuButton.getPreviousItem(3) : null KeyNavigation.up: visibleChildren.length
KeyNavigation.down: visibleChildren.length != 0 ? settingsMenuButton.getNextItem(3) : null != 0 ? settingsMenuButton.getPreviousItem(
3) : null
KeyNavigation.down: visibleChildren.length
!= 0 ? settingsMenuButton.getNextItem(
3) : null
} }
IconLabelButton { IconLabelButton {
id: helpButton id: helpButton
@ -419,9 +477,14 @@ Item {
icon.height: 32 * DefaultStyle.dp icon.height: 32 * DefaultStyle.dp
text: qsTr("Aide") text: qsTr("Aide")
icon.source: AppIcons.question icon.source: AppIcons.question
onClicked: openContextualMenuComponent(helpPageComponent) onClicked: openContextualMenuComponent(
KeyNavigation.up: visibleChildren.length != 0 ? settingsMenuButton.getPreviousItem(4) : null helpPageComponent)
KeyNavigation.down: visibleChildren.length != 0 ? settingsMenuButton.getNextItem(4) : null KeyNavigation.up: visibleChildren.length
!= 0 ? settingsMenuButton.getPreviousItem(
4) : null
KeyNavigation.down: visibleChildren.length
!= 0 ? settingsMenuButton.getNextItem(
4) : null
} }
IconLabelButton { IconLabelButton {
id: quitButton id: quitButton
@ -432,19 +495,24 @@ Item {
icon.source: AppIcons.power icon.source: AppIcons.power
onClicked: { onClicked: {
settingsMenuButton.popup.close() settingsMenuButton.popup.close()
UtilsCpp.getMainWindow().showConfirmationLambdaPopup("", UtilsCpp.getMainWindow(
qsTr("Quitter Linphone ?"), ).showConfirmationLambdaPopup(
"", qsTr(
"Quitter Linphone ?"),
"", "",
function (confirmed) { function (confirmed) {
if (confirmed) { if (confirmed) {
console.info("Exiting App from Top Menu"); console.info("Exiting App from Top Menu")
Qt.quit() Qt.quit()
} }
})
} }
) KeyNavigation.up: visibleChildren.length
} != 0 ? settingsMenuButton.getPreviousItem(
KeyNavigation.up: visibleChildren.length != 0 ? settingsMenuButton.getPreviousItem(5) : null 5) : null
KeyNavigation.down: visibleChildren.length != 0 ? settingsMenuButton.getNextItem(5) : null KeyNavigation.down: visibleChildren.length
!= 0 ? settingsMenuButton.getNextItem(
5) : null
} }
Rectangle { Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
@ -455,14 +523,19 @@ Item {
IconLabelButton { IconLabelButton {
id: addAccountButton id: addAccountButton
Layout.fillWidth: true Layout.fillWidth: true
visible: SettingsCpp.maxAccount == 0 || SettingsCpp.maxAccount > accountProxy.count visible: SettingsCpp.maxAccount == 0
|| SettingsCpp.maxAccount > accountProxy.count
icon.width: 32 * DefaultStyle.dp icon.width: 32 * DefaultStyle.dp
icon.height: 32 * DefaultStyle.dp icon.height: 32 * DefaultStyle.dp
text: qsTr("Ajouter un compte") text: qsTr("Ajouter un compte")
icon.source: AppIcons.plusCircle icon.source: AppIcons.plusCircle
onClicked: mainItem.addAccountRequest() onClicked: mainItem.addAccountRequest()
KeyNavigation.up: visibleChildren.length != 0 ? settingsMenuButton.getPreviousItem(7) : null KeyNavigation.up: visibleChildren.length
KeyNavigation.down: visibleChildren.length != 0 ? settingsMenuButton.getNextItem(7) : null != 0 ? settingsMenuButton.getPreviousItem(
7) : null
KeyNavigation.down: visibleChildren.length
!= 0 ? settingsMenuButton.getNextItem(
7) : null
} }
} }
} }
@ -476,14 +549,19 @@ Item {
objectName: "mainStackLayout" objectName: "mainStackLayout"
property int _currentIndex: tabbar.currentIndex property int _currentIndex: tabbar.currentIndex
currentIndex: -1 currentIndex: -1
onActiveFocusChanged: if(activeFocus && currentIndex >= 0) children[currentIndex].forceActiveFocus() onActiveFocusChanged: if (activeFocus
&& currentIndex >= 0)
children[currentIndex].forceActiveFocus()
on_CurrentIndexChanged: { on_CurrentIndexChanged: {
if (count > 0) { if (count > 0) {
if(_currentIndex >= count && tabbar.model[_currentIndex].link){ if (_currentIndex >= count
Qt.openUrlExternally(tabbar.model[_currentIndex].link) && tabbar.model[_currentIndex].link) {
Qt.openUrlExternally(
tabbar.model[_currentIndex].link)
} else if (_currentIndex >= 0) { } else if (_currentIndex >= 0) {
currentIndex = _currentIndex currentIndex = _currentIndex
SettingsCpp.setLastActiveTabIndex(currentIndex) SettingsCpp.setLastActiveTabIndex(
currentIndex)
} }
} }
} }
@ -491,13 +569,22 @@ Item {
id: callPage id: callPage
Connections { Connections {
target: mainItem target: mainItem
function onOpenNewCallRequest(){ callPage.goToNewCall()} function onOpenNewCallRequest() {
function onCallCreated(){ callPage.goToCallHistory()} callPage.goToNewCall()
function onOpenCallHistory(){ callPage.goToCallHistory()} }
function onOpenNumPadRequest(){ callPage.openNumPadRequest()} function onCallCreated() {
callPage.goToCallHistory()
}
function onOpenCallHistory() {
callPage.goToCallHistory()
}
function onOpenNumPadRequest() {
callPage.openNumPadRequest()
}
} }
onCreateContactRequested: (name, address) => { onCreateContactRequested: (name, address) => {
mainItem.createContact(name, address) mainItem.createContact(
name, address)
} }
Component.onCompleted: { Component.onCompleted: {
magicSearchBar.numericPadPopup = callPage.numericPadPopup magicSearchBar.numericPadPopup = callPage.numericPadPopup
@ -545,7 +632,12 @@ Item {
Control.StackView { Control.StackView {
id: mainStackView id: mainStackView
property Transition noTransition: Transition { property Transition noTransition: Transition {
PropertyAnimation { property: "opacity"; from: 1; to: 1; duration: 0 } PropertyAnimation {
property: "opacity"
from: 1
to: 1
duration: 0
}
} }
pushEnter: noTransition pushEnter: noTransition
pushExit: noTransition pushExit: noTransition
@ -560,4 +652,3 @@ Item {
} }
} }
} }