mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-17 11:28:07 +00:00
call history in separated file
This commit is contained in:
parent
743a909bb1
commit
c0dd721da1
4 changed files with 234 additions and 198 deletions
|
|
@ -45,6 +45,7 @@ list(APPEND _LINPHONEAPP_QML_FILES
|
|||
view/Control/Display/Text.qml
|
||||
view/Control/Display/ToolTip.qml
|
||||
view/Control/Display/Call/CallListView.qml
|
||||
view/Control/Display/Call/CallHistoryListView.qml
|
||||
view/Control/Display/Call/CallStatistics.qml
|
||||
view/Control/Display/Contact/Avatar.qml
|
||||
view/Control/Display/Contact/Contact.qml
|
||||
|
|
|
|||
227
Linphone/view/Control/Display/Call/CallHistoryListView.qml
Normal file
227
Linphone/view/Control/Display/Call/CallHistoryListView.qml
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
import QtQuick
|
||||
import QtQuick.Effects
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls.Basic as Control
|
||||
import Linphone
|
||||
import UtilsCpp
|
||||
import SettingsCpp
|
||||
import 'qrc:/qt/qml/Linphone/view/Style/buttonStyle.js' as ButtonStyle
|
||||
import 'qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js' as Utils
|
||||
|
||||
ListView {
|
||||
id: mainItem
|
||||
clip: true
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
property SearchBar searchBar
|
||||
property bool loading: false
|
||||
property string searchText: searchBar.text
|
||||
|
||||
signal resultsReceived()
|
||||
|
||||
onResultsReceived: {
|
||||
loading = false
|
||||
// contentY = 0
|
||||
}
|
||||
onSearchTextChanged: loading = true
|
||||
|
||||
model: CallHistoryProxy {
|
||||
id: callHistoryProxy
|
||||
filterText: searchBar.text
|
||||
onFilterTextChanged: maxDisplayItems = initialDisplayItems
|
||||
initialDisplayItems: Math.max(20, 2 * mainItem.height / (56 * DefaultStyle.dp))
|
||||
displayItemsStep: 3 * initialDisplayItems / 2
|
||||
onModelReset: {
|
||||
console.log("model reset================")
|
||||
mainItem.resultsReceived()
|
||||
}
|
||||
}
|
||||
cacheBuffer: contentHeight>0 ? contentHeight : 0// cache all items
|
||||
flickDeceleration: 10000
|
||||
spacing: 10 * DefaultStyle.dp
|
||||
|
||||
Keys.onPressed: (event) => {
|
||||
if(event.key == Qt.Key_Escape){
|
||||
console.log("Back")
|
||||
searchBar.forceActiveFocus()
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
// remove binding loop
|
||||
onContentHeightChanged: Qt.callLater(function(){
|
||||
mainItem.cacheBuffer = Math.max(contentHeight,0)
|
||||
})
|
||||
onActiveFocusChanged: if(activeFocus && currentIndex < 0 && count > 0) currentIndex = 0
|
||||
onCountChanged: {
|
||||
if(currentIndex < 0 && count > 0){
|
||||
mainItem.currentIndex = 0 // Select first item after loading model
|
||||
}
|
||||
if(atYBeginning)
|
||||
positionViewAtBeginning()// Stay at beginning
|
||||
}
|
||||
Connections {
|
||||
target: deleteHistoryPopup
|
||||
function onAccepted() {
|
||||
mainItem.model.removeAllEntries()
|
||||
}
|
||||
}
|
||||
|
||||
onAtYEndChanged: {
|
||||
if(atYEnd && count > 0){
|
||||
callHistoryProxy.displayMore()
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------
|
||||
function moveToCurrentItem(){
|
||||
if( mainItem.currentIndex >= 0)
|
||||
Utils.updatePosition(mainItem, mainItem)
|
||||
}
|
||||
onCurrentItemChanged: {
|
||||
moveToCurrentItem()
|
||||
}
|
||||
// Update position only if we are moving to current item and its position is changing.
|
||||
property var _currentItemY: currentItem?.y
|
||||
on_CurrentItemYChanged: if(_currentItemY && moveAnimation.running){
|
||||
moveToCurrentItem()
|
||||
}
|
||||
Behavior on contentY{
|
||||
NumberAnimation {
|
||||
id: moveAnimation
|
||||
duration: 500
|
||||
easing.type: Easing.OutExpo
|
||||
alwaysRunToEnd: true
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------
|
||||
|
||||
|
||||
onVisibleChanged: {
|
||||
if (!visible) currentIndex = -1
|
||||
}
|
||||
// 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.
|
||||
property int lastMouseContainsIndex: -1
|
||||
delegate: FocusScope {
|
||||
width:mainItem.width
|
||||
height: 56 * DefaultStyle.dp
|
||||
visible: !!modelData
|
||||
|
||||
RowLayout {
|
||||
z: 1
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 10 * DefaultStyle.dp
|
||||
spacing: 10 * DefaultStyle.dp
|
||||
Avatar {
|
||||
id: historyAvatar
|
||||
property var contactObj: UtilsCpp.findFriendByAddress(modelData.core.remoteAddress)
|
||||
contact: contactObj?.value || null
|
||||
_address: modelData.core.conferenceInfo
|
||||
? modelData.core.conferenceInfo.core.subject
|
||||
: modelData.core.remoteAddress
|
||||
secured: securityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
|
||||
width: 45 * DefaultStyle.dp
|
||||
height: 45 * DefaultStyle.dp
|
||||
isConference: modelData.core.isConference
|
||||
}
|
||||
ColumnLayout {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
spacing: 5 * DefaultStyle.dp
|
||||
Text {
|
||||
id: friendAddress
|
||||
Layout.fillWidth: true
|
||||
maximumLineCount: 1
|
||||
text: historyAvatar.displayNameVal
|
||||
font {
|
||||
pixelSize: 14 * DefaultStyle.dp
|
||||
weight: 400 * DefaultStyle.dp
|
||||
capitalization: Font.Capitalize
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
spacing: 6 * DefaultStyle.dp
|
||||
EffectImage {
|
||||
id: statusIcon
|
||||
imageSource: modelData.core.status === LinphoneEnums.CallStatus.Declined
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.Aborted
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted
|
||||
? AppIcons.arrowElbow
|
||||
: modelData.core.isOutgoing
|
||||
? AppIcons.arrowUpRight
|
||||
: AppIcons.arrowDownLeft
|
||||
colorizationColor: modelData.core.status === LinphoneEnums.CallStatus.Declined
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.Aborted
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.Missed
|
||||
? DefaultStyle.danger_500main
|
||||
: modelData.core.isOutgoing
|
||||
? DefaultStyle.info_500_main
|
||||
: DefaultStyle.success_500main
|
||||
Layout.preferredWidth: 12 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 12 * DefaultStyle.dp
|
||||
transform: Rotation {
|
||||
angle: modelData.core.isOutgoing && (modelData.core.status === LinphoneEnums.CallStatus.Declined
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.Aborted
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted) ? 180 : 0
|
||||
origin {
|
||||
x: statusIcon.width/2
|
||||
y: statusIcon.height/2
|
||||
}
|
||||
}
|
||||
}
|
||||
Text {
|
||||
// text: modelData.core.date
|
||||
text: UtilsCpp.formatDate(modelData.core.date)
|
||||
font {
|
||||
pixelSize: 12 * DefaultStyle.dp
|
||||
weight: 300 * DefaultStyle.dp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BigButton {
|
||||
style: ButtonStyle.noBackground
|
||||
icon.source: AppIcons.phone
|
||||
focus: true
|
||||
activeFocusOnTab: false
|
||||
onClicked: {
|
||||
if (modelData.core.isConference) {
|
||||
var callsWindow = UtilsCpp.getCallsWindow()
|
||||
callsWindow.setupConference(modelData.core.conferenceInfo)
|
||||
UtilsCpp.smartShowWindow(callsWindow)
|
||||
}
|
||||
else {
|
||||
UtilsCpp.createCall(modelData.core.remoteAddress)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
hoverEnabled: true
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
onContainsMouseChanged: {
|
||||
if(containsMouse)
|
||||
mainItem.lastMouseContainsIndex = index
|
||||
else if( mainItem.lastMouseContainsIndex == index)
|
||||
mainItem.lastMouseContainsIndex = -1
|
||||
}
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
opacity: 0.7
|
||||
radius: 8 * DefaultStyle.dp
|
||||
color: mainItem.currentIndex === index ? DefaultStyle.main2_200 : DefaultStyle.main2_100
|
||||
visible: mainItem.lastMouseContainsIndex === index || mainItem.currentIndex === index
|
||||
}
|
||||
onPressed: {
|
||||
mainItem.currentIndex = model.index
|
||||
mainItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Control.ScrollBar.vertical: scrollbar
|
||||
}
|
||||
|
|
@ -32,7 +32,7 @@ LoginLayout {
|
|||
}
|
||||
EffectImage {
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: AppIcons.profile
|
||||
imageSource: AppIcons.profile
|
||||
Layout.preferredHeight: 34 * DefaultStyle.dp
|
||||
Layout.preferredWidth: 34 * DefaultStyle.dp
|
||||
colorizationColor: DefaultStyle.main2_600
|
||||
|
|
|
|||
|
|
@ -214,213 +214,21 @@ AbstractMainPage {
|
|||
weight: 800 * DefaultStyle.dp
|
||||
}
|
||||
}
|
||||
ListView {
|
||||
CallHistoryListView {
|
||||
id: historyListView
|
||||
clip: true
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
model: CallHistoryProxy {
|
||||
id: callHistoryProxy
|
||||
filterText: searchBar.text
|
||||
onFilterTextChanged: maxDisplayItems = initialDisplayItems
|
||||
initialDisplayItems: Math.max(20, 2 * historyListView.height / (56 * DefaultStyle.dp))
|
||||
displayItemsStep: 3 * initialDisplayItems / 2
|
||||
}
|
||||
cacheBuffer: contentHeight>0 ? contentHeight : 0// cache all items
|
||||
flickDeceleration: 10000
|
||||
spacing: 10 * DefaultStyle.dp
|
||||
|
||||
Keys.onPressed: (event) => {
|
||||
if(event.key == Qt.Key_Escape){
|
||||
console.log("Back")
|
||||
searchBar.forceActiveFocus()
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
// remove binding loop
|
||||
onContentHeightChanged: Qt.callLater(function(){
|
||||
historyListView.cacheBuffer = Math.max(contentHeight,0)
|
||||
})
|
||||
onActiveFocusChanged: if(activeFocus && currentIndex < 0 && count > 0) currentIndex = 0
|
||||
onCountChanged: {
|
||||
if(currentIndex < 0 && count > 0){
|
||||
historyListView.currentIndex = 0 // Select first item after loading model
|
||||
}
|
||||
if(atYBeginning)
|
||||
positionViewAtBeginning()// Stay at beginning
|
||||
}
|
||||
Connections {
|
||||
target: deleteHistoryPopup
|
||||
function onAccepted() {
|
||||
historyListView.model.removeAllEntries()
|
||||
}
|
||||
}
|
||||
searchBar: searchBar
|
||||
Connections{
|
||||
target: mainItem
|
||||
function onListViewUpdated(){
|
||||
callHistoryProxy.reload()
|
||||
historyListView.model.reload()
|
||||
}
|
||||
}
|
||||
onAtYEndChanged: {
|
||||
if(atYEnd && count > 0){
|
||||
callHistoryProxy.displayMore()
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------
|
||||
function moveToCurrentItem(){
|
||||
if( historyListView.currentIndex >= 0)
|
||||
Utils.updatePosition(historyListView, historyListView)
|
||||
}
|
||||
onCurrentItemChanged: {
|
||||
moveToCurrentItem()
|
||||
}
|
||||
// Update position only if we are moving to current item and its position is changing.
|
||||
property var _currentItemY: currentItem?.y
|
||||
on_CurrentItemYChanged: if(_currentItemY && moveAnimation.running){
|
||||
moveToCurrentItem()
|
||||
}
|
||||
Behavior on contentY{
|
||||
NumberAnimation {
|
||||
id: moveAnimation
|
||||
duration: 500
|
||||
easing.type: Easing.OutExpo
|
||||
alwaysRunToEnd: true
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------
|
||||
|
||||
onCurrentIndexChanged: {
|
||||
mainItem.selectedRowHistoryGui = model.getAt(currentIndex)
|
||||
}
|
||||
onVisibleChanged: {
|
||||
if (!visible) currentIndex = -1
|
||||
onCountChanged: {
|
||||
mainItem.selectedRowHistoryGui = model.getAt(currentIndex)
|
||||
}
|
||||
// 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.
|
||||
property int lastMouseContainsIndex: -1
|
||||
delegate: FocusScope {
|
||||
width:historyListView.width
|
||||
height: 56 * DefaultStyle.dp
|
||||
visible: !!modelData
|
||||
|
||||
RowLayout {
|
||||
z: 1
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 10 * DefaultStyle.dp
|
||||
spacing: 10 * DefaultStyle.dp
|
||||
Avatar {
|
||||
id: historyAvatar
|
||||
property var contactObj: UtilsCpp.findFriendByAddress(modelData.core.remoteAddress)
|
||||
contact: contactObj?.value || null
|
||||
_address: modelData.core.conferenceInfo
|
||||
? modelData.core.conferenceInfo.core.subject
|
||||
: modelData.core.remoteAddress
|
||||
secured: securityLevel === LinphoneEnums.SecurityLevel.EndToEndEncryptedAndVerified
|
||||
width: 45 * DefaultStyle.dp
|
||||
height: 45 * DefaultStyle.dp
|
||||
isConference: modelData.core.isConference
|
||||
}
|
||||
ColumnLayout {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
spacing: 5 * DefaultStyle.dp
|
||||
Text {
|
||||
id: friendAddress
|
||||
Layout.fillWidth: true
|
||||
maximumLineCount: 1
|
||||
text: historyAvatar.displayNameVal
|
||||
font {
|
||||
pixelSize: 14 * DefaultStyle.dp
|
||||
weight: 400 * DefaultStyle.dp
|
||||
capitalization: Font.Capitalize
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
spacing: 6 * DefaultStyle.dp
|
||||
EffectImage {
|
||||
id: statusIcon
|
||||
imageSource: modelData.core.status === LinphoneEnums.CallStatus.Declined
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.Aborted
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted
|
||||
? AppIcons.arrowElbow
|
||||
: modelData.core.isOutgoing
|
||||
? AppIcons.arrowUpRight
|
||||
: AppIcons.arrowDownLeft
|
||||
colorizationColor: modelData.core.status === LinphoneEnums.CallStatus.Declined
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.Aborted
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.Missed
|
||||
? DefaultStyle.danger_500main
|
||||
: modelData.core.isOutgoing
|
||||
? DefaultStyle.info_500_main
|
||||
: DefaultStyle.success_500main
|
||||
Layout.preferredWidth: 12 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 12 * DefaultStyle.dp
|
||||
transform: Rotation {
|
||||
angle: modelData.core.isOutgoing && (modelData.core.status === LinphoneEnums.CallStatus.Declined
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.Aborted
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted) ? 180 : 0
|
||||
origin {
|
||||
x: statusIcon.width/2
|
||||
y: statusIcon.height/2
|
||||
}
|
||||
}
|
||||
}
|
||||
Text {
|
||||
// text: modelData.core.date
|
||||
text: UtilsCpp.formatDate(modelData.core.date)
|
||||
font {
|
||||
pixelSize: 12 * DefaultStyle.dp
|
||||
weight: 300 * DefaultStyle.dp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BigButton {
|
||||
style: ButtonStyle.noBackground
|
||||
icon.source: AppIcons.phone
|
||||
focus: true
|
||||
activeFocusOnTab: false
|
||||
onClicked: {
|
||||
if (modelData.core.isConference) {
|
||||
var callsWindow = UtilsCpp.getCallsWindow()
|
||||
callsWindow.setupConference(modelData.core.conferenceInfo)
|
||||
UtilsCpp.smartShowWindow(callsWindow)
|
||||
}
|
||||
else {
|
||||
UtilsCpp.createCall(modelData.core.remoteAddress)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
hoverEnabled: true
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
onContainsMouseChanged: {
|
||||
if(containsMouse)
|
||||
historyListView.lastMouseContainsIndex = index
|
||||
else if( historyListView.lastMouseContainsIndex == index)
|
||||
historyListView.lastMouseContainsIndex = -1
|
||||
}
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
opacity: 0.7
|
||||
radius: 8 * DefaultStyle.dp
|
||||
color: historyListView.currentIndex === index ? DefaultStyle.main2_200 : DefaultStyle.main2_100
|
||||
visible: historyListView.lastMouseContainsIndex === index || historyListView.currentIndex === index
|
||||
}
|
||||
onPressed: {
|
||||
historyListView.currentIndex = model.index
|
||||
historyListView.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Control.ScrollBar.vertical: scrollbar
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue