diff --git a/Linphone/core/App.cpp b/Linphone/core/App.cpp
index d755683ff..fcc5d033f 100644
--- a/Linphone/core/App.cpp
+++ b/Linphone/core/App.cpp
@@ -114,6 +114,7 @@
#include "tool/request/RequestDialog.hpp"
#include "tool/thread/Thread.hpp"
#include "tool/ui/DashRectangle.hpp"
+#include "tool/ui/FocusNavigator.hpp"
#if defined(Q_OS_MACOS)
#include "core/event-count-notifier/EventCountNotifierMacOs.hpp"
@@ -714,6 +715,7 @@ void App::initCore() {
#endif
mEngine->rootContext()->setContextProperty("applicationName", APPLICATION_NAME);
mEngine->rootContext()->setContextProperty("executableName", EXECUTABLE_NAME);
+ mEngine->rootContext()->setContextProperty("FocusNavigator", new FocusNavigator(mEngine));
initCppInterfaces();
mEngine->addImageProvider(ImageProvider::ProviderId, new ImageProvider());
diff --git a/Linphone/data/languages/de.ts b/Linphone/data/languages/de.ts
index febc3e85b..b285614ac 100644
--- a/Linphone/data/languages/de.ts
+++ b/Linphone/data/languages/de.ts
@@ -22,6 +22,21 @@
+
+ AbstractSettingsMenu
+
+
+ back_previous_menu_accessible_name
+ Back to previous menu
+
+
+
+
+ settings_page_selection_accessible_name
+ Settings page selection
+
+
+
AbstractWindow
@@ -670,143 +685,141 @@
App
-
+
remote_provisioning_dialog
Voulez-vous télécharger et appliquer la configuration depuis cette adresse ?
Möchten Sie die Remote-Konfiguration von dieser Adresse herunterladen und anwenden?
-
-
-
+
+
+
info_popup_error_title
Error
Fehler
-
-
+
+
info_popup_configuration_failed_message
Remote provisioning failed : %1
-
+
info_popup_error_checking_update
An error occured while trying to check update. Please try again later or contact support team.
-
+
info_popup_new_version_download_label
- Download it !
-
+
info_popup_new_version_available_title
New version available !
-
+
info_popup_new_version_available_message
A new version of Linphone (%1) is available. %2
-
+
info_popup_version_up_to_date_title
- Up to date
-
+
info_popup_version_up_to_date_message
Your version is up to date
-
+
configuration_error_detail
not reachable
-
+
application_description
"A free and open source SIP video-phone."
Ein kostenloses Open-Source SIP Video-Telefon.
-
+
command_line_arg_order
"Send an order to the application towards a command line"
Kommandozeilen-Befehl an die Anwendung schicken
-
+
command_line_option_show_help
Zeige Hilfe
-
+
command_line_option_show_app_version
App-Version anzeigen
-
+
command_line_option_config_to_fetch
"Specify the linphone configuration file to be fetched. It will be merged with the current configuration."
Abzurufende Linphone-Konfigurationsdatei angeben. Sie wird mit der aktuellen Konfiguration zusammengeführt.
-
+
command_line_option_config_to_fetch_arg
"URL, path or file"
URL, Pfad oder Datei
-
+
command_line_option_minimized
-
+
command_line_option_log_to_stdout
Debug-Informationen auf der Standardausgabe ausgeben
-
+
command_line_option_print_app_logs_only
"Print only logs from the application"
Nur Anwendungs-Logs ausgeben
-
+
hide_action
"Cacher" "Afficher"
Ausblenden
-
+
show_action
Zeigen
-
+
quit_action
"Quitter"
Beenden
-
+
check_for_update
Check for update
-
+
mark_all_read_action
@@ -1019,11 +1032,35 @@
CallHistoryListView
-
+
call_name_accessible_button
Call %1
+ Anruf %1
+
+
+
+ call_history_entry_accessible_name
+ %1 - %2 - %3 - right arrow for call-back button
+
+
+ notification_missed_call_title
+ "Appel manqué"
+ Verpasster Anruf
+
+
+
+ call_outgoing
+ "Appel sortant"
+ Ausgehender Anruf
+
+
+
+ call_audio_incoming
+ "Appel entrant"
+ Eingehender Anruf
+
CallLayout
@@ -1080,7 +1117,6 @@
local_group_call
- "Local group call"
@@ -1230,101 +1266,101 @@
Anrufprotokoll leer
-
+
history_dialog_delete_all_call_logs_title
Supprimer l'historique d'appels ?
Anrufprotokoll löschen?
-
+
history_dialog_delete_all_call_logs_message
"L'ensemble de votre historique d'appels sera définitivement supprimé."
Das gesamte Anrufprotokoll wird dauerhaft gelöscht.
-
+
history_dialog_delete_call_logs_title
Supprimer l'historique d'appels ?
Anrufprotokoll löschen?
-
+
history_dialog_delete_call_logs_message
"L'ensemble de votre historique d'appels avec ce correspondant sera définitivement supprimé."
Das Anrufprotokoll mit diesem Benutzer wird dauerhaft gelöscht.
-
+
call_history_call_list_title
"Appels"
Anrufe
-
+
call_history_options_accessible_name
-
-
+
+
menu_delete_history
"Supprimer l'historique"
Verlauf löschen
-
+
call_history_list_options_accessible_name
Call history options
-
+
create_new_call_accessible_name
Create new call
-
+
call_search_in_history
"Rechercher un appel"
Anruf suchen
-
+
call_forward_to_address_info
-
+
call_forward_to_address_info_voicemail
-
+
list_filter_no_result_found
"Aucun résultat…"
Kein Ergebnis gefunden…
-
+
history_list_empty_history
"Aucun appel dans votre historique"
Anrufverlauf leer
-
+
return_to_call_history_accessible_name
Return to call history
-
+
call_action_start_new_call
"Nouvel appel"
Neuer Anruf
-
+
call_start_group_call_title
"Appel de groupe"
Gruppenanruf
@@ -1338,7 +1374,7 @@
-
+
call_action_start_group_call
"Lancer"
Starten
@@ -1354,74 +1390,74 @@
Erforderlich
-
-
-
+
+
+
information_popup_error_title
Fehler
-
+
group_call_error_must_have_name
"Un nom doit être donné à l'appel de groupe
Es muss ein Name für den Anruf angegeben werden
-
+
group_call_error_not_connected
"Vous n'etes pas connecté"
Sie sind nicht verbunden
-
+
menu_see_existing_contact
"Show contact"
Kontakt anzeigen
-
+
menu_add_address_to_contacts
"Add to contacts"
Zu Kontakten hinzufügen
-
+
menu_copy_sip_address
"Copier l'adresse SIP"
SIP-Adresse kopieren
-
+
sip_address_copied_to_clipboard_toast
Adresse copiée
SIP-Adresse kopiert
-
+
sip_address_copied_to_clipboard_message
L'adresse a été copié dans le presse_papiers
Die Adresse wurde in die Zwischenablage kopiert
-
+
sip_address_copy_to_clipboard_error
"Erreur lors de la copie de l'adresse"
Fehler beim Kopieren der Adresse
-
+
notification_missed_call_title
"Appel manqué"
Verpasster Anruf
-
+
call_outgoing
"Appel sortant"
Ausgehender Anruf
-
+
call_audio_incoming
"Appel entrant"
Eingehender Anruf
@@ -2344,7 +2380,6 @@ Error
popup_error_nb_files_not_found_message
- %n files were not found
@@ -2365,7 +2400,6 @@ Error
popup_error_unsupported_files_message
- Unable to get supported mime type for %1 files.
@@ -2598,91 +2632,91 @@ Error
-
+
info_popup_error_title
Fehler
-
+
info_popup_chatroom_creation_failed
Chat room creation failed !
-
+
loading_popup_chatroom_creation_pending_message
Chat room is being created...
-
+
chat_dialog_delete_chat_title
Supprimer la conversation ?
-
+
chat_dialog_delete_chat_message
"La conversation et tous ses messages seront supprimés."
-
+
chat_list_title
"Conversations"
Konversationen
-
+
menu_mark_all_as_read
"mark all as read"
-
+
chat_search_in_history
"Rechercher une conversation"
-
+
list_filter_no_result_found
"Aucun résultat…"
Kein Ergebnis…
-
+
chat_list_empty_history
"Aucune conversation dans votre historique"
-
+
chat_action_start_new_chat
"New chat"
-
+
chat_start_group_chat_title
"Nouveau groupe"
-
+
chat_action_start_group_chat
"Créer"
Erstellen
-
-
-
+
+
+
information_popup_error_title
Fehler
-
+
information_popup_chat_creation_failed_message
"La création a échoué"
@@ -2693,25 +2727,25 @@ Error
Der Codec konnte nicht installiert werden.
-
+
group_chat_error_must_have_name
"Un nom doit être donné au groupe
-
+
group_chat_error_no_participant
"Please select at least one participant
-
+
group_call_error_not_connected
"Vous n'etes pas connecté"
Sie sind nicht verbunden
-
+
chat_creation_in_progress
Creation de la conversation en cours …
@@ -2771,28 +2805,34 @@ Error
CliModel
+
show_function_description
- Zeigen
+ Zeigen
+
fetch_config_function_description
- Konfiguration abrufen
+ Konfiguration abrufen
+
call_function_description
- Anrufen
+ Anrufen
+
bye_function_description
- Auflegen
+ Auflegen
+
accept_function_description
- Akzeptieren
+ Akzeptieren
+
decline_function_description
- Ablehnen
+ Ablehnen
@@ -3006,53 +3046,71 @@ Error
ContactListItem
-
+
+ call_with_contact_name_accessible_button
+ "Call %1"
+
+
+
+
+ video_call_with_contact_name_accessible_button
+ "Video call %1"
+
+
+
+
+ message_with_contact_name_accessible_button
+ "Message %1"
+
+
+
+
contact_details_remove_from_favourites
"Enlever des favoris"
Aus Favoriten entfernen
-
+
contact_details_add_to_favourites
"Ajouter aux favoris"
Zu Favoriten hinzufügen
-
+
Partager
Teilen
-
+
information_popup_error_title
Fehler
-
+
information_popup_vcard_creation_error
La création du fichier vcard a échoué
VCard-Erstellung fehlgeschlagen
-
+
information_popup_vcard_creation_title
VCard créée
VCard erstellt
-
+
information_popup_vcard_creation_success
"VCard du contact enregistrée dans %1"
VCard in %1 gespeichert
-
+
contact_sharing_email_title
Partage de contact
Kontakt teilen
-
+
contact_details_delete
"Supprimer"
Löschen
@@ -3088,149 +3146,149 @@ Error
Zurzeit keine Kontakte
-
+
contact_new_title
"Nouveau contact"
Neuer Kontakt
-
+
create
Erstellen
-
+
contact_edit_title
"Modifier contact"
Kontakt bearbeiten
-
+
save
Speichern
-
+
contact_dialog_delete_title
Supprimer %1 ?"
%1 löschen?
-
+
contact_dialog_delete_message
Ce contact sera définitivement supprimé.
Dieser Kontakt wird dauerhaft gelöscht.
-
+
contact_deleted_toast
"Contact supprimé"
Kontakt gelöscht
-
+
contact_deleted_message
"%1 a été supprimé"
%1 wurde gelöscht
-
+
contact_dialog_devices_trust_popup_title
"Augmenter la confiance"
Vertrauenslevel erhöhen
-
+
contact_dialog_devices_trust_popup_message
"Pour augmenter le niveau de confiance vous devez appeler les différents appareils de votre contact et valider un code.<br><br>Vous êtes sur le point d’appeler “%1” voulez vous continuer ?"
Um das Vertrauenslevel zu erhöhen müssen Sie Ihren Kontakt anrufen und einen Code bestätigen.<br><br>Sie sind dabei, "%1" anzurufen. Möchten Sie fortfahren?
-
+
popup_do_not_show_again
Ne plus afficher
Nicht mehr anzeigen
-
+
cancel
Abbrechen
-
+
dialog_call
"Appeler"
Anrufen
-
+
contact_dialog_devices_trust_help_title
"Niveau de confiance"
Vertrauenslevel
-
+
contact_dialog_devices_trust_help_message
"Vérifiez les appareils de votre contact pour confirmer que vos communications seront sécurisées et sans compromission. <br>Quand tous seront vérifiés, vous atteindrez le niveau de confiance maximal."
Überprüfen Sie die Geräte Ihres Kontakts um sicherzustellen, dass Ihre Kommunikation sicher und unkompromittiert ist. Wenn alle Geräte überprüft sind, erreichen Sie das höchste Vertrauenslevel.
-
+
dialog_ok
"Ok"
Ok
-
+
bottom_navigation_contacts_label
"Contacts"
Kontakte
-
+
create_contact_accessible_name
Create new contact
-
+
search_bar_look_for_contact_text
Rechercher un contact
Kontakt suchen
-
+
list_filter_no_result_found
Aucun résultat…
Kein Ergebnis…
-
+
contact_list_empty
Aucun contact pour le moment
Zurzeit keine Kontakte
-
+
more_info_accessible_name
More info %1
-
+
expand_accessible_name
Expand %1
-
+
shrink_accessible_name
Shrink %1
-
-
+
+
contact_details_edit
Edit
----------
@@ -3238,19 +3296,19 @@ Error
Bearbeiten
-
+
contact_call_action
"Appel"
Anrufen
-
+
contact_message_action
"Message"
Nachricht
-
+
contact_video_call_action
"Appel vidéo"
Videoanruf
@@ -3276,133 +3334,133 @@ Error
Offline
-
+
contact_details_numbers_and_addresses_title
"Coordonnées"
Kontaktinformationen
-
+
call_adress_accessible_name
Call address %1
-
+
contact_details_company_name
"Société :"
Unternehmen :
-
+
contact_details_job_title
"Poste :"
Beruf :
-
+
contact_details_medias_title
"Medias"
Medien
-
-
+
+
contact_details_medias_subtitle
"Afficher les medias partagés"
Geteilte Medien anzeigen
-
+
contact_details_trust_title
"Confiance"
Vertrauen
-
+
contact_dialog_devices_trust_title
"Niveau de confiance - Appareils vérifiés"
Vertrauenslevel - Verifizierte Geräte
-
+
contact_details_no_device_found
"Aucun appareil"
Kein Gerät
-
+
contact_device_without_name
"Appareil inconnu"
Unbekanntes Gerät
-
+
contact_make_call_check_device_trust
"Vérifier"
Überprüfen
-
+
verify_device_accessible_name
Verify %1 device
-
+
contact_details_actions_title
"Autres actions"
Weitere Aktionen
-
+
contact_details_remove_from_favourites
"Retirer des favoris"
Aus Favoriten entfernen
-
+
contact_details_add_to_favourites
"Ajouter aux favoris"
Zu Favoriten hinzufügen
-
+
contact_details_share
"Partager"
Teilen
-
+
information_popup_error_title
Fehler
-
+
contact_details_share_error_mesage
"La création du fichier vcard a échoué"
VCard-Erstellung fehlgeschlagen
-
+
contact_details_share_success_title
"VCard créée"
VCard erstellt
-
+
contact_details_share_success_mesage
"VCard du contact enregistrée dans %1"
VCard wurde in %1 gespeichert
-
+
contact_details_share_email_title
"Partage de contact"
Kontakt teilen
-
+
contact_details_delete
"Supprimer ce contact"
Kontakt löschen
@@ -4430,7 +4488,6 @@ Error
default_account_connection_state_error_toast
- Erreur durant la connexion, veuillez vérifier vos paramètres
Fehler bei der Verbindung
@@ -4445,144 +4502,144 @@ Error
MainLayout
-
+
bottom_navigation_calls_label
"Appels"
Anrufe
-
+
open_calls_page_accessible_name
"Open calls page"
-
+
bottom_navigation_contacts_label
"Contacts"
Kontakte
-
+
open_contacts_page_accessible_name
"Open contacts page"
-
+
bottom_navigation_conversations_label
"Conversations"
Konversationen
-
+
open_conversations_page_accessible_name
"Open conversations page"
-
+
bottom_navigation_meetings_label
"Réunions"
Besprechungen
-
+
open_contact_page_accessible_name
"Open meetings page"
-
+
searchbar_placeholder_text
"Rechercher un contact, appeler %1"
Kontakt suchen, %1 anrufen
-
+
searchbar_placeholder_text_chat_feature_enabled
"ou envoyer un message …"
oder eine Nachricht senden …
-
+
do_not_disturb_accessible_name
"Do not disturb"
Nicht stören
-
-
+
+
contact_presence_status_disable_do_not_disturb
"Désactiver ne pas déranger"
Nicht stören deaktivieren
-
+
information_popup_error_title
Fehler
-
+
no_voicemail_uri_error_message
"L'URI de messagerie vocale n'est pas définie."
Die Voicemail-URI ist nicht definiert.
-
+
account_list_accessible_name
"Account list"
-
+
application_options_accessible_name
"Application options"
-
+
drawer_menu_manage_account
Mon compte
Mein Konto
-
+
contact_presence_status_enable_do_not_disturb
"Activer ne pas déranger"
Nicht stören aktivieren
-
+
settings_title
Einstellungen
-
+
recordings_title
"Enregistrements"
Aufnahmen
-
+
help_title
"Aide"
Hilfe
-
+
help_quit_title
"Quitter l'application"
App beenden
-
+
quit_app_question
"Quitter %1 ?"
%1 beenden?
-
+
drawer_menu_add_account
"Ajouter un compte"
Konto hinzufügen
@@ -4789,158 +4846,158 @@ Error
Keine Besprechungen
-
+
meeting_schedule_cancel_dialog_message
"Souhaitez-vous annuler et supprimer cette réunion ?"
Möchten Sie diese Besprechung absagen und löschen?
-
+
meeting_schedule_delete_dialog_message
Souhaitez-vous supprimer cette réunion ?
Möchten Sie diese Besprechung löschen?
-
+
meeting_schedule_cancel_and_delete_action
"Annuler et supprimer"
Absagen und löschen
-
+
meeting_schedule_delete_only_action
"Supprimer seulement"
Nur löschen
-
+
meeting_schedule_delete_action
"Supprimer"
Löschen
-
+
back_action
Retour
Zurück
-
+
meetings_list_title
Réunions
Besprechungen
-
+
meetings_search_hint
"Rechercher une réunion"
Besprechung suchen
-
+
list_filter_no_result_found
"Aucun résultat…"
Kein Ergebnis…
-
+
meetings_empty_list
"Aucune réunion"
Keine Besprechungen
-
-
+
+
meeting_schedule_title
"Nouvelle réunion"
Neue Besprechung
-
+
create
Erstellen
-
-
-
-
-
-
+
+
+
+
+
+
information_popup_error_title
Fehler
-
-
+
+
meeting_schedule_mandatory_field_not_filled_toast
Veuillez saisir un titre et sélectionner au moins un participant
Bitte Titel bestimmen und mindestens einen Teilnehmer auswählen
-
-
+
+
meeting_schedule_duration_error_toast
"La fin de la conférence doit être plus récente que son début"
Das Ende der Besprechung muss nach dem Beginn liegen
-
-
+
+
meeting_schedule_creation_in_progress
"Création de la réunion en cours …"
Besprechung wird erstellt…
-
+
meeting_info_created_toast
"Réunion planifiée avec succès"
Besprechung erfolgreich erstellt
-
+
meeting_failed_to_schedule_toast
"Échec de création de la réunion !"
Besprechung konnte nicht erstellt werden!
-
+
save
Speichern
-
-
+
+
saved
"Enregistré"
Gespeichert
-
+
meeting_info_updated_toast
"Réunion mise à jour"
Besprechung geändert
-
+
meeting_schedule_edit_in_progress
"Modification de la réunion en cours…"
Bersprechung wird geändert…
-
+
meeting_failed_to_edit_toast
"Échec de la modification de la réunion !"
Besprechung konnte nicht geändert werden!
-
+
meeting_schedule_add_participants_title
"Ajouter des participants"
Teilnehmer hinzufügen
-
+
meeting_schedule_add_participants_apply
Apply
@@ -4949,7 +5006,7 @@ Error
Hinzufügen
-
+
group_call_participant_selected
"%n participant(s) sélectionné(s)"
@@ -4958,31 +5015,31 @@ Error
-
+
meeting_info_delete
"Supprimer la réunion"
Besprechung löschen
-
+
meeting_address_copied_to_clipboard_toast
"Adresse de la réunion copiée"
Besprechungs-URI kopiert
-
+
meeting_schedule_timezone_title
"Fuseau horaire"
Zeitzone
-
+
meeting_info_organizer_label
"Organisateur"
Organisator
-
+
meeting_info_join_title
"Rejoindre la réunion"
Besprechung beitreten
@@ -5218,6 +5275,36 @@ Error
+
+ NumericPad
+
+
+ numpad_longpress_accessible_name
+ %1 longpress %2
+
+
+
+
+ call_accessible_name
+ Call
+
+
+
+
+ erase_accessible_name
+ Erase
+
+
+
+
+ NumericPadPopup
+
+
+ close_numeric_pad_accessible_name
+ Close numeric pad
+
+
+
OIDCModel
@@ -6235,7 +6322,6 @@ Pour les activer dans un projet commercial, merci de nous contacter.
unknown_audio_device_name
- "Unknown device"
Unbekannter Gerätename
@@ -6430,9 +6516,6 @@ Pour les activer dans un projet commercial, merci de nous contacter.
chat_error
- Error creating or opening the chat
-----------
-Error in the chat
diff --git a/Linphone/data/languages/en.ts b/Linphone/data/languages/en.ts
index 0018122bd..18a020089 100644
--- a/Linphone/data/languages/en.ts
+++ b/Linphone/data/languages/en.ts
@@ -22,6 +22,21 @@
Save %1 settings
+
+ AbstractSettingsMenu
+
+
+ back_previous_menu_accessible_name
+ Back to previous menu
+ Back to previous menu
+
+
+
+ settings_page_selection_accessible_name
+ Settings page selection
+ Settings page selection
+
+
AbstractWindow
@@ -661,143 +676,141 @@
App
-
+
remote_provisioning_dialog
Voulez-vous télécharger et appliquer la configuration depuis cette adresse ?
Do you want to download and apply remote provisioning from this address ?
-
-
-
+
+
+
info_popup_error_title
Error
Error
-
-
+
+
info_popup_configuration_failed_message
Remote provisioning failed : %1
Remote provisioning failed : %1
-
+
info_popup_error_checking_update
An error occured while trying to check update. Please try again later or contact support team.
An error occured while trying to check update. Please try again later or contact support team.
-
+
info_popup_new_version_download_label
- Download it !
Download it !
-
+
info_popup_new_version_available_title
New version available !
New version available !
-
+
info_popup_new_version_available_message
A new version of Linphone (%1) is available. %2
A new version of Linphone (%1) is available at %1
-
+
info_popup_version_up_to_date_title
- Up to date
Up to date
-
+
info_popup_version_up_to_date_message
Your version is up to date
Up to date Your version is up to date
-
+
configuration_error_detail
not reachable
not reachable
-
+
application_description
"A free and open source SIP video-phone."
A free and open source SIP video-phone.
-
+
command_line_arg_order
"Send an order to the application towards a command line"
Send an order to the application towards a command line
-
+
command_line_option_show_help
Show this help
-
+
command_line_option_show_app_version
Show app version
-
+
command_line_option_config_to_fetch
"Specify the linphone configuration file to be fetched. It will be merged with the current configuration."
Specify the linphone configuration file to be fetched. It will be merged with the current configuration.
-
+
command_line_option_config_to_fetch_arg
"URL, path or file"
URL, path or file
-
+
command_line_option_minimized
Minimize
-
+
command_line_option_log_to_stdout
Log to stdout some debug information while running
-
+
command_line_option_print_app_logs_only
"Print only logs from the application"
Print only logs from the application
-
+
hide_action
"Cacher" "Afficher"
Hide
-
+
show_action
Show
-
+
quit_action
"Quitter"
Quit
-
+
check_for_update
Check for update
Check for update
-
+
mark_all_read_action
Marquer tout comme lu
@@ -1030,11 +1043,35 @@
CallHistoryListView
-
+
call_name_accessible_button
Call %1
Call %1
+
+
+ call_history_entry_accessible_name
+ %1 - %2 - %3 - right arrow for call-back button
+ %1 - %2 - %3 - right arrow for call-back button
+
+
+
+ notification_missed_call_title
+ "Appel manqué"
+ Missed call
+
+
+
+ call_outgoing
+ "Appel sortant"
+ Outgoing call
+
+
+
+ call_audio_incoming
+ "Appel entrant"
+ Incoming call
+
CallLayout
@@ -1091,7 +1128,6 @@
local_group_call
- "Local group call"
Local group call
@@ -1229,12 +1265,12 @@
CallPage
-
+
call_forward_to_address_info
Forward calls to:
-
+
call_forward_to_address_info_voicemail
Voicemail
@@ -1251,170 +1287,170 @@
Empty call history
-
+
history_dialog_delete_all_call_logs_title
Supprimer l'historique d'appels ?
Delete call history ?
-
+
history_dialog_delete_all_call_logs_message
"L'ensemble de votre historique d'appels sera définitivement supprimé."
Call history will be permanently deleted.
-
+
history_dialog_delete_call_logs_title
Supprimer l'historique d'appels ?
Delete call history ?
-
+
history_dialog_delete_call_logs_message
"L'ensemble de votre historique d'appels avec ce correspondant sera définitivement supprimé."
Call history with this user will be permanently deleted.
-
+
call_history_call_list_title
"Appels"
Calls
-
+
call_history_options_accessible_name
Call history options
-
-
+
+
menu_delete_history
"Supprimer l'historique"
Delete history
-
+
call_history_list_options_accessible_name
Call history options
Call history options
-
+
create_new_call_accessible_name
Create new call
Create new call
-
+
call_search_in_history
"Rechercher un appel"
Find call
-
+
list_filter_no_result_found
"Aucun résultat…"
No result found…
-
+
history_list_empty_history
"Aucun appel dans votre historique"
No call in history
-
+
return_to_call_history_accessible_name
Return to call history
Return to call history
-
+
call_action_start_new_call
"Nouvel appel"
New call
-
+
call_start_group_call_title
"Appel de groupe"
Group call
-
+
call_action_start_group_call
"Lancer"
Start
-
-
-
+
+
+
information_popup_error_title
Error
-
+
group_call_error_must_have_name
"Un nom doit être donné à l'appel de groupe
A name must be provided for the call
-
+
group_call_error_not_connected
"Vous n'etes pas connecté"
You are not connected
-
+
menu_see_existing_contact
"Show contact"
Show contact
-
+
menu_add_address_to_contacts
"Add to contacts"
Add to contacts
-
+
menu_copy_sip_address
"Copier l'adresse SIP"
Copy SIP address
-
+
sip_address_copied_to_clipboard_toast
Adresse copiée
SIP address copied
-
+
sip_address_copied_to_clipboard_message
L'adresse a été copié dans le presse_papiers
The address has been copied to the clipboard
-
+
sip_address_copy_to_clipboard_error
"Erreur lors de la copie de l'adresse"
Error copying address
-
+
notification_missed_call_title
"Appel manqué"
Missed call
-
+
call_outgoing
"Appel sortant"
Outgoing call
-
+
call_audio_incoming
"Appel entrant"
Incoming call
@@ -2337,7 +2373,6 @@ Error
popup_error_nb_files_not_found_message
- %n files were not found
%1 files were not found
@@ -2358,7 +2393,6 @@ Error
popup_error_unsupported_files_message
- Unable to get supported mime type for %1 files.
Unable to get supported mime type for %1 files.
@@ -2588,115 +2622,115 @@ Only your correspondent can decrypt them.
No conversation
-
+
info_popup_error_title
Error
-
+
info_popup_chatroom_creation_failed
Chat room creation failed !
Chat room creation failed !
-
+
loading_popup_chatroom_creation_pending_message
Chat room is being created...
Chat room is being created...
-
+
chat_dialog_delete_chat_title
Supprimer la conversation ?
Delete conversation ?
-
+
chat_dialog_delete_chat_message
"La conversation et tous ses messages seront supprimés."
This conversation and all its messages will be deleted.
-
+
chat_list_title
"Conversations"
Conversations
-
+
menu_mark_all_as_read
"mark all as read"
Mark all as read
-
+
chat_search_in_history
"Rechercher une conversation"
Search for a chat
-
+
list_filter_no_result_found
"Aucun résultat…"
No result…
-
+
chat_list_empty_history
"Aucune conversation dans votre historique"
No conversation in history
-
+
chat_action_start_new_chat
"New chat"
New conversation
-
+
chat_start_group_chat_title
"Nouveau groupe"
New group
-
+
chat_action_start_group_chat
"Créer"
Create
-
-
-
+
+
+
information_popup_error_title
Error
-
+
information_popup_chat_creation_failed_message
"La création a échoué"
Creation failed
-
+
group_chat_error_must_have_name
"Un nom doit être donné au groupe
A name must be set for the group
-
+
group_chat_error_no_participant
"Please select at least one participant
Please select at least one participant
-
+
group_call_error_not_connected
"Vous n'etes pas connecté"
You are not connected
-
+
chat_creation_in_progress
Creation de la conversation en cours …
Chat creation pending…
@@ -2756,28 +2790,34 @@ Only your correspondent can decrypt them.
CliModel
+
show_function_description
- Show
+ Show
+
fetch_config_function_description
- Fetch configuration
+ Fetch configuration
+
call_function_description
- Call
+ Call
+
bye_function_description
- Hang up
+ Hang up
+
accept_function_description
- Accept
+ Accept
+
decline_function_description
- Decline
+ Decline
@@ -2966,53 +3006,71 @@ Only your correspondent can decrypt them.
ContactListItem
-
+
+ call_with_contact_name_accessible_button
+ "Call %1"
+ Call %1
+
+
+
+ video_call_with_contact_name_accessible_button
+ "Video call %1"
+ Video call %1
+
+
+
+ message_with_contact_name_accessible_button
+ "Message %1"
+ Message %1
+
+
+
contact_details_remove_from_favourites
"Enlever des favoris"
Remove from favorites
-
+
contact_details_add_to_favourites
"Ajouter aux favoris"
Add to favorites
-
+
Partager
Share
-
+
information_popup_error_title
Error
-
+
information_popup_vcard_creation_error
La création du fichier vcard a échoué
VCard creation failed
-
+
information_popup_vcard_creation_title
VCard créée
VCard created
-
+
information_popup_vcard_creation_success
"VCard du contact enregistrée dans %1"
VCard has been saved in %1
-
+
contact_sharing_email_title
Partage de contact
Share contact
-
+
contact_details_delete
"Supprimer"
Delete
@@ -3048,149 +3106,149 @@ Only your correspondent can decrypt them.
No contact at the moment
-
+
contact_new_title
"Nouveau contact"
New contact
-
+
create
Create
-
+
contact_edit_title
"Modifier contact"
Edit contact
-
+
save
Save
-
+
contact_dialog_delete_title
Supprimer %1 ?"
Delete %1?
-
+
contact_dialog_delete_message
Ce contact sera définitivement supprimé.
This contact will be permanently deleted.
-
+
contact_deleted_toast
"Contact supprimé"
Contact deleted
-
+
contact_deleted_message
"%1 a été supprimé"
%1 has been deleted
-
+
contact_dialog_devices_trust_popup_title
"Augmenter la confiance"
Increase trust level
-
+
contact_dialog_devices_trust_popup_message
"Pour augmenter le niveau de confiance vous devez appeler les différents appareils de votre contact et valider un code.<br><br>Vous êtes sur le point d’appeler “%1” voulez vous continuer ?"
To increase trust level you must call your contact's devices and validate a code.<br><br>You are about to call "%1" do you want to continue?
-
+
popup_do_not_show_again
Ne plus afficher
Do not show again
-
+
cancel
Cancel
-
+
dialog_call
"Appeler"
Call
-
+
contact_dialog_devices_trust_help_title
"Niveau de confiance"
Trust level
-
+
contact_dialog_devices_trust_help_message
"Vérifiez les appareils de votre contact pour confirmer que vos communications seront sécurisées et sans compromission. <br>Quand tous seront vérifiés, vous atteindrez le niveau de confiance maximal."
Verify your contact's devices to confirm that your communications will be secure and uncompromised. When all are verified, you will reach the maximum trust level.
-
+
dialog_ok
"Ok"
Ok
-
+
bottom_navigation_contacts_label
"Contacts"
Contacts
-
+
search_bar_look_for_contact_text
Rechercher un contact
Find contact
-
+
list_filter_no_result_found
Aucun résultat…
No result…
-
+
contact_list_empty
Aucun contact pour le moment
No contact at the moment
-
+
expand_accessible_name
Expand %1
Expand %1
-
+
shrink_accessible_name
Shrink %1
Shrink %1
-
+
create_contact_accessible_name
Create new contact
Create new contact
-
+
more_info_accessible_name
More info %1
More info %1
-
-
+
+
contact_details_edit
Edit
----------
@@ -3198,151 +3256,151 @@ Only your correspondent can decrypt them.
Edit
-
+
contact_call_action
"Appel"
Call
-
+
contact_message_action
"Message"
Message
-
+
contact_video_call_action
"Appel vidéo"
Video call
-
+
contact_details_numbers_and_addresses_title
"Coordonnées"
Contact details
-
+
call_adress_accessible_name
Call address %1
Call address %1
-
+
contact_details_company_name
"Société :"
Company :
-
+
contact_details_job_title
"Poste :"
Job :
-
+
contact_details_medias_title
"Medias"
Medias
-
-
+
+
contact_details_medias_subtitle
"Afficher les medias partagés"
Show shared media
-
+
contact_details_trust_title
"Confiance"
Trust
-
+
contact_dialog_devices_trust_title
"Niveau de confiance - Appareils vérifiés"
Trust Level - Verified Devices
-
+
contact_details_no_device_found
"Aucun appareil"
No device
-
+
contact_device_without_name
"Appareil inconnu"
Unknown device
-
+
contact_make_call_check_device_trust
"Vérifier"
Verify
-
+
verify_device_accessible_name
Verify %1 device
Verify %1 device
-
+
contact_details_actions_title
"Autres actions"
Other actions
-
+
contact_details_remove_from_favourites
"Retirer des favoris"
Remove from favorites
-
+
contact_details_add_to_favourites
"Ajouter aux favoris"
Add to favorites
-
+
contact_details_share
"Partager"
Share
-
+
information_popup_error_title
Error
-
+
contact_details_share_error_mesage
"La création du fichier vcard a échoué"
VCard creation failed
-
+
contact_details_share_success_title
"VCard créée"
VCard created
-
+
contact_details_share_success_mesage
"VCard du contact enregistrée dans %1"
VCard has been saved in %1
-
+
contact_details_share_email_title
"Partage de contact"
Share contact
-
+
contact_details_delete
"Supprimer ce contact"
Delete contact
@@ -4362,7 +4420,6 @@ Expiration : %1
default_account_connection_state_error_toast
- Erreur durant la connexion, veuillez vérifier vos paramètres
Error during connection
@@ -4377,144 +4434,144 @@ Expiration : %1
MainLayout
-
+
bottom_navigation_calls_label
"Appels"
Calls
-
+
open_calls_page_accessible_name
"Open calls page"
Open calls pages
-
+
bottom_navigation_contacts_label
"Contacts"
Contacts
-
+
open_contacts_page_accessible_name
"Open contacts page"
Open contacts page
-
+
bottom_navigation_conversations_label
"Conversations"
Conversations
-
+
open_conversations_page_accessible_name
"Open conversations page"
Open conversations page
-
+
bottom_navigation_meetings_label
"Réunions"
Meetings
-
+
open_contact_page_accessible_name
"Open meetings page"
Open meetings page
-
+
searchbar_placeholder_text
"Rechercher un contact, appeler %1"
Find contact, call %1
-
+
searchbar_placeholder_text_chat_feature_enabled
"ou envoyer un message …"
or send message …
-
+
do_not_disturb_accessible_name
"Do not disturb"
Do not disturb
-
-
+
+
contact_presence_status_disable_do_not_disturb
"Désactiver ne pas déranger"
Disable do not disturb
-
+
information_popup_error_title
Error
-
+
no_voicemail_uri_error_message
"L'URI de messagerie vocale n'est pas définie."
The voicemail URI is not defined.
-
+
account_list_accessible_name
"Account list"
account list
-
+
application_options_accessible_name
"Application options"
Application options
-
+
drawer_menu_manage_account
Mon compte
My account
-
+
contact_presence_status_enable_do_not_disturb
"Activer ne pas déranger"
Enable do not disturb
-
+
settings_title
Settings
-
+
recordings_title
"Enregistrements"
Records
-
+
help_title
"Aide"
Help
-
+
help_quit_title
"Quitter l'application"
Quit the app
-
+
quit_app_question
"Quitter %1 ?"
Quit %1 ?
-
+
drawer_menu_add_account
"Ajouter un compte"
Add an account
@@ -4721,163 +4778,163 @@ Expiration : %1
No meeting
-
+
meeting_schedule_cancel_dialog_message
"Souhaitez-vous annuler et supprimer cette réunion ?"
Would you like to cancel and delete this meeting?
-
+
meeting_schedule_delete_dialog_message
Souhaitez-vous supprimer cette réunion ?
Would you like to delete this meeting?
-
+
meeting_schedule_cancel_and_delete_action
"Annuler et supprimer"
Cancel and delete
-
+
meeting_schedule_delete_only_action
"Supprimer seulement"
Delete only
-
+
meeting_schedule_delete_action
"Supprimer"
Delete
-
+
back_action
Retour
Back
-
+
meetings_list_title
Réunions
Meetings
-
+
meetings_search_hint
"Rechercher une réunion"
Find meeting
-
+
list_filter_no_result_found
"Aucun résultat…"
No result…
-
+
meetings_empty_list
"Aucune réunion"
No meeting
-
-
+
+
meeting_schedule_title
"Nouvelle réunion"
New meeting
-
+
create
Create
-
-
-
-
-
-
+
+
+
+
+
+
information_popup_error_title
Error
-
-
+
+
meeting_schedule_mandatory_field_not_filled_toast
Veuillez saisir un titre et sélectionner au moins un participant
Please fill the title and select at least one participant
-
-
+
+
meeting_schedule_duration_error_toast
"La fin de la conférence doit être plus récente que son début"
The end of the conference must be more recent than its beginning
-
-
+
+
meeting_schedule_creation_in_progress
"Création de la réunion en cours …"
Creation in progress…
-
+
meeting_info_created_toast
"Réunion planifiée avec succès"
Meeting successfully created
-
+
meeting_failed_to_schedule_toast
"Échec de création de la réunion !"
Failed to create meeting!
-
+
save
Save
-
-
+
+
saved
"Enregistré"
Saved
-
+
meeting_info_updated_toast
"Réunion mise à jour"
Meeting updated
-
+
meeting_schedule_edit_in_progress
"Modification de la réunion en cours…"
Meeting update in progress…
-
+
meeting_failed_to_edit_toast
"Échec de la modification de la réunion !"
Failed to update meeting !
-
+
meeting_schedule_add_participants_title
"Ajouter des participants"
Add participants
-
+
meeting_schedule_add_participants_apply
Apply
-
+
group_call_participant_selected
"%n participant(s) sélectionné(s)"
@@ -4886,31 +4943,31 @@ Expiration : %1
-
+
meeting_info_delete
"Supprimer la réunion"
Delete meeting
-
+
meeting_address_copied_to_clipboard_toast
"Adresse de la réunion copiée"
Meeting URI copied
-
+
meeting_schedule_timezone_title
"Fuseau horaire"
Timezone
-
+
meeting_info_organizer_label
"Organisateur"
Organizer
-
+
meeting_info_join_title
"Rejoindre la réunion"
Join meeting
@@ -5141,6 +5198,36 @@ Expiration : %1
New message on chatroom %1
+
+ NumericPad
+
+
+ numpad_longpress_accessible_name
+ %1 longpress %2
+ %1 longpress %2
+
+
+
+ call_accessible_name
+ Call
+ Call
+
+
+
+ erase_accessible_name
+ Erase
+ Erase
+
+
+
+ NumericPadPopup
+
+
+ close_numeric_pad_accessible_name
+ Close numeric pad
+ Close numeric pad
+
+
OIDCModel
@@ -6114,7 +6201,6 @@ To enable them in a commercial project, please contact us.
unknown_audio_device_name
- "Unknown device"
Unknown device name
@@ -6370,9 +6456,6 @@ To enable them in a commercial project, please contact us.
chat_error
- Error creating or opening the chat
-----------
-Error in the chat
Error in the chat
diff --git a/Linphone/data/languages/fr.ts b/Linphone/data/languages/fr.ts
index dc8c5c138..67c519909 100644
--- a/Linphone/data/languages/fr.ts
+++ b/Linphone/data/languages/fr.ts
@@ -22,6 +22,21 @@
Sauvegarder les paramètres %1
+
+ AbstractSettingsMenu
+
+
+ back_previous_menu_accessible_name
+ Back to previous menu
+ Retour au menu précédent
+
+
+
+ settings_page_selection_accessible_name
+ Settings page selection
+ Selection de la page de paramètre
+
+
AbstractWindow
@@ -656,143 +671,141 @@
App
-
+
remote_provisioning_dialog
Voulez-vous télécharger et appliquer la configuration depuis cette adresse ?
Voulez-vous télécharger et appliquer la configuration depuis cette adresse ?
-
-
-
+
+
+
info_popup_error_title
Error
Erreur
-
-
+
+
info_popup_configuration_failed_message
Remote provisioning failed : %1
La configuration distante a échoué : %1
-
+
info_popup_error_checking_update
An error occured while trying to check update. Please try again later or contact support team.
Une erreur est survenue lors de la recherche de mise à jour. Merci de réessayer plus tard ou de contacter l'équipe de support.
-
+
info_popup_new_version_download_label
- Download it !
Téléchargez-là !
-
+
info_popup_new_version_available_title
New version available !
Nouvelle version disponible !
-
+
info_popup_new_version_available_message
A new version of Linphone (%1) is available. %2
Une nouvelle version de Linphone (%1) est disponible. %2
-
+
info_popup_version_up_to_date_title
- Up to date
À jour
-
+
info_popup_version_up_to_date_message
Your version is up to date
Votre version est à jour
-
+
configuration_error_detail
not reachable
indisponible
-
+
application_description
"A free and open source SIP video-phone."
A free and open source SIP video-phone.
-
+
command_line_arg_order
"Send an order to the application towards a command line"
Send an order to the application towards a command line
-
+
command_line_option_show_help
Show this help
-
+
command_line_option_show_app_version
Afficher la version de l'application
-
+
command_line_option_config_to_fetch
"Specify the linphone configuration file to be fetched. It will be merged with the current configuration."
Specify the linphone configuration file to be fetched. It will be merged with the current configuration.
-
+
command_line_option_config_to_fetch_arg
"URL, path or file"
URL, path or file
-
+
command_line_option_minimized
Minimiser
-
+
command_line_option_log_to_stdout
Log to stdout some debug information while running
-
+
command_line_option_print_app_logs_only
"Print only logs from the application"
Print only logs from the application
-
+
hide_action
"Cacher" "Afficher"
Cacher
-
+
show_action
Afficher
-
+
quit_action
"Quitter"
Quitter
-
+
check_for_update
Check for update
Rechercher une mise à jour
-
+
mark_all_read_action
Marquer tout comme lu
@@ -1005,11 +1018,35 @@
CallHistoryListView
-
+
call_name_accessible_button
Call %1
Appeler %1
+
+
+ call_history_entry_accessible_name
+ %1 - %2 - %3 - right arrow for call-back button
+ %1 - %2 - %3 - flèche droite pour bouton de rappel
+
+
+
+ notification_missed_call_title
+ "Appel manqué"
+ Appel manqué
+
+
+
+ call_outgoing
+ "Appel sortant"
+ Appel sortant
+
+
+
+ call_audio_incoming
+ "Appel entrant"
+ Appel entrant
+
CallLayout
@@ -1066,7 +1103,6 @@
local_group_call
- "Local group call"
Appel de groupe local
@@ -1216,180 +1252,180 @@
Historique d'appel vide
-
+
history_dialog_delete_all_call_logs_title
Supprimer l'historique d'appels ?
Supprimer l'historique d'appels ?
-
+
history_dialog_delete_all_call_logs_message
"L'ensemble de votre historique d'appels sera définitivement supprimé."
L'ensemble de votre historique d'appels sera définitivement supprimé.
-
+
history_dialog_delete_call_logs_title
Supprimer l'historique d'appels ?
Supprimer l'historique d'appels ?
-
+
history_dialog_delete_call_logs_message
"L'ensemble de votre historique d'appels avec ce correspondant sera définitivement supprimé."
L'ensemble de votre historique d'appels avec ce correspondant sera définitivement supprimé.
-
+
call_history_call_list_title
"Appels"
Appels
-
+
call_history_options_accessible_name
Options de l'
-
-
+
+
menu_delete_history
"Supprimer l'historique"
Supprimer l'historique
-
+
call_history_list_options_accessible_name
Call history options
Options de la liste de l'historique d'appel
-
+
create_new_call_accessible_name
Create new call
Créer un nouvel appel
-
+
call_search_in_history
"Rechercher un appel"
Rechercher un appel
-
+
call_forward_to_address_info
Transférer l'appel à :
-
+
call_forward_to_address_info_voicemail
Boîte vocale
-
+
list_filter_no_result_found
"Aucun résultat…"
Aucun résultat…
-
+
history_list_empty_history
"Aucun appel dans votre historique"
Aucun appel dans votre historique
-
+
return_to_call_history_accessible_name
Return to call history
Retourner à l'historique d'appels
-
+
call_action_start_new_call
"Nouvel appel"
Nouvel appel
-
+
call_start_group_call_title
"Appel de groupe"
Appel de groupe
-
+
call_action_start_group_call
"Lancer"
Lancer
-
-
-
+
+
+
information_popup_error_title
Erreur
-
+
group_call_error_must_have_name
"Un nom doit être donné à l'appel de groupe
Un nom doit être donné à l'appel de groupe
-
+
group_call_error_not_connected
"Vous n'etes pas connecté"
Vous n'etes pas connecté
-
+
menu_see_existing_contact
"Show contact"
Voir le contact
-
+
menu_add_address_to_contacts
"Add to contacts"
Ajouter aux contacts
-
+
menu_copy_sip_address
"Copier l'adresse SIP"
Copier l'adresse SIP
-
+
sip_address_copied_to_clipboard_toast
Adresse copiée
Adresse copiée
-
+
sip_address_copied_to_clipboard_message
L'adresse a été copié dans le presse_papiers
L'adresse a été copié dans le presse-papiers
-
+
sip_address_copy_to_clipboard_error
"Erreur lors de la copie de l'adresse"
Erreur lors de la copie de l'adresse
-
+
notification_missed_call_title
"Appel manqué"
Appel manqué
-
+
call_outgoing
"Appel sortant"
Appel sortant
-
+
call_audio_incoming
"Appel entrant"
Appel entrant
@@ -2312,7 +2348,6 @@ Error
popup_error_nb_files_not_found_message
- %n files were not found
%1 fichiers n'ont pas été trouvés
@@ -2333,7 +2368,6 @@ Error
popup_error_unsupported_files_message
- Unable to get supported mime type for %1 files.
Impossible de trouver un type MIME pris en charge pour %1 fichiers.
@@ -2563,115 +2597,115 @@ en bout. Seul votre correspondant peut les déchiffrer.
Aucune conversation
-
+
info_popup_error_title
Erreur
-
+
info_popup_chatroom_creation_failed
Chat room creation failed !
La création de la conversation a échoué !
-
+
loading_popup_chatroom_creation_pending_message
Chat room is being created...
Création de la conversation en cours...
-
+
chat_dialog_delete_chat_title
Supprimer la conversation ?
Supprimer la conversation ?
-
+
chat_dialog_delete_chat_message
"La conversation et tous ses messages seront supprimés."
La conversation et tous ses messages seront supprimés.
-
+
chat_list_title
"Conversations"
Conversations
-
+
menu_mark_all_as_read
"mark all as read"
Tout marquer comme lu
-
+
chat_search_in_history
"Rechercher une conversation"
Rechercher une conversation
-
+
list_filter_no_result_found
"Aucun résultat…"
Aucun résultat…
-
+
chat_list_empty_history
"Aucune conversation dans votre historique"
Aucune conversation dans votre historique
-
+
chat_action_start_new_chat
"New chat"
Nouvelle conversation
-
+
chat_start_group_chat_title
"Nouveau groupe"
Nouveau groupe
-
+
chat_action_start_group_chat
"Créer"
Créer
-
-
-
+
+
+
information_popup_error_title
Erreur
-
+
information_popup_chat_creation_failed_message
"La création a échoué"
La création a échoué
-
+
group_chat_error_must_have_name
"Un nom doit être donné au groupe
Un nom doit être donné au groupe
-
+
group_chat_error_no_participant
"Please select at least one participant
Veuillez sélectionner au moins un participant
-
+
group_call_error_not_connected
"Vous n'etes pas connecté"
Vous n'êtes pas connecté
-
+
chat_creation_in_progress
Creation de la conversation en cours …
Création de la conversation en cours…
@@ -2731,28 +2765,34 @@ en bout. Seul votre correspondant peut les déchiffrer.
CliModel
+
show_function_description
- Afficher
+ Afficher
+
fetch_config_function_description
- Récupérer une configuration
+ Récupérer une configuration
+
call_function_description
- Appeler
+ Appeler
+
bye_function_description
- Raccrocher
+ Raccrocher
+
accept_function_description
- Accepter
+ Accepter
+
decline_function_description
- Décliner
+ Décliner
@@ -2941,53 +2981,71 @@ en bout. Seul votre correspondant peut les déchiffrer.
ContactListItem
-
+
+ call_with_contact_name_accessible_button
+ "Call %1"
+ Appeller %1
+
+
+
+ video_call_with_contact_name_accessible_button
+ "Video call %1"
+ Appel vidéo %1
+
+
+
+ message_with_contact_name_accessible_button
+ "Message %1"
+ Message %1
+
+
+
contact_details_remove_from_favourites
"Enlever des favoris"
Enlever des favoris
-
+
contact_details_add_to_favourites
"Ajouter aux favoris"
Ajouter aux favoris
-
+
Partager
Partager
-
+
information_popup_error_title
Erreur
-
+
information_popup_vcard_creation_error
La création du fichier vcard a échoué
La création du fichier vcard a échoué
-
+
information_popup_vcard_creation_title
VCard créée
VCard créée
-
+
information_popup_vcard_creation_success
"VCard du contact enregistrée dans %1"
VCard du contact enregistrée dans %1
-
+
contact_sharing_email_title
Partage de contact
Partage de contact
-
+
contact_details_delete
"Supprimer"
Supprimer
@@ -3023,149 +3081,149 @@ en bout. Seul votre correspondant peut les déchiffrer.
Aucun contact pour le moment
-
+
contact_new_title
"Nouveau contact"
Nouveau contact
-
+
create
Créer
-
+
contact_edit_title
"Modifier contact"
Modifier contact
-
+
save
Enregistrer
-
+
contact_dialog_delete_title
Supprimer %1 ?"
Supprimer %1 ?
-
+
contact_dialog_delete_message
Ce contact sera définitivement supprimé.
Ce contact sera définitivement supprimé.
-
+
contact_deleted_toast
"Contact supprimé"
Contact supprimé
-
+
contact_deleted_message
"%1 a été supprimé"
%1 a été supprimé
-
+
contact_dialog_devices_trust_popup_title
"Augmenter la confiance"
Augmenter la confiance
-
+
contact_dialog_devices_trust_popup_message
"Pour augmenter le niveau de confiance vous devez appeler les différents appareils de votre contact et valider un code.<br><br>Vous êtes sur le point d’appeler “%1” voulez vous continuer ?"
Pour augmenter le niveau de confiance vous devez appeler les différents appareils de votre contact et valider un code.<br><br>Vous êtes sur le point d’appeler “%1” voulez vous continuer ?
-
+
popup_do_not_show_again
Ne plus afficher
Ne plus afficher
-
+
cancel
Annuler
-
+
dialog_call
"Appeler"
Appeler
-
+
contact_dialog_devices_trust_help_title
"Niveau de confiance"
Niveau de confiance
-
+
contact_dialog_devices_trust_help_message
"Vérifiez les appareils de votre contact pour confirmer que vos communications seront sécurisées et sans compromission. <br>Quand tous seront vérifiés, vous atteindrez le niveau de confiance maximal."
Vérifiez les appareils de votre contact pour confirmer que vos communications seront sécurisées et sans compromission. <br>Quand tous seront vérifiés, vous atteindrez le niveau de confiance maximal.
-
+
dialog_ok
"Ok"
Ok
-
+
bottom_navigation_contacts_label
"Contacts"
Contacts
-
+
search_bar_look_for_contact_text
Rechercher un contact
Rechercher un contact
-
+
list_filter_no_result_found
Aucun résultat…
Aucun résultat…
-
+
contact_list_empty
Aucun contact pour le moment
Aucun contact pour le moment
-
+
expand_accessible_name
Expand %1
Étendre %1
-
+
shrink_accessible_name
Shrink %1
Réduire %1
-
+
create_contact_accessible_name
Create new contact
Créer un nouveau contact
-
+
more_info_accessible_name
More info %1
Plus d'information %1
-
-
+
+
contact_details_edit
Edit
----------
@@ -3173,151 +3231,151 @@ en bout. Seul votre correspondant peut les déchiffrer.
Éditer
-
+
contact_call_action
"Appel"
Appel
-
+
contact_message_action
"Message"
Message
-
+
contact_video_call_action
"Appel vidéo"
Appel vidéo
-
+
contact_details_numbers_and_addresses_title
"Coordonnées"
Coordonnées
-
+
call_adress_accessible_name
Call address %1
Appeller l'adresse %1
-
+
contact_details_company_name
"Société :"
Société :
-
+
contact_details_job_title
"Poste :"
Poste :
-
+
contact_details_medias_title
"Medias"
Medias
-
-
+
+
contact_details_medias_subtitle
"Afficher les medias partagés"
Afficher les medias partagés
-
+
contact_details_trust_title
"Confiance"
Confiance
-
+
contact_dialog_devices_trust_title
"Niveau de confiance - Appareils vérifiés"
Niveau de confiance - Appareils vérifiés
-
+
contact_details_no_device_found
"Aucun appareil"
Aucun appareil
-
+
contact_device_without_name
"Appareil inconnu"
Appareil inconnu
-
+
contact_make_call_check_device_trust
"Vérifier"
Vérifier
-
+
verify_device_accessible_name
Verify %1 device
Vérifier l'appareil %1
-
+
contact_details_actions_title
"Autres actions"
Autres actions
-
+
contact_details_remove_from_favourites
"Retirer des favoris"
Retirer des favoris
-
+
contact_details_add_to_favourites
"Ajouter aux favoris"
Ajouter aux favoris
-
+
contact_details_share
"Partager"
Partager
-
+
information_popup_error_title
Erreur
-
+
contact_details_share_error_mesage
"La création du fichier vcard a échoué"
La création du fichier vcard a échoué
-
+
contact_details_share_success_title
"VCard créée"
VCard créée
-
+
contact_details_share_success_mesage
"VCard du contact enregistrée dans %1"
VCard du contact enregistrée dans %1
-
+
contact_details_share_email_title
"Partage de contact"
Partage de contact
-
+
contact_details_delete
"Supprimer ce contact"
Supprimer ce contact
@@ -4337,7 +4395,6 @@ Expiration : %1
default_account_connection_state_error_toast
- Erreur durant la connexion, veuillez vérifier vos paramètres
Erreur durant la connexion
@@ -4352,144 +4409,144 @@ Expiration : %1
MainLayout
-
+
bottom_navigation_calls_label
"Appels"
Appels
-
+
open_calls_page_accessible_name
"Open calls page"
Ouvrir la page des appels
-
+
bottom_navigation_contacts_label
"Contacts"
Contacts
-
+
open_contacts_page_accessible_name
"Open contacts page"
Ouvrir la page des contacts
-
+
bottom_navigation_conversations_label
"Conversations"
Conversations
-
+
open_conversations_page_accessible_name
"Open conversations page"
Ouvrir la page des conversations
-
+
bottom_navigation_meetings_label
"Réunions"
Réunions
-
+
open_contact_page_accessible_name
"Open meetings page"
Ouvrir la page des réunions
-
+
searchbar_placeholder_text
"Rechercher un contact, appeler %1"
Rechercher un contact, appeler %1
-
+
searchbar_placeholder_text_chat_feature_enabled
"ou envoyer un message …"
ou envoyer un message …
-
+
do_not_disturb_accessible_name
"Do not disturb"
Ne pas déranger
-
-
+
+
contact_presence_status_disable_do_not_disturb
"Désactiver ne pas déranger"
Désactiver ne pas déranger
-
+
information_popup_error_title
Erreur
-
+
no_voicemail_uri_error_message
"L'URI de messagerie vocale n'est pas définie."
L'URI de messagerie vocale n'est pas définie.
-
+
account_list_accessible_name
"Account list"
liste des comptes
-
+
application_options_accessible_name
"Application options"
Options de l'application
-
+
drawer_menu_manage_account
Mon compte
Mon compte
-
+
contact_presence_status_enable_do_not_disturb
"Activer ne pas déranger"
Activer ne pas déranger
-
+
settings_title
Paramètres
-
+
recordings_title
"Enregistrements"
Enregistrements
-
+
help_title
"Aide"
Aide
-
+
help_quit_title
"Quitter l'application"
Quitter l'application
-
+
quit_app_question
"Quitter %1 ?"
Quitter %1 ?
-
+
drawer_menu_add_account
"Ajouter un compte"
Ajouter un compte
@@ -4692,163 +4749,163 @@ Expiration : %1
Aucune réunion
-
+
meeting_schedule_cancel_dialog_message
"Souhaitez-vous annuler et supprimer cette réunion ?"
Souhaitez-vous annuler et supprimer cette réunion ?
-
+
meeting_schedule_delete_dialog_message
Souhaitez-vous supprimer cette réunion ?
Souhaitez-vous supprimer cette réunion ?
-
+
meeting_schedule_cancel_and_delete_action
"Annuler et supprimer"
Annuler et supprimer
-
+
meeting_schedule_delete_only_action
"Supprimer seulement"
Supprimer seulement
-
+
meeting_schedule_delete_action
"Supprimer"
Supprimer
-
+
back_action
Retour
Retour
-
+
meetings_list_title
Réunions
Réunions
-
+
meetings_search_hint
"Rechercher une réunion"
Rechercher une réunion
-
+
list_filter_no_result_found
"Aucun résultat…"
Aucun résultat…
-
+
meetings_empty_list
"Aucune réunion"
Aucune réunion
-
-
+
+
meeting_schedule_title
"Nouvelle réunion"
Nouvelle réunion
-
+
create
Créer
-
-
-
-
-
-
+
+
+
+
+
+
information_popup_error_title
Erreur
-
-
+
+
meeting_schedule_mandatory_field_not_filled_toast
Veuillez saisir un titre et sélectionner au moins un participant
Veuillez saisir un titre et sélectionner au moins un participant
-
-
+
+
meeting_schedule_duration_error_toast
"La fin de la conférence doit être plus récente que son début"
La fin de la conférence doit être plus récente que son début
-
-
+
+
meeting_schedule_creation_in_progress
"Création de la réunion en cours …"
Création de la réunion en cours…
-
+
meeting_info_created_toast
"Réunion planifiée avec succès"
Réunion planifiée avec succès
-
+
meeting_failed_to_schedule_toast
"Échec de création de la réunion !"
Échec de création de la réunion !
-
+
save
Enregistrer
-
-
+
+
saved
"Enregistré"
Enregistré
-
+
meeting_info_updated_toast
"Réunion mise à jour"
Réunion mise à jour
-
+
meeting_schedule_edit_in_progress
"Modification de la réunion en cours…"
Modification de la réunion en cours…
-
+
meeting_failed_to_edit_toast
"Échec de la modification de la réunion !"
Échec de la modification de la réunion !
-
+
meeting_schedule_add_participants_title
"Ajouter des participants"
Ajouter des participants
-
+
meeting_schedule_add_participants_apply
Appliquer
-
+
group_call_participant_selected
"%n participant(s) sélectionné(s)"
@@ -4857,31 +4914,31 @@ Expiration : %1
-
+
meeting_info_delete
"Supprimer la réunion"
Supprimer la réunion
-
+
meeting_address_copied_to_clipboard_toast
"Adresse de la réunion copiée"
Adresse de la réunion copiée
-
+
meeting_schedule_timezone_title
"Fuseau horaire"
Fuseau horaire
-
+
meeting_info_organizer_label
"Organisateur"
Organisateur
-
+
meeting_info_join_title
"Rejoindre la réunion"
Rejoindre la réunion
@@ -5112,6 +5169,36 @@ Expiration : %1
Nouveau message sur la conversation %1
+
+ NumericPad
+
+
+ numpad_longpress_accessible_name
+ %1 longpress %2
+ %1 appui long %2
+
+
+
+ call_accessible_name
+ Call
+ Appeler
+
+
+
+ erase_accessible_name
+ Erase
+ Effacer
+
+
+
+ NumericPadPopup
+
+
+ close_numeric_pad_accessible_name
+ Close numeric pad
+ Fermer le pavé numérique
+
+
OIDCModel
@@ -6080,7 +6167,6 @@ Pour les activer dans un projet commercial, merci de nous contacter.
unknown_audio_device_name
- "Unknown device"
Appareil inconnu
@@ -6282,9 +6368,6 @@ Pour les activer dans un projet commercial, merci de nous contacter.
chat_error
- Error creating or opening the chat
-----------
-Error in the chat
Erreur dans le chat
diff --git a/Linphone/tool/CMakeLists.txt b/Linphone/tool/CMakeLists.txt
index e14869028..923c6f304 100644
--- a/Linphone/tool/CMakeLists.txt
+++ b/Linphone/tool/CMakeLists.txt
@@ -27,6 +27,7 @@ list(APPEND _LINPHONEAPP_SOURCES
tool/file/TemporaryFile.cpp
tool/ui/DashRectangle.cpp
+ tool/ui/FocusNavigator.cpp
tool/accessibility/AccessibilityHelper.cpp
tool/accessibility/KeyboardShortcuts.cpp
diff --git a/Linphone/tool/accessibility/FocusHelper.cpp b/Linphone/tool/accessibility/FocusHelper.cpp
index 392673ce4..877f899f9 100644
--- a/Linphone/tool/accessibility/FocusHelper.cpp
+++ b/Linphone/tool/accessibility/FocusHelper.cpp
@@ -34,6 +34,7 @@ bool FocusHelperAttached::eventFilter(QObject *watched, QEvent *event) {
auto fe = static_cast(event);
if (fe) {
int focusReason = fe->reason();
+ // qDebug() << "FocusReason" << focusReason; // Usefull to debug focus problems
m_keyboardFocus = (focusReason == Qt::TabFocusReason || focusReason == Qt::BacktabFocusReason);
m_otherFocus = focusReason == Qt::OtherFocusReason;
emit keyboardFocusChanged();
diff --git a/Linphone/tool/ui/FocusNavigator.cpp b/Linphone/tool/ui/FocusNavigator.cpp
new file mode 100644
index 000000000..e94724b70
--- /dev/null
+++ b/Linphone/tool/ui/FocusNavigator.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2010-2025 Belledonne Communications SARL.
+ *
+ * This file is part of linphone-desktop
+ * (see https://www.linphone.org).
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "FocusNavigator.hpp"
+
+#include
+#include
+
+FocusNavigator::FocusNavigator(QObject *parent) : QObject(parent) {
+ connect(qApp, &QGuiApplication::focusObjectChanged, this, &FocusNavigator::onFocusObjectChanged);
+ qApp->installEventFilter(this);
+}
+
+bool FocusNavigator::doesLastFocusWasKeyboard() {
+ return mLastFocusWasKeyboard;
+}
+
+bool FocusNavigator::eventFilter(QObject *, QEvent *event) {
+ switch (event->type()) {
+ case QEvent::FocusIn: {
+ auto fe = static_cast(event);
+ if (fe) {
+ int focusReason = fe->reason();
+ mLastFocusWasKeyboard = (focusReason == Qt::TabFocusReason || focusReason == Qt::BacktabFocusReason);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return false;
+}
+
+void FocusNavigator::onFocusObjectChanged(QObject *obj) {
+ // qDebug() << "New focus object" << obj; // Usefull to debug focus problems
+ auto item = qobject_cast(obj);
+ if (!item) return;
+ emit focusChanged(item, mLastFocusWasKeyboard);
+}
diff --git a/Linphone/tool/ui/FocusNavigator.hpp b/Linphone/tool/ui/FocusNavigator.hpp
new file mode 100644
index 000000000..955cf743e
--- /dev/null
+++ b/Linphone/tool/ui/FocusNavigator.hpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010-2025 Belledonne Communications SARL.
+ *
+ * This file is part of linphone-desktop
+ * (see https://www.linphone.org).
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+
+#include
+#include
+
+class FocusNavigator : public QObject {
+ Q_OBJECT
+
+public:
+ explicit FocusNavigator(QObject *parent = nullptr);
+ Q_INVOKABLE bool doesLastFocusWasKeyboard();
+
+protected:
+ bool eventFilter(QObject *obj, QEvent *event) override;
+
+signals:
+ void focusChanged(QQuickItem *item, bool keyboardFocus);
+
+private:
+ bool mLastFocusWasKeyboard = false;
+ void onFocusObjectChanged(QObject *obj);
+};
diff --git a/Linphone/view/Control/Button/IconButton.qml b/Linphone/view/Control/Button/IconButton.qml
index fce059491..2385f1186 100644
--- a/Linphone/view/Control/Button/IconButton.qml
+++ b/Linphone/view/Control/Button/IconButton.qml
@@ -23,7 +23,8 @@ Button {
: mainItem.hovered || mainItem.hasNavigationFocus
? mainItem.hoveredColor
: mainItem.color
- border.color: mainItem.borderColor
+ border.color: mainItem.keyboardFocus ? mainItem.keyboardFocusedBorderColor : mainItem.borderColor
+ border.width: mainItem.keyboardFocus ? mainItem.keyboardFocusedBorderWidth : mainItem.borderWidth
}
contentItem: EffectImage {
diff --git a/Linphone/view/Control/Container/VerticalTabBar.qml b/Linphone/view/Control/Container/VerticalTabBar.qml
index 1d655251f..20dbedf65 100644
--- a/Linphone/view/Control/Container/VerticalTabBar.qml
+++ b/Linphone/view/Control/Container/VerticalTabBar.qml
@@ -18,6 +18,9 @@ Control.TabBar {
property AccountGui defaultAccount
property int visibleCount: 0
+
+ signal enterPressed()
+ signal spacePressed()
// Call it after model is ready. If done before, Repeater will not be updated
function initButtons(){
@@ -96,6 +99,8 @@ Control.TabBar {
onVisibleChanged: mainItem.updateVisibleCount()
text: modelData.accessibilityLabel
property bool keyboardFocus: FocusHelper.keyboardFocus
+ focusPolicy: Qt.StrongFocus
+ activeFocusOnTab: true
UnreadNotification {
unread: !defaultAccount
? -1
@@ -165,6 +170,23 @@ Control.TabBar {
mainItem.implicitWidth = Math.max(mainItem.implicitWidth, advanceWidth + buttonIcon.buttonSize)
}
}
+ Keys.onPressed: event => {
+ if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
+ mainItem.enterPressed()
+ } else if(event.key === Qt.Key_Space){
+ mainItem.spacePressed()
+ } else if(event.key === Qt.Key_Down){
+ event.accepted = true;
+ if(TabBar.index >= mainItem.visibleCount - 1)
+ return;
+ tabButton.nextItemInFocusChain(true).forceActiveFocus(Qt.TabFocusReason)
+ } else if(event.key === Qt.Key_Up){
+ event.accepted = true;
+ if(TabBar.index <= 0)
+ return;
+ tabButton.nextItemInFocusChain(false).forceActiveFocus(Qt.BacktabFocusReason)
+ }
+ }
onClicked: {
mainItem.setCurrentIndex(TabBar.index)
}
diff --git a/Linphone/view/Control/Display/Call/CallHistoryListView.qml b/Linphone/view/Control/Display/Call/CallHistoryListView.qml
index 89c023c2d..6ac875503 100644
--- a/Linphone/view/Control/Display/Call/CallHistoryListView.qml
+++ b/Linphone/view/Control/Display/Call/CallHistoryListView.qml
@@ -5,17 +5,22 @@ import QtQuick.Controls.Basic as Control
import Linphone
import UtilsCpp
import SettingsCpp
+import CustomControls 1.0
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
+ keyNavigationEnabled: false // We will reimplement the keyNavigation
+ activeFocusOnTab: true
property SearchBar searchBar
property bool loading: false
property string searchText: searchBar?.text
property real busyIndicatorSize: Utils.getSizeWithScreenRatio(60)
+ property bool keyboardFocus: FocusHelper.keyboardFocus
+ property bool lastFocusByNavigationKeyboard: false // Workaround to get the correct focusReason
signal resultsReceived
@@ -41,7 +46,26 @@ ListView {
Keys.onPressed: event => {
if (event.key == Qt.Key_Escape) {
console.log("Back")
- searchBar.forceActiveFocus()
+ searchBar.forceActiveFocus(Qt.BacktabFocusReason)
+ event.accepted = true
+ }
+
+ // Re-implement key navigation to have Qt.TabFocusReason and Qt.BacktabFocusReason instead of Qt.OtherFocusReason when using arrows to navigate in listView
+ else if (event.key === Qt.Key_Up) {
+ if(currentIndex === 0){
+ searchBar.forceActiveFocus(Qt.BacktabFocusReason)
+ lastFocusByNavigationKeyboard = false
+ }else{
+ decrementCurrentIndex()
+ currentItem.forceActiveFocus(Qt.BacktabFocusReason) // The focusReason is created by QT later, need to create a workaround
+ lastFocusByNavigationKeyboard = true
+ }
+ event.accepted = true
+ }
+ else if(event.key === Qt.Key_Down){
+ incrementCurrentIndex()
+ currentItem.forceActiveFocus(Qt.TabFocusReason) // The focusReason is created by QT later, need to create a workaround
+ lastFocusByNavigationKeyboard = true
event.accepted = true
}
}
@@ -113,6 +137,8 @@ ListView {
delegate: FocusScope {
width: mainItem.width
height: Utils.getSizeWithScreenRatio(56)
+ Accessible.role: Accessible.ListItem
+
RowLayout {
z: 1
anchors.fill: parent
@@ -188,12 +214,14 @@ ListView {
}
}
BigButton {
+ id: callButton
visible: !modelData.core.isConference || !SettingsCpp.disableMeetingsFeature
style: ButtonStyle.noBackground
icon.source: AppIcons.phone
- focus: true
+ focus: false
activeFocusOnTab: false
asynchronous: false
+
//: Call %1
Accessible.name: qsTr("call_name_accessible_button").arg(historyAvatar.displayNameVal)
onClicked: {
@@ -206,12 +234,38 @@ ListView {
UtilsCpp.createCall(modelData.core.remoteAddress)
}
}
+ Keys.onPressed: event => {
+ if (event.key === Qt.Key_Left){
+ backgroundMouseArea.forceActiveFocus(Qt.BacktabFocusReason)
+ lastFocusByNavigationKeyboard = true;
+ }
+ }
+ onActiveFocusChanged: {
+ if (!activeFocus) {
+ console.log("Unfocus button");
+ callButton.focus = false // Make sure to be unfocusable (could be when called by forceActiveFocus)
+ backgroundMouseArea.focus = true
+ }
+ }
}
}
MouseArea {
+ id: backgroundMouseArea
hoverEnabled: true
anchors.fill: parent
focus: true
+ property bool keyboardFocus: FocusHelper.keyboardFocus || activeFocus && lastFocusByNavigationKeyboard
+
+ //: %1 - %2 - %3 - right arrow for call-back button
+ Accessible.name: qsTr("call_history_entry_accessible_name").arg(
+ //: "Appel manqué"
+ modelData.core.status === LinphoneEnums.CallStatus.Missed ? qsTr("notification_missed_call_title")
+ //: "Appel sortant"
+ : modelData.core.isOutgoing ? qsTr("call_outgoing")
+ //: "Appel entrant"
+ : qsTr("call_audio_incoming")
+ ).arg(historyAvatar.displayNameVal).arg(UtilsCpp.formatDate(modelData.core.date))
+
onContainsMouseChanged: {
if (containsMouse)
mainItem.lastMouseContainsIndex = index
@@ -224,12 +278,20 @@ ListView {
radius: Utils.getSizeWithScreenRatio(8)
color: mainItem.currentIndex
=== index ? DefaultStyle.main2_200 : DefaultStyle.main2_100
+ border.color: backgroundMouseArea.keyboardFocus ? DefaultStyle.main2_900 : "transparent"
+ border.width: backgroundMouseArea.keyboardFocus ? Utils.getSizeWithScreenRatio(3) : 0
visible: mainItem.lastMouseContainsIndex === index
|| mainItem.currentIndex === index
}
onPressed: {
mainItem.currentIndex = model.index
mainItem.forceActiveFocus()
+ mainItem.lastFocusByNavigationKeyboard = false
+ }
+ Keys.onPressed: event => {
+ if(event.key === Qt.Key_Right){
+ callButton.forceActiveFocus(Qt.TabFocusReason)
+ }
}
}
}
diff --git a/Linphone/view/Control/Display/Contact/AllContactListView.qml b/Linphone/view/Control/Display/Contact/AllContactListView.qml
index 4e3af895a..f275677a8 100644
--- a/Linphone/view/Control/Display/Contact/AllContactListView.qml
+++ b/Linphone/view/Control/Display/Contact/AllContactListView.qml
@@ -185,7 +185,7 @@ Flickable {
direction)
if (newItem) {
newItem.selectIndex(
- direction > 0 ? -1 : newItem.model.count - 1)
+ direction > 0 ? -1 : newItem.model.count - 1, direction > 0 ? Qt.BacktabFocusReason : Qt.TabFocusReason)
event.accepted = true
}
}
diff --git a/Linphone/view/Control/Display/Contact/ContactListItem.qml b/Linphone/view/Control/Display/Contact/ContactListItem.qml
index 9d4f57660..bc8458b3a 100644
--- a/Linphone/view/Control/Display/Contact/ContactListItem.qml
+++ b/Linphone/view/Control/Display/Contact/ContactListItem.qml
@@ -6,6 +6,7 @@ import Linphone
import UtilsCpp
import ConstantsCpp
import SettingsCpp
+import CustomControls 1.0
import "qrc:/qt/qml/Linphone/view/Style/buttonStyle.js" as ButtonStyle
import "qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js" as Utils
@@ -149,6 +150,9 @@ FocusScope {
onClicked: UtilsCpp.createCall(mainItem.addressFromFilter)
KeyNavigation.left: chatButton
KeyNavigation.right: videoCallButton
+ //: "Call %1"
+ Accessible.name: qsTr("call_with_contact_name_accessible_button").arg(mainItem.displayName)
+ keyboardFocus: FocusHelper.keyboardFocus || FocusHelper.otherFocus
}
IconButton {
id: videoCallButton
@@ -164,6 +168,9 @@ FocusScope {
onClicked: UtilsCpp.createCall(mainItem.addressFromFilter, {"localVideoEnabled": true})
KeyNavigation.left: callButton
KeyNavigation.right: chatButton
+ //: "Video call %1"
+ Accessible.name: qsTr("video_call_with_contact_name_accessible_button").arg(mainItem.displayName)
+ keyboardFocus: FocusHelper.keyboardFocus || FocusHelper.otherFocus
}
IconButton {
id: chatButton
@@ -184,6 +191,9 @@ FocusScope {
console.debug("[ContactListItem.qml] Open conversation")
mainWindow.displayChatPage(mainItem.addressFromFilter)
}
+ //: "Message %1"
+ Accessible.name: qsTr("message_with_contact_name_accessible_button").arg(mainItem.displayName)
+ keyboardFocus: FocusHelper.keyboardFocus || FocusHelper.otherFocus
}
}
PopupButton {
diff --git a/Linphone/view/Control/Display/Contact/ContactListView.qml b/Linphone/view/Control/Display/Contact/ContactListView.qml
index ca86cd767..d5944d301 100644
--- a/Linphone/view/Control/Display/Contact/ContactListView.qml
+++ b/Linphone/view/Control/Display/Contact/ContactListView.qml
@@ -68,13 +68,13 @@ ListView {
property bool _moveToIndex: false
- function selectIndex(index){
+ function selectIndex(index, focusReason = Qt.OtherFocusReason){
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()
+ item.forceActiveFocus(focusReason)
updatePosition()
_moveToIndex = false
}else{// Move on the next items load.
@@ -85,7 +85,7 @@ ListView {
mainItem.currentIndex = -1
mainItem.highlightedContact = null
if(headerItem) {
- headerItem.forceActiveFocus()
+ headerItem.forceActiveFocus(focusReason)
}
_moveToIndex = false
}
@@ -97,12 +97,12 @@ ListView {
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)
+ selectIndex(mainItem.currentIndex-1, Qt.BacktabFocusReason)
event.accepted = true;
}
}else if(event.key == Qt.Key_Down && mainItem.expanded){
if(currentIndex < model.count - 1) {
- selectIndex(mainItem.currentIndex+1)
+ selectIndex(mainItem.currentIndex+1, Qt.TabFocusReason)
event.accepted = true;
}
}
diff --git a/Linphone/view/Control/Display/Settings/SettingsMenuItem.qml b/Linphone/view/Control/Display/Settings/SettingsMenuItem.qml
index 2792a8d91..e953b0f49 100644
--- a/Linphone/view/Control/Display/Settings/SettingsMenuItem.qml
+++ b/Linphone/view/Control/Display/Settings/SettingsMenuItem.qml
@@ -20,6 +20,7 @@ Item {
//: %1 settings
Accessible.name: qsTr("setting_tab_accessible_name").arg(titleText)
+ Accessible.role: Accessible.ListItem
Keys.onPressed: (event)=>{
if(event.key == Qt.Key_Space || event.key == Qt.Key_Return || event.key == Qt.Key_Enter){
diff --git a/Linphone/view/Control/Input/NumericPad.qml b/Linphone/view/Control/Input/NumericPad.qml
index f145c14e1..c5fb1b5dc 100644
--- a/Linphone/view/Control/Input/NumericPad.qml
+++ b/Linphone/view/Control/Input/NumericPad.qml
@@ -172,6 +172,9 @@ FocusScope {
radius: Utils.getSizeWithScreenRatio(71)
style: ButtonStyle.numericPad
+ //: %1 longpress %2
+ Accessible.name: longPressText.text ? qsTr("numpad_longpress_accessible_name").arg(pressText.text).arg(longPressText.text) : pressText.text
+
contentItem: Item {
anchors.fill: parent
Text {
@@ -214,7 +217,10 @@ FocusScope {
icon.height: Utils.getSizeWithScreenRatio(32)
radius: Utils.getSizeWithScreenRatio(71)
style: ButtonStyle.phoneGreen
-
+
+ //: Call
+ Accessible.name: qsTr("call_accessible_name")
+
onClicked: mainItem.launchCall()
KeyNavigation.left: eraseButton
@@ -237,6 +243,9 @@ FocusScope {
Layout.Layout.preferredWidth: Utils.getSizeWithScreenRatio(38)
Layout.Layout.preferredHeight: Utils.getSizeWithScreenRatio(38)
+ //: Erase
+ Accessible.name: qsTr("erase_accessible_name")
+
onClicked: mainItem.wipe()
KeyNavigation.left: launchCallButton
@@ -244,8 +253,13 @@ FocusScope {
KeyNavigation.up: numPadGrid.getButtonAt(11)
KeyNavigation.down: numPadGrid.getButtonAt(1)
- background: Item {
- visible: false
+ background: Rectangle {
+ width: eraseButton.width
+ height: eraseButton.height
+ color: "transparent"
+
+ border.color: eraseButton.keyboardFocus ? eraseButton.keyboardFocusedBorderColor : "transparent"
+ border.width: eraseButton.keyboardFocus ? eraseButton.keyboardFocusedBorderWidth : eraseButton.borderWidth
}
}
}
diff --git a/Linphone/view/Control/Popup/NumericPadPopup.qml b/Linphone/view/Control/Popup/NumericPadPopup.qml
index 56c763ee3..529448e99 100644
--- a/Linphone/view/Control/Popup/NumericPadPopup.qml
+++ b/Linphone/view/Control/Popup/NumericPadPopup.qml
@@ -69,6 +69,8 @@ Control.Popup {
icon.height: Utils.getSizeWithScreenRatio(24)
style: ButtonStyle.noBackground
onClicked: mainItem.close()
+ //: Close numeric pad
+ Accessible.name: qsTr("close_numeric_pad_accessible_name")
}
}
contentItem: NumericPad{
diff --git a/Linphone/view/Control/Tool/Helper/utils.js b/Linphone/view/Control/Tool/Helper/utils.js
index 9b72b4c14..e7e99ed42 100644
--- a/Linphone/view/Control/Tool/Helper/utils.js
+++ b/Linphone/view/Control/Tool/Helper/utils.js
@@ -807,6 +807,17 @@ function infoDialog(window, message) {
}, function (status) {})
}
+// Ensure that the item is visible in the view
+function ensureVisibleY(item, view){
+ const itemPosition = item.mapToItem(view, 0, 0)
+
+ if (itemPosition.y < 0){
+ view.contentY = view.contentY + itemPosition.y
+ } else if (itemPosition.y + item.height > view.height){
+ view.contentY = itemPosition.y + view.contentY + item.height - view.height
+ }
+}
+
// Set position of list.currentItem into the scrollItem
function updatePosition(scrollItem, list){
if(scrollItem.height == 0) return;
diff --git a/Linphone/view/Page/Form/Settings/AbstractSettingsMenu.qml b/Linphone/view/Page/Form/Settings/AbstractSettingsMenu.qml
index 3cbe9ee8e..d5b461158 100644
--- a/Linphone/view/Page/Form/Settings/AbstractSettingsMenu.qml
+++ b/Linphone/view/Page/Form/Settings/AbstractSettingsMenu.qml
@@ -48,6 +48,8 @@ AbstractMainPage {
onClicked: {
mainItem.goBackRequested()
}
+ //: Back to previous menu
+ Accessible.name: qsTr("back_previous_menu_accessible_name")
}
Text {
text: titleText
@@ -69,6 +71,9 @@ AbstractMainPage {
property int selectedIndex: mainItem.defaultIndex != -1 ? mainItem.defaultIndex : 0
activeFocusOnTab: true
spacing: Utils.getSizeWithScreenRatio(5)
+ Accessible.role: Accessible.List
+ //: Settings page selection
+ Accessible.name: qsTr("settings_page_selection_accessible_name")
delegate: SettingsMenuItem {
titleText: modelData.title
@@ -86,7 +91,9 @@ AbstractMainPage {
let initialEntry = mainItem.families[familiesList.selectedIndex]
rightPanelStackView.push(layoutUrl(initialEntry.layout), { titleText: initialEntry.title, model: initialEntry.model, container: rightPanelStackView})
familiesList.currentIndex = familiesList.selectedIndex
- backButton.forceActiveFocus()
}
}
+ Control.StackView.onActivated: {
+ familiesList.forceActiveFocus(FocusNavigator.doesLastFocusWasKeyboard() ? Qt.TabFocusReason : Qt.MouseFocusReason)
+ }
}
diff --git a/Linphone/view/Page/Layout/Main/MainLayout.qml b/Linphone/view/Page/Layout/Main/MainLayout.qml
index e108ff40c..bdc9508f4 100644
--- a/Linphone/view/Page/Layout/Main/MainLayout.qml
+++ b/Linphone/view/Page/Layout/Main/MainLayout.qml
@@ -14,6 +14,7 @@ Item {
id: mainItem
property var callObj
property var contextualMenuOpenedComponent: undefined
+ property bool focusPageOnNextLoad: false // Focus the page on next load - usefull cause of loader
signal addAccountRequest
signal openNewCallRequest
@@ -184,6 +185,18 @@ Item {
mainStackView.currentItem.forceActiveFocus();
}
}
+
+ /**
+ * Focus the page when user select the page with keyboard.
+ * Do not add this behavior on the arrows
+ */
+ onEnterPressed: {
+ focusPageOnNextLoad = true
+ }
+ onSpacePressed: {
+ focusPageOnNextLoad = true
+ }
+
Component.onCompleted: {
if (SettingsCpp.shortcutCount > 0) {
var shortcuts = SettingsCpp.shortcuts;
@@ -639,6 +652,10 @@ Item {
openContextualMenuComponent(page);
}
}
+ onLoaded: {
+ if(focusPageOnNextLoad) item.forceActiveFocus(Qt.TabFocusReason)
+ focusPageOnNextLoad = false
+ }
}
Loader {
active: mainStackLayout.currentIndex === 1
@@ -654,6 +671,10 @@ Item {
}
}
}
+ onLoaded: {
+ if(focusPageOnNextLoad) item.forceActiveFocus(Qt.TabFocusReason)
+ focusPageOnNextLoad = false
+ }
}
Loader {
active: mainStackLayout.currentIndex === 2
@@ -672,6 +693,10 @@ Item {
}
}
}
+ onLoaded: {
+ if(focusPageOnNextLoad) item.forceActiveFocus(Qt.TabFocusReason)
+ focusPageOnNextLoad = false
+ }
}
Loader {
@@ -688,6 +713,10 @@ Item {
}
}
}
+ onLoaded: {
+ if(focusPageOnNextLoad) item.forceActiveFocus(Qt.TabFocusReason)
+ focusPageOnNextLoad = false
+ }
}
}
diff --git a/Linphone/view/Page/Layout/Settings/AbstractSettingsLayout.qml b/Linphone/view/Page/Layout/Settings/AbstractSettingsLayout.qml
index bf995d01f..1e175a822 100644
--- a/Linphone/view/Page/Layout/Settings/AbstractSettingsLayout.qml
+++ b/Linphone/view/Page/Layout/Settings/AbstractSettingsLayout.qml
@@ -100,17 +100,13 @@ Rectangle {
}
}
}
- Control.ScrollView {
+ Flickable {
id: scrollView
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.top: header.bottom
anchors.topMargin: Utils.getSizeWithScreenRatio(16)
- // Workaround while the CI is made with Qt6.5.3
- // When updated to 6.8, remove this Item and
- // change the ScrollView with a Flickable
- Item{anchors.fill: parent}
contentHeight: contentListView.contentHeight
Control.ScrollBar.vertical: ScrollBar {
active: contentListView.contentHeight > scrollView.height
@@ -130,21 +126,21 @@ Rectangle {
model: mainItem.contentModel
anchors.left: parent.left
anchors.right: parent.right
- anchors.leftMargin: Utils.getSizeWithScreenRatio(45)
- anchors.rightMargin: Utils.getSizeWithScreenRatio(45)
+ anchors.leftMargin: Utils.getSizeWithScreenRatio(45)
+ anchors.rightMargin: Utils.getSizeWithScreenRatio(45)
height: contentHeight
- spacing: Utils.getSizeWithScreenRatio(10)
+ spacing: Utils.getSizeWithScreenRatio(10)
delegate: ColumnLayout {
- visible: modelData.visible != undefined ? modelData.visible: true
- Component.onCompleted: if (!visible) height = 0
- spacing: Utils.getSizeWithScreenRatio(16)
+ visible: modelData.visible != undefined ? modelData.visible: true
+ Component.onCompleted: if (!visible) height = 0
+ spacing: Utils.getSizeWithScreenRatio(16)
width: contentListView.width
Rectangle {
visible: index !== 0
- Layout.topMargin: Utils.getSizeWithScreenRatio(modelData.hideTopSeparator ? 0 : 16)
- Layout.bottomMargin: Utils.getSizeWithScreenRatio(16)
+ Layout.topMargin: Utils.getSizeWithScreenRatio(modelData.hideTopSeparator ? 0 : 16)
+ Layout.bottomMargin: Utils.getSizeWithScreenRatio(16)
Layout.fillWidth: true
- height: Utils.getSizeWithScreenRatio(1)
+ height: Utils.getSizeWithScreenRatio(1)
color: modelData.hideTopSeparator ? 'transparent' : DefaultStyle.main2_500_main
}
GridLayout {
@@ -152,12 +148,12 @@ Rectangle {
columns: mainItem.useVerticalLayout ? 1 : 2
Layout.fillWidth: true
// Layout.preferredWidth: parent.width
- rowSpacing: modelData.title.length > 0 || modelData.subTitle.length > 0 ? Utils.getSizeWithScreenRatio(20) : 0
- columnSpacing: Utils.getSizeWithScreenRatio(47)
+ rowSpacing: modelData.title.length > 0 || modelData.subTitle.length > 0 ? Utils.getSizeWithScreenRatio(20) : 0
+ columnSpacing: Utils.getSizeWithScreenRatio(47)
ColumnLayout {
- Layout.preferredWidth: Utils.getSizeWithScreenRatio(341)
- Layout.maximumWidth: Utils.getSizeWithScreenRatio(341)
- spacing: Utils.getSizeWithScreenRatio(3)
+ Layout.preferredWidth: Utils.getSizeWithScreenRatio(341)
+ Layout.maximumWidth: Utils.getSizeWithScreenRatio(341)
+ spacing: Utils.getSizeWithScreenRatio(3)
Text {
text: modelData.title
visible: modelData.title.length > 0
@@ -179,10 +175,10 @@ Rectangle {
}
}
RowLayout {
- Layout.topMargin: modelData.hideTopMargin ? 0 : Utils.getSizeWithScreenRatio(mainItem.useVerticalLayout ? 10 : 21)
- Layout.bottomMargin: Utils.getSizeWithScreenRatio(21)
- Layout.leftMargin: mainItem.useVerticalLayout ? 0 : Utils.getSizeWithScreenRatio(17)
- Layout.preferredWidth: Utils.getSizeWithScreenRatio(modelData.customWidth > 0 ? modelData.customWidth : 545)
+ Layout.topMargin: modelData.hideTopMargin ? 0 : Utils.getSizeWithScreenRatio(mainItem.useVerticalLayout ? 10 : 21)
+ Layout.bottomMargin: Utils.getSizeWithScreenRatio(21)
+ Layout.leftMargin: mainItem.useVerticalLayout ? 0 : Utils.getSizeWithScreenRatio(17)
+ Layout.preferredWidth: Utils.getSizeWithScreenRatio(modelData.customWidth > 0 ? modelData.customWidth : 545)
Layout.alignment: Qt.AlignRight
Loader {
id: contentLoader
@@ -190,12 +186,22 @@ Rectangle {
sourceComponent: modelData.contentComponent
}
Item {
- Layout.preferredWidth: Utils.getSizeWithScreenRatio(modelData.customRightMargin > 0 ? modelData.customRightMargin : 17)
+ Layout.preferredWidth: Utils.getSizeWithScreenRatio(modelData.customRightMargin > 0 ? modelData.customRightMargin : 17)
}
}
}
}
}
+
+ Connections {
+ target: FocusNavigator
+
+ function onFocusChanged(item, keyboardFocus) {
+ if(Utils.isDescendant(item,scrollView) && keyboardFocus){
+ Utils.ensureVisibleY(item, scrollView)
+ }
+ }
+ }
}
}
diff --git a/Linphone/view/Page/Main/Call/CallPage.qml b/Linphone/view/Page/Main/Call/CallPage.qml
index 372de87fa..d6ffb7bc3 100644
--- a/Linphone/view/Page/Main/Call/CallPage.qml
+++ b/Linphone/view/Page/Main/Call/CallPage.qml
@@ -24,6 +24,14 @@ AbstractMainPage {
goToCallHistory()
}
+ /**
+ * Focus on the first pertinent element in the page (LINQT-2202)
+ * @override
+ */
+ function forceActiveFocus(reason = undefined){
+ listStackView.currentItem?.newCallButton?.forceActiveFocus(reason)
+ }
+
//Group call properties
property ConferenceInfoGui confInfoGui
property AccountProxy accounts: AccountProxy {
@@ -134,6 +142,8 @@ AbstractMainPage {
FocusScope {
objectName: "historyListItem"
property alias listView: historyListView
+ property alias newCallButton: newCallButton
+
ColumnLayout {
anchors.fill: parent
spacing: 0
@@ -187,6 +197,7 @@ AbstractMainPage {
}
Button {
id: newCallButton
+ focus: true
style: ButtonStyle.noBackground
icon.source: AppIcons.newCall
Layout.preferredWidth: Utils.getSizeWithScreenRatio(34)
diff --git a/Linphone/view/Page/Main/Chat/ChatPage.qml b/Linphone/view/Page/Main/Chat/ChatPage.qml
index c50b4a7bb..e141a6adf 100644
--- a/Linphone/view/Page/Main/Chat/ChatPage.qml
+++ b/Linphone/view/Page/Main/Chat/ChatPage.qml
@@ -16,6 +16,14 @@ AbstractMainPage {
emptyListText: qsTr("chat_empty_title")
newItemIconSource: AppIcons.plusCircle
+ /**
+ * Focus on the first pertinent element in the page (LINQT-2202)
+ * @override
+ */
+ function forceActiveFocus(reason = undefined){
+ listStackView.currentItem?.newChatButton?.forceActiveFocus(reason)
+ }
+
property AccountProxy accounts: AccountProxy {
id: accountProxy
}
@@ -116,6 +124,7 @@ AbstractMainPage {
FocusScope {
objectName: "chatListItem"
property alias listView: chatListView
+ property alias newChatButton: newChatButton
ColumnLayout {
anchors.fill: parent
spacing: 0
@@ -158,6 +167,7 @@ AbstractMainPage {
}
Button {
id: newChatButton
+ focus: true
style: ButtonStyle.noBackground
icon.source: AppIcons.plusCircle
Layout.preferredWidth: Utils.getSizeWithScreenRatio(28)
diff --git a/Linphone/view/Page/Main/Contact/ContactPage.qml b/Linphone/view/Page/Main/Contact/ContactPage.qml
index 2b58cbb20..135270a1d 100644
--- a/Linphone/view/Page/Main/Contact/ContactPage.qml
+++ b/Linphone/view/Page/Main/Contact/ContactPage.qml
@@ -17,6 +17,14 @@ AbstractMainPage {
emptyListText: qsTr("contacts_list_empty")
newItemIconSource: AppIcons.plusCircle
+ /**
+ * Focus on the first pertinent element in the page (LINQT-2202)
+ * @override
+ */
+ function forceActiveFocus(reason = undefined){
+ createContactButton.forceActiveFocus(reason)
+ }
+
// disable left panel contact list interaction while a contact is being edited
property bool leftPanelEnabled: !rightPanelStackView.currentItem
|| rightPanelStackView.currentItem.objectName
@@ -243,6 +251,7 @@ AbstractMainPage {
visible: !rightPanelStackView.currentItem
|| rightPanelStackView.currentItem.objectName !== "contactEdition"
style: ButtonStyle.noBackground
+ focus: true
icon.source: AppIcons.plusCircle
Layout.preferredWidth: Utils.getSizeWithScreenRatio(28)
Layout.preferredHeight: Utils.getSizeWithScreenRatio(28)
diff --git a/Linphone/view/Page/Main/Meeting/MeetingPage.qml b/Linphone/view/Page/Main/Meeting/MeetingPage.qml
index 326fbf76a..a57b9fe9f 100644
--- a/Linphone/view/Page/Main/Meeting/MeetingPage.qml
+++ b/Linphone/view/Page/Main/Meeting/MeetingPage.qml
@@ -26,6 +26,15 @@ AbstractMainPage {
rightPanelStackTopMargin: Utils.getSizeWithScreenRatio(45)
rightPanelStackBottomMargin: Utils.getSizeWithScreenRatio(30)
+ /**
+ * Focus on the first pertinent element in the page (LINQT-2202)
+ * @override
+ */
+ function forceActiveFocus(reason = undefined){
+ leftPanelStackView.currentItem?.newConfButton?.forceActiveFocus(reason)
+ }
+
+
function createPreFilledMeeting(subject, addresses) {
mainItem.selectedConference = Qt.createQmlObject('import Linphone
ConferenceInfoGui{
@@ -137,6 +146,7 @@ AbstractMainPage {
id: listLayout
FocusScope{
property string objectName: "listLayout"
+ property alias newConfButton: newConfButton
Control.StackView.onDeactivated: {
mainItem.selectedConference = null
}
@@ -166,6 +176,7 @@ AbstractMainPage {
}
Button {
id: newConfButton
+ focus: true
style: ButtonStyle.noBackground
icon.source: AppIcons.plusCircle
Layout.preferredWidth: Utils.getSizeWithScreenRatio(28)