asynchronous actions buttons to improve performances
This commit is contained in:
parent
586dca5cd0
commit
3629732fde
5 changed files with 1298 additions and 1061 deletions
|
|
@ -2,162 +2,191 @@ 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
|
style: ButtonStyle.popupButton
|
||||||
: hovered
|
checked: popup.visible
|
||||||
? hoveredColor
|
implicitWidth: 24 * DefaultStyle.dp
|
||||||
: color
|
implicitHeight: 24 * DefaultStyle.dp
|
||||||
style: ButtonStyle.popupButton
|
width: 24 * DefaultStyle.dp
|
||||||
checked: popup.visible
|
height: 24 * DefaultStyle.dp
|
||||||
implicitWidth: 24 * DefaultStyle.dp
|
leftPadding: 0
|
||||||
implicitHeight: 24 * DefaultStyle.dp
|
rightPadding: 0
|
||||||
width: 24 * DefaultStyle.dp
|
topPadding: 0
|
||||||
height: 24 * DefaultStyle.dp
|
bottomPadding: 0
|
||||||
leftPadding: 0
|
icon.source: AppIcons.verticalDots
|
||||||
rightPadding: 0
|
icon.width: 24 * DefaultStyle.dp
|
||||||
topPadding: 0
|
icon.height: 24 * DefaultStyle.dp
|
||||||
bottomPadding: 0
|
function close() {
|
||||||
icon.source: AppIcons.verticalDots
|
popup.close()
|
||||||
icon.width: 24 * DefaultStyle.dp
|
}
|
||||||
icon.height: 24 * DefaultStyle.dp
|
function open() {
|
||||||
function close() {
|
popup.open()
|
||||||
popup.close()
|
}
|
||||||
}
|
|
||||||
function open() {
|
|
||||||
popup.open()
|
|
||||||
}
|
|
||||||
|
|
||||||
function isFocusable(item){
|
|
||||||
return item.activeFocusOnTab
|
|
||||||
}
|
|
||||||
function getPreviousItem(index){
|
|
||||||
return _getPreviousItem(popup.contentItem instanceof FocusScope ? popup.contentItem.children[0] : popup.contentItem, index)
|
|
||||||
}
|
|
||||||
function getNextItem(index){
|
|
||||||
return _getNextItem(popup.contentItem instanceof FocusScope ? popup.contentItem.children[0] : popup.contentItem, index)
|
|
||||||
}
|
|
||||||
|
|
||||||
function _getPreviousItem(content, index){
|
|
||||||
if(content.visibleChildren.length == 0) return null
|
|
||||||
--index
|
|
||||||
while(index >= 0){
|
|
||||||
if( isFocusable(content.children[index]) && content.children[index].visible) return content.children[index]
|
|
||||||
--index
|
|
||||||
}
|
|
||||||
return _getPreviousItem(content, content.children.length)
|
|
||||||
}
|
|
||||||
function _getNextItem(content, index){
|
|
||||||
++index
|
|
||||||
while(index < content.children.length){
|
|
||||||
if( isFocusable(content.children[index]) && content.children[index].visible) return content.children[index]
|
|
||||||
++index
|
|
||||||
}
|
|
||||||
return _getNextItem(content, -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
Keys.onPressed: (event) => {
|
function isFocusable(item) {
|
||||||
if(mainItem.checked){
|
return item.activeFocusOnTab
|
||||||
if( event.key == Qt.Key_Escape || event.key == Qt.Key_Left || event.key == Qt.Key_Space){
|
}
|
||||||
mainItem.close()
|
function getPreviousItem(index) {
|
||||||
mainItem.forceActiveFocus()
|
return _getPreviousItem(
|
||||||
event.accepted = true
|
popup.contentItem
|
||||||
}else if(event.key == Qt.Key_Up){
|
instanceof FocusScope ? popup.contentItem.children[0] : popup.contentItem,
|
||||||
getPreviousItem(0).forceActiveFocus()
|
index)
|
||||||
event.accepted = true
|
}
|
||||||
}else if(event.key == Qt.Key_Tab || event.key == Qt.Key_Down){
|
function getNextItem(index) {
|
||||||
getNextItem(-1).forceActiveFocus()
|
return _getNextItem(
|
||||||
event.accepted = true
|
popup.contentItem
|
||||||
}
|
instanceof FocusScope ? popup.contentItem.children[0] : popup.contentItem,
|
||||||
}else if(event.key == Qt.Key_Space){
|
index)
|
||||||
mainItem.open()
|
}
|
||||||
event.accepted = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
background: Item {
|
|
||||||
anchors.fill: mainItem
|
|
||||||
Rectangle {
|
|
||||||
id: buttonBackground
|
|
||||||
anchors.fill: parent
|
|
||||||
color: mainItem.backgroundColor
|
|
||||||
radius: 40 * DefaultStyle.dp
|
|
||||||
}
|
|
||||||
MultiEffect {
|
|
||||||
enabled: mainItem.shadowEnabled
|
|
||||||
anchors.fill: buttonBackground
|
|
||||||
source: buttonBackground
|
|
||||||
visible: mainItem.shadowEnabled
|
|
||||||
// Crash : https://bugreports.qt.io/browse/QTBUG-124730
|
|
||||||
shadowEnabled: true //mainItem.shadowEnabled
|
|
||||||
shadowColor: DefaultStyle.grey_1000
|
|
||||||
shadowBlur: 0.1
|
|
||||||
shadowOpacity: mainItem.shadowEnabled ? 0.5 : 0.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
contentItem: EffectImage {
|
|
||||||
imageSource: mainItem.icon.source
|
|
||||||
imageWidth: mainItem.icon.width
|
|
||||||
imageHeight: mainItem.icon.height
|
|
||||||
colorizationColor: mainItem.contentImageColor
|
|
||||||
}
|
|
||||||
onPressed: {
|
|
||||||
if (popup.visible) popup.close()
|
|
||||||
else popup.open()
|
|
||||||
}
|
|
||||||
Control.Popup {
|
|
||||||
id: popup
|
|
||||||
x: 0
|
|
||||||
y: mainItem.height
|
|
||||||
closePolicy: Popup.CloseOnPressOutsideParent | Popup.CloseOnPressOutside | Popup.CloseOnEscape
|
|
||||||
padding: 10 * DefaultStyle.dp
|
|
||||||
parent: mainItem // Explicit define for coordinates references.
|
|
||||||
function updatePosition(){
|
|
||||||
if (!visible) return
|
|
||||||
var popupHeight = popup.height + popup.padding
|
|
||||||
var popupWidth = popup.width + popup.padding
|
|
||||||
var winPosition = mainItem.Window.contentItem ? mainItem.Window.contentItem.mapToItem(mainItem,0 , 0) : {x:0,y:0}
|
|
||||||
// Stay inside main window
|
|
||||||
y = Math.max( Math.min( 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?)
|
|
||||||
if( y < mainItem.height && y + popupHeight > 0){
|
|
||||||
x += mainItem.width
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onHeightChanged: Qt.callLater(updatePosition)
|
|
||||||
onWidthChanged: Qt.callLater(updatePosition)
|
|
||||||
onVisibleChanged: Qt.callLater(updatePosition)
|
|
||||||
|
|
||||||
Connections{
|
|
||||||
target: mainItem.Window
|
|
||||||
function onHeightChanged(){ Qt.callLater(popup.updatePosition)}
|
|
||||||
function onWidthChanged(){ Qt.callLater(popup.updatePosition)}
|
|
||||||
}
|
|
||||||
|
|
||||||
background: Item {
|
function _getPreviousItem(content, index) {
|
||||||
anchors.fill: parent
|
if (content.visibleChildren.length == 0)
|
||||||
Rectangle {
|
return null
|
||||||
id: popupBackground
|
--index
|
||||||
anchors.fill: parent
|
while (index >= 0) {
|
||||||
color: DefaultStyle.grey_0
|
if (isFocusable(content.children[index])
|
||||||
radius: 16 * DefaultStyle.dp
|
&& content.children[index].visible)
|
||||||
}
|
return content.children[index]
|
||||||
MultiEffect {
|
--index
|
||||||
source: popupBackground
|
}
|
||||||
anchors.fill: popupBackground
|
return _getPreviousItem(content, content.children.length)
|
||||||
shadowEnabled: true
|
}
|
||||||
shadowBlur: 0.1
|
function _getNextItem(content, index) {
|
||||||
shadowColor: DefaultStyle.grey_1000
|
++index
|
||||||
shadowOpacity: 0.4
|
while (index < content.children.length) {
|
||||||
}
|
if (isFocusable(content.children[index])
|
||||||
}
|
&& content.children[index].visible)
|
||||||
}
|
return content.children[index]
|
||||||
|
++index
|
||||||
|
}
|
||||||
|
return _getNextItem(content, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onPressed: event => {
|
||||||
|
if (mainItem.checked) {
|
||||||
|
if (event.key == Qt.Key_Escape
|
||||||
|
|| event.key == Qt.Key_Left
|
||||||
|
|| event.key == Qt.Key_Space) {
|
||||||
|
mainItem.close()
|
||||||
|
mainItem.forceActiveFocus()
|
||||||
|
event.accepted = true
|
||||||
|
} else if (event.key == Qt.Key_Up) {
|
||||||
|
getPreviousItem(0).forceActiveFocus()
|
||||||
|
event.accepted = true
|
||||||
|
} else if (event.key == Qt.Key_Tab
|
||||||
|
|| event.key == Qt.Key_Down) {
|
||||||
|
getNextItem(-1).forceActiveFocus()
|
||||||
|
event.accepted = true
|
||||||
|
}
|
||||||
|
} else if (event.key == Qt.Key_Space) {
|
||||||
|
mainItem.open()
|
||||||
|
event.accepted = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
background: Item {
|
||||||
|
anchors.fill: mainItem
|
||||||
|
Rectangle {
|
||||||
|
id: buttonBackground
|
||||||
|
anchors.fill: parent
|
||||||
|
color: mainItem.backgroundColor
|
||||||
|
radius: 40 * DefaultStyle.dp
|
||||||
|
}
|
||||||
|
MultiEffect {
|
||||||
|
enabled: mainItem.shadowEnabled
|
||||||
|
anchors.fill: buttonBackground
|
||||||
|
source: buttonBackground
|
||||||
|
visible: mainItem.shadowEnabled
|
||||||
|
// Crash : https://bugreports.qt.io/browse/QTBUG-124730
|
||||||
|
shadowEnabled: true //mainItem.shadowEnabled
|
||||||
|
shadowColor: DefaultStyle.grey_1000
|
||||||
|
shadowBlur: 0.1
|
||||||
|
shadowOpacity: mainItem.shadowEnabled ? 0.5 : 0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contentItem: EffectImage {
|
||||||
|
imageSource: mainItem.icon.source
|
||||||
|
imageWidth: mainItem.icon.width
|
||||||
|
imageHeight: mainItem.icon.height
|
||||||
|
colorizationColor: mainItem.contentImageColor
|
||||||
|
}
|
||||||
|
onPressed: {
|
||||||
|
if (popup.visible)
|
||||||
|
popup.close()
|
||||||
|
else
|
||||||
|
popup.open()
|
||||||
|
}
|
||||||
|
Control.Popup {
|
||||||
|
id: popup
|
||||||
|
x: 0
|
||||||
|
y: mainItem.height
|
||||||
|
visible: false
|
||||||
|
closePolicy: Popup.CloseOnPressOutsideParent | Popup.CloseOnPressOutside
|
||||||
|
| Popup.CloseOnEscape
|
||||||
|
padding: 10 * DefaultStyle.dp
|
||||||
|
parent: mainItem // Explicit define for coordinates references.
|
||||||
|
function updatePosition() {
|
||||||
|
if (!visible)
|
||||||
|
return
|
||||||
|
var popupHeight = popup.height + popup.padding
|
||||||
|
var popupWidth = popup.width + popup.padding
|
||||||
|
var winPosition = mainItem.Window.contentItem ? mainItem.Window.contentItem.mapToItem(
|
||||||
|
mainItem, 0,
|
||||||
|
0) : {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
}
|
||||||
|
// Stay inside main window
|
||||||
|
y = Math.max(Math.min(
|
||||||
|
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?)
|
||||||
|
if (y < mainItem.height && y + popupHeight > 0) {
|
||||||
|
x += mainItem.width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onHeightChanged: Qt.callLater(updatePosition)
|
||||||
|
onWidthChanged: Qt.callLater(updatePosition)
|
||||||
|
onVisibleChanged: Qt.callLater(updatePosition)
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: mainItem.Window
|
||||||
|
function onHeightChanged() {
|
||||||
|
Qt.callLater(popup.updatePosition)
|
||||||
|
}
|
||||||
|
function onWidthChanged() {
|
||||||
|
Qt.callLater(popup.updatePosition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
background: Item {
|
||||||
|
anchors.fill: parent
|
||||||
|
Rectangle {
|
||||||
|
id: popupBackground
|
||||||
|
anchors.fill: parent
|
||||||
|
color: DefaultStyle.grey_0
|
||||||
|
radius: 16 * DefaultStyle.dp
|
||||||
|
}
|
||||||
|
MultiEffect {
|
||||||
|
source: popupBackground
|
||||||
|
anchors.fill: popupBackground
|
||||||
|
shadowEnabled: true
|
||||||
|
shadowBlur: 0.1
|
||||||
|
shadowColor: DefaultStyle.grey_1000
|
||||||
|
shadowOpacity: 0.4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
@ -37,28 +39,32 @@ ListView {
|
||||||
}
|
}
|
||||||
flickDeceleration: 10000
|
flickDeceleration: 10000
|
||||||
spacing: 10 * DefaultStyle.dp
|
spacing: 10 * DefaultStyle.dp
|
||||||
|
|
||||||
Keys.onPressed: (event) => {
|
|
||||||
if(event.key == Qt.Key_Escape){
|
|
||||||
console.log("Back")
|
|
||||||
searchBar.forceActiveFocus()
|
|
||||||
event.accepted = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: cacheBuffer = Math.max(contentHeight,0)//contentHeight>0 ? contentHeight : 0// cache all items
|
Keys.onPressed: event => {
|
||||||
|
if (event.key == Qt.Key_Escape) {
|
||||||
|
console.log("Back")
|
||||||
|
searchBar.forceActiveFocus()
|
||||||
|
event.accepted = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
if(atYBeginning)
|
if (atYBeginning)
|
||||||
positionViewAtBeginning()// Stay at beginning
|
positionViewAtBeginning() // Stay at beginning
|
||||||
}
|
}
|
||||||
Connections {
|
Connections {
|
||||||
target: deleteHistoryPopup
|
target: deleteHistoryPopup
|
||||||
|
|
@ -68,13 +74,13 @@ ListView {
|
||||||
}
|
}
|
||||||
|
|
||||||
onAtYEndChanged: {
|
onAtYEndChanged: {
|
||||||
if(atYEnd && count > 0){
|
if (atYEnd && count > 0) {
|
||||||
callHistoryProxy.displayMore()
|
callHistoryProxy.displayMore()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
function moveToCurrentItem(){
|
function moveToCurrentItem() {
|
||||||
if( mainItem.currentIndex >= 0)
|
if (mainItem.currentIndex >= 0)
|
||||||
Utils.updatePosition(mainItem, mainItem)
|
Utils.updatePosition(mainItem, mainItem)
|
||||||
}
|
}
|
||||||
onCurrentItemChanged: {
|
onCurrentItemChanged: {
|
||||||
|
|
@ -82,32 +88,32 @@ ListView {
|
||||||
}
|
}
|
||||||
// Update position only if we are moving to current item and its position is changing.
|
// Update position only if we are moving to current item and its position is changing.
|
||||||
property var _currentItemY: currentItem?.y
|
property var _currentItemY: currentItem?.y
|
||||||
on_CurrentItemYChanged: if(_currentItemY && moveAnimation.running){
|
on_CurrentItemYChanged: if (_currentItemY && moveAnimation.running) {
|
||||||
moveToCurrentItem()
|
moveToCurrentItem()
|
||||||
}
|
}
|
||||||
Behavior on contentY{
|
Behavior on contentY {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
id: moveAnimation
|
id: moveAnimation
|
||||||
duration: 500
|
duration: 500
|
||||||
easing.type: Easing.OutExpo
|
easing.type: Easing.OutExpo
|
||||||
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.
|
||||||
// So we need to use this variable to switch off all hovered items.
|
// So we need to use this variable to switch off all hovered items.
|
||||||
property int lastMouseContainsIndex: -1
|
property int lastMouseContainsIndex: -1
|
||||||
delegate: FocusScope {
|
delegate: FocusScope {
|
||||||
width:mainItem.width
|
width: mainItem.width
|
||||||
height: 56 * DefaultStyle.dp
|
height: 56 * DefaultStyle.dp
|
||||||
visible: !!modelData
|
visible: !!modelData
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
z: 1
|
z: 1
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
@ -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,32 +151,32 @@ 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
|
||||||
|| modelData.core.status === LinphoneEnums.CallStatus.Aborted
|
=== LinphoneEnums.CallStatus.DeclinedElsewhere
|
||||||
|| modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted
|
|| modelData.core.status === LinphoneEnums.CallStatus.Aborted
|
||||||
? AppIcons.arrowElbow
|
|| modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted ? AppIcons.arrowElbow : modelData.core.isOutgoing ? AppIcons.arrowUpRight : AppIcons.arrowDownLeft
|
||||||
: modelData.core.isOutgoing
|
colorizationColor: modelData.core.status
|
||||||
? AppIcons.arrowUpRight
|
=== LinphoneEnums.CallStatus.Declined
|
||||||
: AppIcons.arrowDownLeft
|
|| modelData.core.status
|
||||||
colorizationColor: modelData.core.status === LinphoneEnums.CallStatus.Declined
|
=== LinphoneEnums.CallStatus.DeclinedElsewhere
|
||||||
|| modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere
|
|| modelData.core.status
|
||||||
|| modelData.core.status === LinphoneEnums.CallStatus.Aborted
|
=== LinphoneEnums.CallStatus.Aborted
|
||||||
|| modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted
|
|| modelData.core.status
|
||||||
|| modelData.core.status === LinphoneEnums.CallStatus.Missed
|
=== LinphoneEnums.CallStatus.EarlyAborted
|
||||||
? DefaultStyle.danger_500main
|
|| modelData.core.status === LinphoneEnums.CallStatus.Missed ? DefaultStyle.danger_500main : modelData.core.isOutgoing ? DefaultStyle.info_500_main : DefaultStyle.success_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.Aborted
|
|| modelData.core.status
|
||||||
|| modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted) ? 180 : 0
|
=== LinphoneEnums.CallStatus.DeclinedElsewhere
|
||||||
|
|| modelData.core.status === LinphoneEnums.CallStatus.Aborted
|
||||||
|
|| 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -205,17 +212,19 @@ ListView {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
focus: true
|
focus: true
|
||||||
onContainsMouseChanged: {
|
onContainsMouseChanged: {
|
||||||
if(containsMouse)
|
if (containsMouse)
|
||||||
mainItem.lastMouseContainsIndex = index
|
mainItem.lastMouseContainsIndex = index
|
||||||
else if( mainItem.lastMouseContainsIndex == index)
|
else if (mainItem.lastMouseContainsIndex == index)
|
||||||
mainItem.lastMouseContainsIndex = -1
|
mainItem.lastMouseContainsIndex = -1
|
||||||
}
|
}
|
||||||
Rectangle {
|
Rectangle {
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -6,27 +6,28 @@ 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
|
||||||
|
|
||||||
flickableDirection: Flickable.VerticalFlick
|
flickableDirection: Flickable.VerticalFlick
|
||||||
|
|
||||||
property bool showInitials: true // Display Initials of Display name.
|
property bool showInitials: true // Display Initials of Display name.
|
||||||
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 bool showFavorites: true // Display the favorites in the header
|
property bool showFavorites: true // Display the favorites in the header
|
||||||
property bool hideSuggestions: false // Hide not stored contacts (not suggestions)
|
property bool hideSuggestions: false // Hide not stored contacts (not suggestions)
|
||||||
property string highlightText: searchText // Bold characters in Display name.
|
property string highlightText: searchText // Bold characters in Display name.
|
||||||
property var sourceFlags: LinphoneEnums.MagicSearchSource.All
|
property var sourceFlags: LinphoneEnums.MagicSearchSource.All
|
||||||
|
|
||||||
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 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) {
|
||||||
|
|
@ -91,49 +93,59 @@ Flickable {
|
||||||
contactRemovedFromSelection(address)
|
contactRemovedFromSelection(address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function haveAddress(address){
|
function haveAddress(address) {
|
||||||
var index = magicSearchProxy.findFriendIndexByAddress(address)
|
var index = magicSearchProxy.findFriendIndexByAddress(address)
|
||||||
return index != -1
|
return index != -1
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetSelections(){
|
function resetSelections() {
|
||||||
mainItem.highlightedContact = null
|
mainItem.highlightedContact = null
|
||||||
favoritesList.currentIndex = -1
|
favoritesList.currentIndex = -1
|
||||||
contactsList.currentIndex = -1
|
contactsList.currentIndex = -1
|
||||||
suggestionsList.currentIndex = -1
|
suggestionsList.currentIndex = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
Utils.updatePosition(mainItem, list)
|
Utils.updatePosition(mainItem, list)
|
||||||
}
|
}
|
||||||
|
|
||||||
onHighlightedContactChanged:{
|
onHighlightedContactChanged: {
|
||||||
favoritesList.highlightedContact = highlightedContact
|
favoritesList.highlightedContact = highlightedContact
|
||||||
contactsList.highlightedContact = highlightedContact
|
contactsList.highlightedContact = highlightedContact
|
||||||
suggestionsList.highlightedContact = highlightedContact
|
suggestionsList.highlightedContact = highlightedContact
|
||||||
}
|
}
|
||||||
|
|
||||||
onSearchBarTextChanged: {
|
onSearchBarTextChanged: {
|
||||||
if(!pauseSearch && (mainItem.searchOnEmpty || searchBarText != '')) {
|
if (!pauseSearch && (mainItem.searchOnEmpty || searchBarText != '')) {
|
||||||
console.log("change search text")
|
console.log("change search text")
|
||||||
searchText = searchBarText.length === 0 ? "*" : searchBarText
|
searchText = searchBarText.length === 0 ? "*" : searchBarText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onPauseSearchChanged: {
|
onPauseSearchChanged: {
|
||||||
if(!pauseSearch && (mainItem.searchOnEmpty || searchBarText != '')){
|
if (!pauseSearch && (mainItem.searchOnEmpty || searchBarText != '')) {
|
||||||
searchText = searchBarText.length === 0 ? "*" : searchBarText
|
searchText = searchBarText.length === 0 ? "*" : searchBarText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -142,26 +154,37 @@ 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
|
||||||
var newItem
|
|| event.key == Qt.Key_Down) {
|
||||||
var direction = (event.key == Qt.Key_Up ? -1 : 1)
|
var newItem
|
||||||
if(suggestionsList.activeFocus) newItem = findNextList(suggestionsList, 0, direction)
|
var direction = (event.key == Qt.Key_Up ? -1 : 1)
|
||||||
else if(contactsList.activeFocus) newItem = findNextList(contactsList, 0, direction)
|
if (suggestionsList.activeFocus)
|
||||||
else if(favoritesList.activeFocus) newItem = findNextList(favoritesList, 0, direction)
|
newItem = findNextList(suggestionsList, 0,
|
||||||
else newItem = findNextList(suggestionsList, 0, direction)
|
direction)
|
||||||
if(newItem){
|
else if (contactsList.activeFocus)
|
||||||
newItem.selectIndex(direction > 0 ? -1 : newItem.model.count - 1)
|
newItem = findNextList(contactsList, 0,
|
||||||
event.accepted = true
|
direction)
|
||||||
}
|
else if (favoritesList.activeFocus)
|
||||||
}
|
newItem = findNextList(favoritesList, 0,
|
||||||
}
|
direction)
|
||||||
}
|
else
|
||||||
|
newItem = findNextList(suggestionsList, 0,
|
||||||
|
direction)
|
||||||
|
if (newItem) {
|
||||||
|
newItem.selectIndex(
|
||||||
|
direction > 0 ? -1 : newItem.model.count - 1)
|
||||||
|
event.accepted = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
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
|
||||||
|
|
@ -189,18 +211,21 @@ Flickable {
|
||||||
}
|
}
|
||||||
|
|
||||||
onInitialized: {
|
onInitialized: {
|
||||||
if(mainItem.searchOnEmpty || searchText != '' ) {
|
if (mainItem.searchOnEmpty || searchText != '') {
|
||||||
mainItem.loading = true
|
mainItem.loading = true
|
||||||
forceUpdate()
|
forceUpdate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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()
|
||||||
Behavior on contentY{
|
else
|
||||||
|
suggestionsProxy.displayMore()
|
||||||
|
}
|
||||||
|
Behavior on contentY {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: 500
|
duration: 500
|
||||||
easing.type: Easing.OutExpo
|
easing.type: Easing.OutExpo
|
||||||
|
|
@ -210,7 +235,7 @@ Flickable {
|
||||||
Control.ScrollBar.vertical: ScrollBar {
|
Control.ScrollBar.vertical: ScrollBar {
|
||||||
id: scrollbar
|
id: scrollbar
|
||||||
z: 1
|
z: 1
|
||||||
topPadding: 24 * DefaultStyle.dp // Avoid to be on top of collapse button
|
topPadding: 24 * DefaultStyle.dp // Avoid to be on top of collapse button
|
||||||
active: true
|
active: true
|
||||||
interactive: true
|
interactive: true
|
||||||
visible: mainItem.contentHeight > mainItem.height
|
visible: mainItem.contentHeight > mainItem.height
|
||||||
|
|
@ -220,7 +245,7 @@ Flickable {
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: contentsLayout
|
id: contentsLayout
|
||||||
width: mainItem.width
|
width: mainItem.width
|
||||||
spacing: 0//20 * DefaultStyle.dp
|
spacing: 0 //20 * DefaultStyle.dp
|
||||||
|
|
||||||
BusyIndicator {
|
BusyIndicator {
|
||||||
id: busyIndicator
|
id: busyIndicator
|
||||||
|
|
@ -232,7 +257,7 @@ Flickable {
|
||||||
Layout.alignment: Qt.AlignCenter | Qt.AlignVCenter
|
Layout.alignment: Qt.AlignCenter | Qt.AlignVCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
ContactListView{
|
ContactListView {
|
||||||
id: favoritesList
|
id: favoritesList
|
||||||
visible: contentHeight > 0
|
visible: contentHeight > 0
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
@ -252,22 +277,32 @@ 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 {
|
||||||
id: contactsList
|
id: contactsList
|
||||||
visible: contentHeight > 0
|
visible: contentHeight > 0
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
@ -286,32 +321,45 @@ 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ContactListView{
|
ContactListView {
|
||||||
id: suggestionsList
|
id: suggestionsList
|
||||||
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)
|
||||||
model:MagicSearchProxy {
|
}
|
||||||
|
onAddContactToSelection: address => {
|
||||||
|
mainItem.addContactToSelection(address)
|
||||||
|
}
|
||||||
|
onRemoveContactFromSelection: index => {
|
||||||
|
mainItem.removeContactFromSelection(
|
||||||
|
index)
|
||||||
|
}
|
||||||
|
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
|
||||||
|
|
|
||||||
|
|
@ -6,243 +6,291 @@ 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
|
||||||
implicitHeight: visible ? 56 * DefaultStyle.dp : 0
|
implicitHeight: visible ? 56 * DefaultStyle.dp : 0
|
||||||
property var searchResultItem
|
property var searchResultItem
|
||||||
property bool showInitials: true // Display Initials of Display name.
|
property bool showInitials: true // Display Initials of Display name.
|
||||||
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
|
||||||
|
|
||||||
property bool displayNameCapitalization: true // Capitalize display name.
|
|
||||||
|
|
||||||
property bool selectionEnabled: true // Contact can be selected
|
|
||||||
property bool multiSelectionEnabled: false //Multiple items can be selected.
|
|
||||||
property list<string> selectedContacts // List of default address on selected contacts.
|
|
||||||
property bool isSelected: false // selected in list => currentIndex == index
|
|
||||||
property bool isLastHovered: false
|
|
||||||
|
|
||||||
property var previousInitial // Use directly previous initial
|
|
||||||
property int itemsRightMargin: 39 * DefaultStyle.dp
|
|
||||||
|
|
||||||
property var displayName: searchResultItem.core.fullName
|
|
||||||
property string initial: displayName ? displayName[0].toLocaleLowerCase(ConstantsCpp.DefaultLocale) : ''
|
|
||||||
|
|
||||||
signal clicked(var mouse)
|
|
||||||
signal contactDeletionRequested(FriendGui contact)
|
|
||||||
signal containsMouseChanged(bool containsMouse)
|
|
||||||
|
|
||||||
Text {
|
// Bold characters in Display name.
|
||||||
id: initial
|
property bool displayNameCapitalization: true // Capitalize display name.
|
||||||
anchors.left: parent.left
|
|
||||||
visible: mainItem.showInitials
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
anchors.rightMargin: 15 * DefaultStyle.dp
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
width: 20 * DefaultStyle.dp
|
|
||||||
opacity: previousInitial != mainItem.initial ? 1 : 0
|
|
||||||
text: mainItem.initial
|
|
||||||
color: DefaultStyle.main2_400
|
|
||||||
font {
|
|
||||||
pixelSize: 20 * DefaultStyle.dp
|
|
||||||
weight: 500 * DefaultStyle.dp
|
|
||||||
capitalization: Font.AllUppercase
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RowLayout {
|
|
||||||
id: contactDelegate
|
|
||||||
anchors.left: initial.visible ? initial.right : parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: mainItem.itemsRightMargin
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
spacing: 16 * DefaultStyle.dp
|
|
||||||
z: 1
|
|
||||||
Avatar {
|
|
||||||
Layout.preferredWidth: 45 * DefaultStyle.dp
|
|
||||||
Layout.preferredHeight: 45 * DefaultStyle.dp
|
|
||||||
Layout.leftMargin: 5 * DefaultStyle.dp
|
|
||||||
contact: searchResultItem
|
|
||||||
shadowEnabled: false
|
|
||||||
}
|
|
||||||
ColumnLayout {
|
|
||||||
spacing: 0
|
|
||||||
Text {
|
|
||||||
text: UtilsCpp.boldTextPart(mainItem.displayName, mainItem.highlightText)
|
|
||||||
font{
|
|
||||||
pixelSize: mainItem.showDefaultAddress ? 16 * DefaultStyle.dp : 14 * DefaultStyle.dp
|
|
||||||
capitalization: mainItem.displayNameCapitalization ? Font.Capitalize : Font.MixedCase
|
|
||||||
weight: mainItem.showDefaultAddress ? 800 * DefaultStyle.dp : 400 * DefaultStyle.dp
|
|
||||||
}
|
|
||||||
maximumLineCount: 1
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
Layout.topMargin: 2 * DefaultStyle.dp
|
|
||||||
Layout.fillWidth: true
|
|
||||||
visible: mainItem.showDefaultAddress
|
|
||||||
property string address: SettingsCpp.onlyDisplaySipUriUsername ? UtilsCpp.getUsername(searchResultItem.core.defaultAddress) : searchResultItem.core.defaultAddress
|
|
||||||
text: UtilsCpp.boldTextPart(address, mainItem.highlightText)
|
|
||||||
maximumLineCount: 1
|
|
||||||
elide: Text.ElideRight
|
|
||||||
font {
|
|
||||||
weight: 300 * DefaultStyle.dp
|
|
||||||
pixelSize: 12 * DefaultStyle.dp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Item{Layout.fillWidth: true}
|
|
||||||
RowLayout {
|
|
||||||
id: actionsRow
|
|
||||||
z: 1
|
|
||||||
visible: actionButtons || friendPopup.visible || mainItem.multiSelectionEnabled
|
|
||||||
spacing: visible ? 16 * DefaultStyle.dp : 0
|
|
||||||
Layout.rightMargin: visible ? 10 * DefaultStyle.dp : 0
|
|
||||||
EffectImage {
|
|
||||||
id: isSelectedCheck
|
|
||||||
visible: mainItem.multiSelectionEnabled && (mainItem.selectedContacts.indexOf(searchResultItem.core.defaultAddress) != -1)
|
|
||||||
Layout.preferredWidth: 24 * DefaultStyle.dp
|
|
||||||
Layout.preferredHeight: 24 * DefaultStyle.dp
|
|
||||||
imageSource: AppIcons.check
|
|
||||||
colorizationColor: DefaultStyle.main1_500_main
|
|
||||||
}
|
|
||||||
RowLayout{
|
|
||||||
id: actionButtons
|
|
||||||
visible: mainItem.showActions
|
|
||||||
spacing: visible ? 10 * DefaultStyle.dp : 0
|
|
||||||
IconButton {
|
|
||||||
id: callButton
|
|
||||||
Layout.preferredWidth: 45 * DefaultStyle.dp
|
|
||||||
Layout.preferredHeight: 45 * DefaultStyle.dp
|
|
||||||
icon.width: 24 * DefaultStyle.dp
|
|
||||||
icon.height: 24 * DefaultStyle.dp
|
|
||||||
icon.source: AppIcons.phone
|
|
||||||
focus: visible
|
|
||||||
radius: 40 * DefaultStyle.dp
|
|
||||||
style: ButtonStyle.grey
|
|
||||||
onClicked: UtilsCpp.createCall(searchResultItem.core.defaultFullAddress)
|
|
||||||
KeyNavigation.left: chatButton
|
|
||||||
KeyNavigation.right: videoCallButton
|
|
||||||
}
|
|
||||||
IconButton {
|
|
||||||
id: videoCallButton
|
|
||||||
Layout.preferredWidth: 45 * DefaultStyle.dp
|
|
||||||
Layout.preferredHeight: 45 * DefaultStyle.dp
|
|
||||||
icon.width: 24 * DefaultStyle.dp
|
|
||||||
icon.height: 24 * DefaultStyle.dp
|
|
||||||
icon.source: AppIcons.videoCamera
|
|
||||||
focus: visible && !callButton.visible
|
|
||||||
radius: 40 * DefaultStyle.dp
|
|
||||||
style: ButtonStyle.grey
|
|
||||||
onClicked: UtilsCpp.createCall(searchResultItem.core.defaultFullAddress, {'localVideoEnabled': true})
|
|
||||||
KeyNavigation.left: callButton
|
|
||||||
KeyNavigation.right: chatButton
|
|
||||||
}
|
|
||||||
IconButton {
|
|
||||||
id: chatButton
|
|
||||||
visible: actionButtons.visible && !SettingsCpp.disableChatFeature
|
|
||||||
Layout.preferredWidth: 45 * DefaultStyle.dp
|
|
||||||
Layout.preferredHeight: 45 * DefaultStyle.dp
|
|
||||||
icon.width: 24 * DefaultStyle.dp
|
|
||||||
icon.height: 24 * DefaultStyle.dp
|
|
||||||
icon.source: AppIcons.chatTeardropText
|
|
||||||
focus: visible && !callButton.visible && !videoCallButton.visible
|
|
||||||
radius: 40 * DefaultStyle.dp
|
|
||||||
style: ButtonStyle.grey
|
|
||||||
KeyNavigation.left: videoCallButton
|
|
||||||
KeyNavigation.right: callButton
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PopupButton {
|
|
||||||
id: friendPopup
|
|
||||||
z: 1
|
|
||||||
popup.x: 0
|
|
||||||
popup.padding: 10 * DefaultStyle.dp
|
|
||||||
visible: mainItem.showContactMenu && (contactArea.containsMouse || hovered || popup.opened)
|
|
||||||
|
|
||||||
popup.contentItem: ColumnLayout {
|
|
||||||
IconLabelButton {
|
|
||||||
visible: searchResultItem.core.isStored && !searchResultItem.core.readOnly
|
|
||||||
text: searchResultItem.core.starred ? qsTr("Enlever des favoris") : qsTr("Mettre en favori")
|
|
||||||
icon.source: searchResultItem.core.starred ? AppIcons.heartFill : AppIcons.heart
|
|
||||||
spacing: 10 * DefaultStyle.dp
|
|
||||||
textColor: DefaultStyle.main2_500main
|
|
||||||
hoveredImageColor: searchResultItem.core.starred ? DefaultStyle.main1_700 : DefaultStyle.danger_700
|
|
||||||
contentImageColor: searchResultItem.core.starred ? DefaultStyle.danger_500main : DefaultStyle.main2_600
|
|
||||||
onClicked: {
|
|
||||||
searchResultItem.core.lSetStarred(!searchResultItem.core.starred)
|
|
||||||
friendPopup.close()
|
|
||||||
}
|
|
||||||
style: ButtonStyle.noBackground
|
|
||||||
}
|
|
||||||
IconLabelButton {
|
|
||||||
text: qsTr("Partager")
|
|
||||||
icon.source: AppIcons.shareNetwork
|
|
||||||
spacing: 10 * DefaultStyle.dp
|
|
||||||
textColor: DefaultStyle.main2_500main
|
|
||||||
onClicked: {
|
|
||||||
var vcard = searchResultItem.core.getVCard()
|
|
||||||
var username = searchResultItem.core.givenName + searchResultItem.core.familyName
|
|
||||||
var filepath = UtilsCpp.createVCardFile(username, vcard)
|
|
||||||
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
|
|
||||||
|
|
||||||
}
|
property bool selectionEnabled: true // Contact can be selected
|
||||||
IconLabelButton {
|
property bool multiSelectionEnabled: false //Multiple items can be selected.
|
||||||
text: qsTr("Supprimer")
|
property list<string> selectedContacts
|
||||||
icon.source: AppIcons.trashCan
|
// List of default address on selected contacts.
|
||||||
spacing: 10 * DefaultStyle.dp
|
property bool isSelected: false // selected in list => currentIndex == index
|
||||||
visible: !searchResultItem.core.readOnly
|
property bool isLastHovered: false
|
||||||
onClicked: {
|
|
||||||
mainItem.contactDeletionRequested(searchResultItem)
|
property var previousInitial
|
||||||
friendPopup.close()
|
// Use directly previous initial
|
||||||
}
|
property int itemsRightMargin: 39 * DefaultStyle.dp
|
||||||
style: ButtonStyle.noBackgroundRed
|
|
||||||
}
|
property var displayName: searchResultItem.core.fullName
|
||||||
}
|
property string initial: displayName ? displayName[0].toLocaleLowerCase(
|
||||||
}
|
ConstantsCpp.DefaultLocale) : ''
|
||||||
}
|
|
||||||
}
|
signal clicked(var mouse)
|
||||||
|
signal contactDeletionRequested(FriendGui contact)
|
||||||
MouseArea {
|
signal containsMouseChanged(bool containsMouse)
|
||||||
id: contactArea
|
|
||||||
enabled: mainItem.selectionEnabled
|
Text {
|
||||||
anchors.fill: contactDelegate
|
id: initial
|
||||||
//height: mainItem.height
|
anchors.left: parent.left
|
||||||
hoverEnabled: true
|
visible: mainItem.showInitials
|
||||||
acceptedButtons: Qt.AllButtons
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
z: -1
|
anchors.rightMargin: 15 * DefaultStyle.dp
|
||||||
focus: !actionButtons.visible
|
verticalAlignment: Text.AlignVCenter
|
||||||
onContainsMouseChanged: {
|
width: 20 * DefaultStyle.dp
|
||||||
mainItem.containsMouseChanged(containsMouse)
|
opacity: previousInitial != mainItem.initial ? 1 : 0
|
||||||
}
|
text: mainItem.initial
|
||||||
Rectangle {
|
color: DefaultStyle.main2_400
|
||||||
anchors.fill: contactArea
|
font {
|
||||||
radius: 8 * DefaultStyle.dp
|
pixelSize: 20 * DefaultStyle.dp
|
||||||
opacity: 0.7
|
weight: 500 * DefaultStyle.dp
|
||||||
color: mainItem.isSelected ? DefaultStyle.main2_200 : DefaultStyle.main2_100
|
capitalization: Font.AllUppercase
|
||||||
visible: mainItem.isLastHovered || friendPopup.hovered || mainItem.isSelected || friendPopup.visible
|
}
|
||||||
}
|
}
|
||||||
Keys.onPressed: (event)=> {
|
RowLayout {
|
||||||
if (event.key == Qt.Key_Space || event.key == Qt.Key_Enter || event.key == Qt.Key_Return) {
|
id: contactDelegate
|
||||||
contactArea.clicked(undefined)
|
anchors.left: initial.visible ? initial.right : parent.left
|
||||||
event.accepted = true;
|
anchors.right: parent.right
|
||||||
}
|
anchors.rightMargin: mainItem.itemsRightMargin
|
||||||
}
|
anchors.top: parent.top
|
||||||
onClicked: (mouse) => {
|
anchors.bottom: parent.bottom
|
||||||
forceActiveFocus()
|
spacing: 16 * DefaultStyle.dp
|
||||||
if (mouse && mouse.button == Qt.RightButton && mainItem.showContactMenu) {
|
z: 1
|
||||||
friendPopup.open()
|
Avatar {
|
||||||
} else {
|
Layout.preferredWidth: 45 * DefaultStyle.dp
|
||||||
mainItem.clicked(mouse)
|
Layout.preferredHeight: 45 * DefaultStyle.dp
|
||||||
}
|
Layout.leftMargin: 5 * DefaultStyle.dp
|
||||||
}
|
contact: searchResultItem
|
||||||
}
|
shadowEnabled: false
|
||||||
|
}
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: 0
|
||||||
|
Text {
|
||||||
|
text: UtilsCpp.boldTextPart(mainItem.displayName,
|
||||||
|
mainItem.highlightText)
|
||||||
|
font {
|
||||||
|
pixelSize: mainItem.showDefaultAddress ? 16 * DefaultStyle.dp : 14
|
||||||
|
* DefaultStyle.dp
|
||||||
|
capitalization: mainItem.displayNameCapitalization ? Font.Capitalize : Font.MixedCase
|
||||||
|
weight: mainItem.showDefaultAddress ? 800 * DefaultStyle.dp : 400
|
||||||
|
* DefaultStyle.dp
|
||||||
|
}
|
||||||
|
maximumLineCount: 1
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
Layout.topMargin: 2 * DefaultStyle.dp
|
||||||
|
Layout.fillWidth: true
|
||||||
|
visible: mainItem.showDefaultAddress
|
||||||
|
property string address: SettingsCpp.onlyDisplaySipUriUsername ? UtilsCpp.getUsername(searchResultItem.core.defaultAddress) : searchResultItem.core.defaultAddress
|
||||||
|
text: UtilsCpp.boldTextPart(address, mainItem.highlightText)
|
||||||
|
maximumLineCount: 1
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font {
|
||||||
|
weight: 300 * DefaultStyle.dp
|
||||||
|
pixelSize: 12 * DefaultStyle.dp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Item {
|
||||||
|
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
|
||||||
|
z: 1
|
||||||
|
visible: actionButtons.visible || friendPopup.visible
|
||||||
|
|| mainItem.multiSelectionEnabled
|
||||||
|
spacing: visible ? 16 * DefaultStyle.dp : 0
|
||||||
|
enabled: visible
|
||||||
|
EffectImage {
|
||||||
|
id: isSelectedCheck
|
||||||
|
visible: mainItem.multiSelectionEnabled
|
||||||
|
&& (mainItem.selectedContacts.indexOf(
|
||||||
|
searchResultItem.core.defaultAddress) != -1)
|
||||||
|
Layout.preferredWidth: 24 * DefaultStyle.dp
|
||||||
|
Layout.preferredHeight: 24 * DefaultStyle.dp
|
||||||
|
imageSource: AppIcons.check
|
||||||
|
colorizationColor: DefaultStyle.main1_500_main
|
||||||
|
}
|
||||||
|
RowLayout {
|
||||||
|
id: actionButtons
|
||||||
|
visible: mainItem.showActions
|
||||||
|
spacing: visible ? 10 * DefaultStyle.dp : 0
|
||||||
|
IconButton {
|
||||||
|
id: callButton
|
||||||
|
Layout.preferredWidth: 45 * DefaultStyle.dp
|
||||||
|
Layout.preferredHeight: 45 * DefaultStyle.dp
|
||||||
|
icon.width: 24 * DefaultStyle.dp
|
||||||
|
icon.height: 24 * DefaultStyle.dp
|
||||||
|
icon.source: AppIcons.phone
|
||||||
|
focus: visible
|
||||||
|
radius: 40 * DefaultStyle.dp
|
||||||
|
style: ButtonStyle.grey
|
||||||
|
onClicked: UtilsCpp.createCall(
|
||||||
|
searchResultItem.core.defaultFullAddress)
|
||||||
|
KeyNavigation.left: chatButton
|
||||||
|
KeyNavigation.right: videoCallButton
|
||||||
|
}
|
||||||
|
IconButton {
|
||||||
|
id: videoCallButton
|
||||||
|
Layout.preferredWidth: 45 * DefaultStyle.dp
|
||||||
|
Layout.preferredHeight: 45 * DefaultStyle.dp
|
||||||
|
icon.width: 24 * DefaultStyle.dp
|
||||||
|
icon.height: 24 * DefaultStyle.dp
|
||||||
|
icon.source: AppIcons.videoCamera
|
||||||
|
focus: visible && !callButton.visible
|
||||||
|
radius: 40 * DefaultStyle.dp
|
||||||
|
style: ButtonStyle.grey
|
||||||
|
onClicked: UtilsCpp.createCall(
|
||||||
|
searchResultItem.core.defaultFullAddress,
|
||||||
|
{
|
||||||
|
"localVideoEnabled": true
|
||||||
|
})
|
||||||
|
KeyNavigation.left: callButton
|
||||||
|
KeyNavigation.right: chatButton
|
||||||
|
}
|
||||||
|
IconButton {
|
||||||
|
id: chatButton
|
||||||
|
visible: actionButtons.visible
|
||||||
|
&& !SettingsCpp.disableChatFeature
|
||||||
|
Layout.preferredWidth: 45 * DefaultStyle.dp
|
||||||
|
Layout.preferredHeight: 45 * DefaultStyle.dp
|
||||||
|
icon.width: 24 * DefaultStyle.dp
|
||||||
|
icon.height: 24 * DefaultStyle.dp
|
||||||
|
icon.source: AppIcons.chatTeardropText
|
||||||
|
focus: visible && !callButton.visible
|
||||||
|
&& !videoCallButton.visible
|
||||||
|
radius: 40 * DefaultStyle.dp
|
||||||
|
style: ButtonStyle.grey
|
||||||
|
KeyNavigation.left: videoCallButton
|
||||||
|
KeyNavigation.right: callButton
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PopupButton {
|
||||||
|
id: friendPopup
|
||||||
|
z: 1
|
||||||
|
popup.x: 0
|
||||||
|
popup.padding: 10 * DefaultStyle.dp
|
||||||
|
visible: mainItem.showContactMenu
|
||||||
|
&& (contactArea.containsMouse || hovered
|
||||||
|
|| popup.opened)
|
||||||
|
enabled: visible
|
||||||
|
|
||||||
|
popup.contentItem: ColumnLayout {
|
||||||
|
IconLabelButton {
|
||||||
|
visible: searchResultItem.core.isStored
|
||||||
|
&& !searchResultItem.core.readOnly
|
||||||
|
text: searchResultItem.core.starred ? qsTr(
|
||||||
|
"Enlever des favoris") : qsTr(
|
||||||
|
"Mettre en favori")
|
||||||
|
icon.source: searchResultItem.core.starred ? AppIcons.heartFill : AppIcons.heart
|
||||||
|
spacing: 10 * DefaultStyle.dp
|
||||||
|
textColor: DefaultStyle.main2_500main
|
||||||
|
hoveredImageColor: searchResultItem.core.starred ? DefaultStyle.main1_700 : DefaultStyle.danger_700
|
||||||
|
contentImageColor: searchResultItem.core.starred ? DefaultStyle.danger_500main : DefaultStyle.main2_600
|
||||||
|
onClicked: {
|
||||||
|
searchResultItem.core.lSetStarred(
|
||||||
|
!searchResultItem.core.starred)
|
||||||
|
friendPopup.close()
|
||||||
|
}
|
||||||
|
style: ButtonStyle.noBackground
|
||||||
|
}
|
||||||
|
IconLabelButton {
|
||||||
|
text: qsTr("Partager")
|
||||||
|
icon.source: AppIcons.shareNetwork
|
||||||
|
spacing: 10 * DefaultStyle.dp
|
||||||
|
textColor: DefaultStyle.main2_500main
|
||||||
|
onClicked: {
|
||||||
|
var vcard = searchResultItem.core.getVCard()
|
||||||
|
var username = searchResultItem.core.givenName
|
||||||
|
+ searchResultItem.core.familyName
|
||||||
|
var filepath = UtilsCpp.createVCardFile(
|
||||||
|
username, vcard)
|
||||||
|
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
|
||||||
|
}
|
||||||
|
IconLabelButton {
|
||||||
|
text: qsTr("Supprimer")
|
||||||
|
icon.source: AppIcons.trashCan
|
||||||
|
spacing: 10 * DefaultStyle.dp
|
||||||
|
visible: !searchResultItem.core.readOnly
|
||||||
|
onClicked: {
|
||||||
|
mainItem.contactDeletionRequested(
|
||||||
|
searchResultItem)
|
||||||
|
friendPopup.close()
|
||||||
|
}
|
||||||
|
style: ButtonStyle.noBackgroundRed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: contactArea
|
||||||
|
enabled: mainItem.selectionEnabled
|
||||||
|
anchors.fill: contactDelegate
|
||||||
|
//height: mainItem.height
|
||||||
|
hoverEnabled: true
|
||||||
|
acceptedButtons: Qt.AllButtons
|
||||||
|
z: -1
|
||||||
|
focus: !buttonsLayoutLoader.active
|
||||||
|
onContainsMouseChanged: {
|
||||||
|
mainItem.containsMouseChanged(containsMouse)
|
||||||
|
}
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: contactArea
|
||||||
|
radius: 8 * DefaultStyle.dp
|
||||||
|
opacity: 0.7
|
||||||
|
color: mainItem.isSelected ? DefaultStyle.main2_200 : DefaultStyle.main2_100
|
||||||
|
visible: mainItem.isLastHovered || mainItem.isSelected
|
||||||
|
}
|
||||||
|
Keys.onPressed: event => {
|
||||||
|
if (event.key == Qt.Key_Space
|
||||||
|
|| event.key == Qt.Key_Enter
|
||||||
|
|| event.key == Qt.Key_Return) {
|
||||||
|
contactArea.clicked(undefined)
|
||||||
|
event.accepted = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onClicked: mouse => {
|
||||||
|
forceActiveFocus()
|
||||||
|
if (mouse && mouse.button == Qt.RightButton
|
||||||
|
&& mainItem.showContactMenu) {
|
||||||
|
friendPopup.open()
|
||||||
|
} else {
|
||||||
|
mainItem.clicked(mouse)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue