mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-17 03:18:07 +00:00
466 lines
17 KiB
QML
466 lines
17 KiB
QML
import QtCore
|
|
import QtQuick
|
|
import QtQuick.Controls.Basic as Control
|
|
import QtQuick.Dialogs
|
|
import QtQuick.Effects
|
|
import QtQuick.Layouts
|
|
import Linphone
|
|
import UtilsCpp
|
|
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
|
|
|
|
MainRightPanel {
|
|
id: mainItem
|
|
|
|
property FriendGui contact
|
|
Connections {
|
|
target: contact.core
|
|
function onIsSavedChanged() {
|
|
if (contact.core.isSaved) {
|
|
mainItem.closeEdition(contact.core.defaultFullAddress)
|
|
}
|
|
}
|
|
}
|
|
//: "Modifier contact"
|
|
property string title: qsTr("contact_editor_title")
|
|
//: "Enregistrer
|
|
property string saveButtonText: qsTr("save")
|
|
property string oldPictureUri
|
|
property int addressCount: 0
|
|
|
|
signal closeEdition(var redirectAddress)
|
|
|
|
Dialog {
|
|
id: confirmDialog
|
|
onAccepted: {
|
|
mainItem.contact.core.undo()
|
|
mainItem.closeEdition('')
|
|
}
|
|
width: Utils.getSizeWithScreenRatio(278)
|
|
//: "Les changements seront annulés. Souhaitez-vous continuer ?"
|
|
text: qsTr("contact_editor_dialog_cancel_change_message")
|
|
}
|
|
|
|
headerContentItem: RowLayout {
|
|
Text {
|
|
text: mainItem.title
|
|
font {
|
|
pixelSize: Utils.getSizeWithScreenRatio(20)
|
|
weight: Typography.h4.weight
|
|
}
|
|
}
|
|
Item{Layout.fillWidth: true}
|
|
Button {
|
|
style: ButtonStyle.noBackground
|
|
Layout.preferredWidth: Utils.getSizeWithScreenRatio(30)
|
|
Layout.preferredHeight: Utils.getSizeWithScreenRatio(30)
|
|
icon.source: AppIcons.closeX
|
|
icon.width: Utils.getSizeWithScreenRatio(24)
|
|
icon.height: Utils.getSizeWithScreenRatio(24)
|
|
//: Close %n
|
|
Accessible.name: qsTr("close_accessible_name").arg(mainItem.title)
|
|
onClicked: {
|
|
if (contact.core.isSaved) mainItem.closeEdition('')
|
|
else showConfirmationLambdaPopup("", qsTr("contact_editor_dialog_cancel_change_message"), "", function(confirmed) {
|
|
if (confirmed) {
|
|
mainItem.contact.core.undo()
|
|
mainItem.closeEdition('')
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
content: ContactLayout {
|
|
id: contactLayoutItem
|
|
anchors.fill: parent
|
|
contact: mainItem.contact
|
|
button.text: mainItem.saveButtonText
|
|
button.Keys.onPressed: (event) => {
|
|
if(event.key == Qt.Key_Up){
|
|
phoneNumberInput.forceActiveFocus(Qt.BacktabFocusReason)
|
|
event.accepted = true
|
|
}
|
|
}
|
|
|
|
// Let some time to GUI to set fields on losing focus.
|
|
Timer{
|
|
id: saveDelay
|
|
interval: 200
|
|
onTriggered: {
|
|
//: "Veuillez saisir un prénom ou un nom d'entreprise"
|
|
if (mainItem.contact.core.givenName.length === 0 && mainItem.contact.core.organization.length === 0) {
|
|
givenName.errorMessage = qsTr("contact_editor_mandatory_first_name_or_company_not_filled")
|
|
return
|
|
} else if (addressesList.count === 0 && phoneNumberList.count === 0) {
|
|
//: "Veuillez saisir une adresse ou un numéro de téléphone"
|
|
addressesErrorText.setText(qsTr("contact_editor_mandatory_address_or_number_not_filled"))
|
|
return
|
|
}
|
|
mainItem.contact.core.save()
|
|
}
|
|
}
|
|
button.onClicked: {
|
|
button.forceActiveFocus()
|
|
saveDelay.restart()
|
|
}
|
|
bannerContent: [
|
|
IconLabelButton {
|
|
id: addPictureButton
|
|
Layout.preferredWidth: width
|
|
visible: !mainItem.contact || mainItem.contact.core.pictureUri.length === 0
|
|
icon.source: AppIcons.camera
|
|
//: "Ajouter une image"
|
|
text: qsTr("contact_editor_add_image_label")
|
|
textSize: Typography.h4.pixelSize
|
|
textWeight: Typography.h4.weight
|
|
textColor: DefaultStyle.main2_700
|
|
hoveredTextColor: DefaultStyle.main2_800
|
|
pressedTextColor: DefaultStyle.main2_900
|
|
KeyNavigation.down: editButton.visible ? editButton : givenNameEdit
|
|
onClicked: fileDialog.open()
|
|
},
|
|
RowLayout {
|
|
visible: mainItem.contact && mainItem.contact.core.pictureUri.length != 0
|
|
Layout.alignment: Qt.AlignHCenter
|
|
spacing: Utils.getSizeWithScreenRatio(32)
|
|
IconLabelButton {
|
|
id: editButton
|
|
Layout.preferredWidth: width
|
|
icon.source: AppIcons.pencil
|
|
//: "Modifier"
|
|
text: qsTr("contact_details_edit")
|
|
textColor: DefaultStyle.main2_700
|
|
hoveredTextColor: DefaultStyle.main2_800
|
|
pressedTextColor: DefaultStyle.main2_900
|
|
textSize: Typography.h4.pixelSize
|
|
textWeight: Typography.h4.weight
|
|
KeyNavigation.right: removeButton
|
|
onClicked: fileDialog.open()
|
|
//: "Edit contact image"
|
|
Accessible.name: qsTr("edit_contact_image_accessible_name")
|
|
}
|
|
FileDialog {
|
|
id: fileDialog
|
|
currentFolder: StandardPaths.standardLocations(StandardPaths.PicturesLocation)[0]
|
|
onAccepted: {
|
|
mainItem.oldPictureUri = mainItem.contact.core.pictureUri
|
|
var avatarPath = UtilsCpp.createAvatar( selectedFile )
|
|
if(avatarPath){
|
|
mainItem.contact.core.pictureUri = avatarPath
|
|
}
|
|
}
|
|
}
|
|
IconLabelButton {
|
|
id: removeButton
|
|
Layout.preferredWidth: width
|
|
icon.source: AppIcons.trashCan
|
|
//: "Supprimer"
|
|
text: qsTr("contact_details_delete")
|
|
textColor: DefaultStyle.main2_700
|
|
hoveredTextColor: DefaultStyle.main2_800
|
|
pressedTextColor: DefaultStyle.main2_900
|
|
textSize: Typography.h4.pixelSize
|
|
textWeight: Typography.h4.weight
|
|
KeyNavigation.left: editButton
|
|
onClicked: mainItem.contact.core.pictureUri = ""
|
|
//: "Delete contact image"
|
|
Accessible.name: qsTr("delete_contact_image_accessible_name")
|
|
}
|
|
},
|
|
Item{Layout.fillWidth: true}
|
|
]
|
|
content: Flickable {
|
|
id: editionLayout
|
|
contentWidth: Math.min(parent.width, Utils.getSizeWithScreenRatio(421))
|
|
width: parent.width
|
|
contentY: 0
|
|
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
onClicked: {
|
|
editionLayout.forceActiveFocus()
|
|
}
|
|
}
|
|
|
|
signal ensureVisibleRequested(Item item)
|
|
|
|
function ensureVisible(r) {
|
|
if (contentY >= r.y)
|
|
contentY = r.y;
|
|
else if (contentY+height <= r.y+r.height)
|
|
contentY = r.y + r.height - height;
|
|
}
|
|
|
|
// Hack to ensure the empty textfield is really visible, because
|
|
// its y changes too late after the editingFinished is emitted
|
|
function connectOnce(sig, slot) {
|
|
var f = function() {
|
|
slot.apply(this, arguments)
|
|
sig.disconnect(f)
|
|
}
|
|
sig.connect(f)
|
|
}
|
|
|
|
ScrollBar.vertical: ScrollBar {
|
|
anchors.right: parent.right
|
|
visible: editionLayout.contentHeight > editionLayout.height
|
|
}
|
|
ScrollBar.horizontal: ScrollBar {
|
|
}
|
|
ColumnLayout {
|
|
spacing: Utils.getSizeWithScreenRatio(20)
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
|
|
FormItemLayout {
|
|
id: givenName
|
|
Layout.fillWidth: true
|
|
enableErrorText: true
|
|
//: "Prénom"
|
|
label: qsTr("contact_editor_first_name")
|
|
contentItem: TextField {
|
|
id: givenNameEdit
|
|
Layout.preferredHeight: Utils.getSizeWithScreenRatio(49)
|
|
initialText: contact.core.givenName
|
|
onTextEdited: {
|
|
contact.core.givenName = givenNameEdit.text
|
|
}
|
|
backgroundColor: DefaultStyle.grey_0
|
|
backgroundBorderColor: givenName.errorTextVisible ? DefaultStyle.danger_500_main : DefaultStyle.grey_200
|
|
KeyNavigation.up: editButton.visible ? editButton : addPictureButton
|
|
KeyNavigation.down: nameTextField
|
|
Accessible.name: qsTr("contact_editor_first_name")
|
|
}
|
|
}
|
|
FormItemLayout {
|
|
//: "Nom"
|
|
label: qsTr("contact_editor_last_name")
|
|
Layout.fillWidth: true
|
|
contentItem: TextField {
|
|
id: nameTextField
|
|
initialText: contact.core.familyName
|
|
onTextEdited: contact.core.familyName = text
|
|
backgroundColor: DefaultStyle.grey_0
|
|
KeyNavigation.up: givenNameEdit
|
|
KeyNavigation.down: companyTextField
|
|
Accessible.name: qsTr("contact_editor_last_name")
|
|
}
|
|
}
|
|
FormItemLayout {
|
|
//: "Entreprise"
|
|
label: qsTr("contact_editor_company")
|
|
Layout.fillWidth: true
|
|
contentItem: TextField {
|
|
id: companyTextField
|
|
initialText: contact.core.organization
|
|
onTextEdited: contact.core.organization = text
|
|
backgroundColor: DefaultStyle.grey_0
|
|
KeyNavigation.up: nameTextField
|
|
KeyNavigation.down: jobTextField
|
|
Accessible.name: qsTr("contact_editor_company")
|
|
}
|
|
}
|
|
FormItemLayout {
|
|
//: "Fonction"
|
|
label: qsTr("contact_editor_job_title")
|
|
Layout.fillWidth: true
|
|
contentItem: TextField {
|
|
id: jobTextField
|
|
initialText: contact.core.job
|
|
onTextEdited: contact.core.job = text
|
|
backgroundColor: DefaultStyle.grey_0
|
|
KeyNavigation.up: companyTextField
|
|
Keys.onPressed: (event) => {
|
|
if(event.key == Qt.Key_Down){
|
|
(addressesList.count > 0 ? addressesList.itemAt(0) : newAddressTextField).forceActiveFocus(Qt.TabFocusReason)
|
|
event.accepted = true
|
|
}
|
|
}
|
|
Accessible.name: qsTr("contact_editor_job_title")
|
|
}
|
|
}
|
|
Repeater {
|
|
id: addressesList
|
|
onCountChanged: mainItem.addressCount = count
|
|
model: VariantList {
|
|
model: mainItem.contact && mainItem.contact.core.addresses || []
|
|
}
|
|
delegate: FormItemLayout {
|
|
label: modelData.label
|
|
contentItem: RowLayout {
|
|
id: addressLayout
|
|
spacing: Utils.getSizeWithScreenRatio(10)
|
|
function updateFocus(event){
|
|
if(event.key == Qt.Key_Up){
|
|
(index - 1 >=0 ? addressesList.itemAt(index - 1) : jobTextField).forceActiveFocus(Qt.BacktabFocusReason)
|
|
event.accepted = true
|
|
}else if(event.key == Qt.Key_Down){
|
|
(index + 1 < addressesList.count ? addressesList.itemAt(index+1) : newAddressTextField).forceActiveFocus(Qt.TabFocusReason)
|
|
event.accepted = true
|
|
}else if(event.key == Qt.Key_Right && addressTextField.activeFocus){
|
|
removeAddressButton.forceActiveFocus(Qt.TabFocusReason)
|
|
}else if(event.key == Qt.Key_Left && removeAddressButton.activeFocus){
|
|
addressTextField.forceActiveFocus(Qt.BacktabFocusReason)
|
|
}
|
|
}
|
|
TextField {
|
|
id: addressTextField
|
|
Layout.preferredWidth: Utils.getSizeWithScreenRatio(421)
|
|
Layout.preferredHeight: height
|
|
onEditingFinished: {
|
|
var label = qsTr("sip_address")
|
|
if (text.length != 0) mainItem.contact.core.setAddressAt(index, label, text)
|
|
}
|
|
property string _initialText: modelData.address
|
|
initialText: SettingsCpp.hideSipAddresses ? UtilsCpp.getUsername(_initialText) : _initialText
|
|
backgroundColor: DefaultStyle.grey_0
|
|
focus: true
|
|
KeyNavigation.right: removeAddressButton
|
|
Keys.onPressed: (event) => addressLayout.updateFocus(event)
|
|
//: "SIP address number %1"
|
|
Accessible.name: qsTr("sip_address_number_accessible_name").arg(index+1)
|
|
}
|
|
Button {
|
|
id: removeAddressButton
|
|
Layout.preferredWidth: Utils.getSizeWithScreenRatio(30)
|
|
Layout.preferredHeight: Utils.getSizeWithScreenRatio(30)
|
|
Layout.alignment: Qt.AlignVCenter
|
|
icon.source: AppIcons.closeX
|
|
icon.width: Utils.getSizeWithScreenRatio(24)
|
|
icon.height: Utils.getSizeWithScreenRatio(24)
|
|
style: ButtonStyle.noBackground
|
|
KeyNavigation.left: addressTextField
|
|
Keys.onPressed: (event) => addressLayout.updateFocus(event)
|
|
onClicked: mainItem.contact.core.removeAddress(index)
|
|
//: "Remove SIP address %1"
|
|
Accessible.name: qsTr("remove_sip_address_accessible_name").arg(addressTextField.text)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
FormItemLayout {
|
|
id: newAddressSipTextField
|
|
label: qsTr("sip_address")
|
|
Layout.fillWidth: true
|
|
onYChanged: {
|
|
editionLayout.ensureVisibleRequested(newAddressSipTextField)
|
|
}
|
|
contentItem: TextField {
|
|
id: newAddressTextField
|
|
backgroundColor: DefaultStyle.grey_0
|
|
Keys.onPressed: (event) => {
|
|
if(event.key == Qt.Key_Up){
|
|
(addressesList.count > 0 ? addressesList.itemAt(addressesList.count - 1) : jobTextField).forceActiveFocus(Qt.BacktabFocusReason)
|
|
event.accepted = true
|
|
}else if(event.key == Qt.Key_Down){
|
|
(phoneNumberList.count > 0 ? phoneNumberList.itemAt(0) : phoneNumberInputTextField).forceActiveFocus(Qt.TabFocusReason)
|
|
event.accepted = true
|
|
}
|
|
}
|
|
onEditingFinished: {
|
|
if (text.length > 0) mainItem.contact.core.appendAddress(text)
|
|
newAddressTextField.clear()
|
|
editionLayout.connectOnce(editionLayout.ensureVisibleRequested, editionLayout.ensureVisible)
|
|
}
|
|
//: "New SIP address"
|
|
Accessible.name: qsTr("new_sip_address_accessible_name")
|
|
}
|
|
}
|
|
Repeater {
|
|
id: phoneNumberList
|
|
model: VariantList {
|
|
model: mainItem.contact && mainItem.contact.core.phoneNumbers || []
|
|
}
|
|
delegate: FormItemLayout {
|
|
label: modelData.label
|
|
contentItem: RowLayout {
|
|
id: phoneNumberLayout
|
|
spacing: Utils.getSizeWithScreenRatio(10)
|
|
function updateFocus(event){
|
|
if(event.key == Qt.Key_Up){
|
|
(index - 1 >=0 ? phoneNumberList.itemAt(index - 1): newAddressTextField).forceActiveFocus(Qt.BacktabFocusReason)
|
|
event.accepted = true
|
|
}else if(event.key == Qt.Key_Down){
|
|
(index + 1 < phoneNumberList.count ? phoneNumberList.itemAt(index+1) : phoneNumberInputTextField).forceActiveFocus(Qt.TabFocusReason)
|
|
event.accepted = true
|
|
}
|
|
}
|
|
TextField {
|
|
id: phoneTextField
|
|
Layout.preferredWidth: Utils.getSizeWithScreenRatio(421)
|
|
Layout.preferredHeight: height
|
|
initialText: modelData.address
|
|
backgroundColor: DefaultStyle.grey_0
|
|
focus: true
|
|
KeyNavigation.right: removePhoneButton
|
|
Keys.onPressed: (event) => phoneNumberLayout.updateFocus(event)
|
|
onEditingFinished: {
|
|
//: "Téléphone"
|
|
if (text.length != 0) mainItem.contact.core.setPhoneNumberAt(index, qsTr("phone"), text)
|
|
}
|
|
//: "Phone number number %1"
|
|
Accessible.name: qsTr("phone_number_number_accessible_name").arg(index+1)
|
|
}
|
|
Button {
|
|
id: removePhoneButton
|
|
Layout.preferredWidth: Utils.getSizeWithScreenRatio(30)
|
|
Layout.preferredHeight: Utils.getSizeWithScreenRatio(30)
|
|
Layout.alignment: Qt.AlignVCenter
|
|
style: ButtonStyle.noBackground
|
|
icon.source: AppIcons.closeX
|
|
icon.width: Utils.getSizeWithScreenRatio(24)
|
|
icon.height: Utils.getSizeWithScreenRatio(24)
|
|
KeyNavigation.left: phoneTextField
|
|
Keys.onPressed: (event) => phoneNumberLayout.updateFocus(event)
|
|
onClicked: mainItem.contact.core.removePhoneNumber(index)
|
|
//: Remove phone number %1
|
|
Accessible.name: qsTr("remove_phone_number_accessible_name").arg(phoneTextField.text)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
FormItemLayout {
|
|
id: phoneNumberInput
|
|
Layout.fillWidth: true
|
|
label: qsTr("phone")
|
|
onYChanged: {
|
|
editionLayout.ensureVisibleRequested(phoneNumberInput)
|
|
}
|
|
contentItem: TextField {
|
|
id: phoneNumberInputTextField
|
|
backgroundColor: DefaultStyle.grey_0
|
|
Keys.onPressed: (event) => {
|
|
if(event.key == Qt.Key_Up){
|
|
(phoneNumberList.count > 0 ? phoneNumberList.itemAt(phoneNumberList.count - 1) : newAddressTextField).forceActiveFocus(Qt.BacktabFocusReason)
|
|
event.accepted = true
|
|
}else if(event.key == Qt.Key_Down){
|
|
(contactLayoutItem.button.enabled ? contactLayoutItem.button : givenNameEdit).forceActiveFocus(Qt.TabFocusReason)
|
|
event.accepted = true
|
|
}
|
|
}
|
|
onEditingFinished: {
|
|
if (text.length != 0) mainItem.contact.core.appendPhoneNumber(phoneNumberInput.label, text)
|
|
phoneNumberInputTextField.clear()
|
|
editionLayout.connectOnce(editionLayout.ensureVisibleRequested, editionLayout.ensureVisible)
|
|
}
|
|
//: "New phone number"
|
|
Accessible.name: qsTr("new_phone_number_accessible_name")
|
|
}
|
|
}
|
|
TemporaryText {
|
|
id: addressesErrorText
|
|
Layout.fillWidth: true
|
|
wrapMode: Text.WordWrap
|
|
elide: Text.ElideRight
|
|
onTextChanged: if(addressesErrorText.text.length > 0) editionLayout.ensureVisible(this)
|
|
}
|
|
Item{Layout.fillHeight: true}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|