mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-30 02:19:23 +00:00
only show address for suggestions do not refresh devices if current account is null fix crash add error message on account parameters saved and apply changes on text changed instead of edited (fix #LINQT-1935) fix disable meeting feature setting in wrong thread destroy parameter page when closed (to avoid multiplied connections) fix show/add contact in conversation info
233 lines
7.6 KiB
QML
233 lines
7.6 KiB
QML
import QtQuick
|
|
import QtQuick.Layouts
|
|
import QtQuick.Controls.Basic as Control
|
|
|
|
import Linphone
|
|
import UtilsCpp 1.0
|
|
import ConstantsCpp 1.0
|
|
import SettingsCpp
|
|
import 'qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js' as Utils
|
|
import 'qrc:/qt/qml/Linphone/view/Style/buttonStyle.js' as ButtonStyle
|
|
|
|
ListView {
|
|
id: mainItem
|
|
|
|
property string title
|
|
property bool showInitials: true // Display Initials of Display name.
|
|
property bool showDefaultAddress: true // Display address below display name.
|
|
property bool showDisplayName: true // Display name above address.
|
|
property bool showActions: false // Display actions layout (call buttons)
|
|
property bool showContactMenu: true // Display the dot menu for contacts.
|
|
property bool showFavorites: true // Display the favorites in the header
|
|
property bool hideSuggestions: false // Hide not stored contacts (not suggestions)
|
|
property string highlightText: searchText // Bold characters in Display name.
|
|
property var sourceFlags: LinphoneEnums.MagicSearchSource.All
|
|
|
|
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 FriendGui highlightedContact
|
|
|
|
// Model properties
|
|
// set searchBarText without specifying a model to bold
|
|
// matching names
|
|
property string searchText
|
|
property ConferenceInfoGui confInfoGui
|
|
|
|
property bool haveFavorites: false
|
|
property bool haveContacts: count > 0
|
|
property real sectionsPixelSize: Typography.h4.pixelSize
|
|
property real sectionsWeight: Typography.h4.weight
|
|
property real sectionsSpacing: Math.round(18 * DefaultStyle.dp)
|
|
|
|
property real itemsRightMargin: Math.round(39 * DefaultStyle.dp)
|
|
property bool expanded: true
|
|
property real headerHeight: headerItem?.height
|
|
|
|
signal contactDeletionRequested(FriendGui contact)
|
|
signal contactSelected(FriendGui contact) // Click/Space/Enter
|
|
signal addContactToSelection(var address)
|
|
signal removeContactFromSelection(var indexInSelection)
|
|
signal updatePosition()
|
|
|
|
clip: true
|
|
highlightFollowsCurrentItem: false
|
|
cacheBuffer: 400
|
|
implicitHeight: contentHeight
|
|
spacing: expanded ? Math.round(4 * DefaultStyle.dp) : 0
|
|
|
|
onVisibleChanged: if (visible && !expanded) expanded = true
|
|
|
|
onYChanged: updatePosition()
|
|
|
|
// 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
|
|
|
|
property bool _moveToIndex: false
|
|
|
|
function selectIndex(index){
|
|
if(mainItem.expanded && index >= 0){
|
|
mainItem.currentIndex = index
|
|
var item = itemAtIndex(mainItem.currentIndex)
|
|
if(item){// Item is ready and available
|
|
mainItem.highlightedContact = item.searchResultItem
|
|
item.forceActiveFocus()
|
|
updatePosition()
|
|
_moveToIndex = false
|
|
}else{// Move on the next items load.
|
|
// If visible, try to wait loading
|
|
_moveToIndex = visible
|
|
}
|
|
}else{
|
|
mainItem.currentIndex = -1
|
|
mainItem.highlightedContact = null
|
|
if(headerItem) {
|
|
headerItem.forceActiveFocus()
|
|
}
|
|
_moveToIndex = false
|
|
}
|
|
}
|
|
onContactSelected: updatePosition()
|
|
onExpandedChanged: if(!expanded) updatePosition()
|
|
keyNavigationEnabled: false
|
|
Keys.onPressed: (event)=> {
|
|
if(event.key == Qt.Key_Up || event.key == Qt.Key_Down){
|
|
if(event.key == Qt.Key_Up && !headerItem.activeFocus) {
|
|
if(currentIndex >= 0 ) {
|
|
selectIndex(mainItem.currentIndex-1)
|
|
event.accepted = true;
|
|
}
|
|
}else if(event.key == Qt.Key_Down && mainItem.expanded){
|
|
if(currentIndex < model.count - 1) {
|
|
selectIndex(mainItem.currentIndex+1)
|
|
event.accepted = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Component.onCompleted: {
|
|
if (confInfoGui) {
|
|
for(var i = 0; i < confInfoGui.core.participants.length; ++i) {
|
|
selectedContacts.push(confInfoGui.core.getParticipantAddressAt(i));
|
|
}
|
|
}
|
|
}
|
|
|
|
Connections {
|
|
target: SettingsCpp
|
|
onLdapConfigChanged: {
|
|
if (SettingsCpp.syncLdapContacts)
|
|
magicSearchProxy.forceUpdate()
|
|
}
|
|
}
|
|
// Workaround: itemAtIndex and count are decorellated and are not enough to know when the ListView has load all its children.
|
|
// So when itemAtIndex is not available, start this timer along count changed signal.
|
|
Timer{
|
|
id: delaySelection
|
|
interval: 100
|
|
running: _moveToIndex
|
|
onTriggered: {
|
|
_moveToIndex = false
|
|
if(count > mainItem.currentIndex) selectIndex(mainItem.currentIndex)
|
|
else{
|
|
_moveToIndex = true
|
|
}
|
|
}
|
|
}
|
|
|
|
header: FocusScope{
|
|
id: headerItem
|
|
width: mainItem.width
|
|
height: headerContents.implicitHeight
|
|
|
|
ColumnLayout {
|
|
id: headerContents
|
|
width: parent.width
|
|
spacing: 0
|
|
Item{// Do not use directly RowLayout : there is an issue where the layout doesn't update on visible
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: mainItem.count > 0 ? headerTitleLayout.implicitHeight : 0
|
|
Layout.bottomMargin: Math.round(4 * DefaultStyle.dp)
|
|
RowLayout {
|
|
id: headerTitleLayout
|
|
anchors.fill: parent
|
|
spacing: 0
|
|
// Need this because it can stay at 0 on display without manual relayouting (moving position, resize)
|
|
visible: mainItem.count > 0
|
|
Text {
|
|
text: mainItem.title
|
|
font {
|
|
pixelSize: sectionsPixelSize
|
|
weight: sectionsWeight
|
|
}
|
|
}
|
|
Item {
|
|
Layout.fillWidth: true
|
|
}
|
|
RoundButton {
|
|
id: headerExpandButton
|
|
style: ButtonStyle.noBackground
|
|
icon.source: mainItem.expanded ? AppIcons.upArrow : AppIcons.downArrow
|
|
Layout.rightMargin: mainItem.itemsRightMargin
|
|
focus: true
|
|
onClicked: mainItem.expanded = !mainItem.expanded
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
delegate: ContactListItem{
|
|
id: contactItem
|
|
width: mainItem.width
|
|
focus: true
|
|
visible: mainItem.expanded
|
|
searchResultItem: $modelData
|
|
showInitials: mainItem.showInitials && isStored
|
|
showDefaultAddress: mainItem.showDefaultAddress
|
|
showDisplayName: mainItem.showDisplayName
|
|
showActions: mainItem.showActions
|
|
showContactMenu: mainItem.showContactMenu && searchResultItem.core.isStored
|
|
highlightText: mainItem.highlightText
|
|
displayNameCapitalization: mainItem.displayNameCapitalization
|
|
|
|
selectionEnabled: mainItem.selectionEnabled
|
|
multiSelectionEnabled: mainItem.multiSelectionEnabled
|
|
selectedContacts: mainItem.selectedContacts
|
|
isSelected: mainItem.highlightedContact && mainItem.highlightedContact.core == searchResultItem.core
|
|
isLastHovered: mainItem.lastMouseContainsIndex == index
|
|
previousInitial: mainItem.itemAtIndex(index-1)?.initial
|
|
itemsRightMargin: mainItem.itemsRightMargin
|
|
|
|
onIsSelectedChanged: if(isSelected) mainItem.currentIndex = index
|
|
onContactDeletionRequested: (contact) => mainItem.contactDeletionRequested(contact)
|
|
|
|
onClicked: (mouse) => {
|
|
if (mouse && mouse.button == Qt.RightButton) {
|
|
friendPopup.open()
|
|
} else {
|
|
forceActiveFocus()
|
|
mainItem.highlightedContact = contactItem.searchResultItem
|
|
if (mainItem.multiSelectionEnabled) {
|
|
var indexInSelection = mainItem.selectedContacts.indexOf(searchResultItem.core.defaultAddress)
|
|
if (indexInSelection == -1) {
|
|
mainItem.addContactToSelection(searchResultItem.core.defaultAddress)
|
|
}
|
|
else {
|
|
mainItem.removeContactFromSelection(indexInSelection)
|
|
}
|
|
}
|
|
mainItem.contactSelected(searchResultItem)
|
|
}
|
|
}
|
|
onContainsMouseChanged: (containsMouse) => {
|
|
if(containsMouse)
|
|
mainItem.lastMouseContainsIndex = index
|
|
else if( mainItem.lastMouseContainsIndex == index)
|
|
mainItem.lastMouseContainsIndex = -1
|
|
}
|
|
}
|
|
}
|