mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-30 18:39:23 +00:00
- Fix : display name didn't support UTF8. Address created from Factory take a UTF8 string, aswell as setDisplayName
- Show Historic calls - Handle cursor shapes on mousearea
This commit is contained in:
parent
e3c6e0cd35
commit
e55f218352
73 changed files with 1753 additions and 99 deletions
|
|
@ -138,6 +138,8 @@ set(SOURCES
|
|||
src/components/core/event-count-notifier/AbstractEventCountNotifier.cpp
|
||||
src/components/file/FileDownloader.cpp
|
||||
src/components/file/FileExtractor.cpp
|
||||
src/components/history/HistoryModel.cpp
|
||||
src/components/history/HistoryProxyModel.cpp
|
||||
src/components/notifier/Notifier.cpp
|
||||
src/components/other/clipboard/Clipboard.cpp
|
||||
src/components/other/colors/Colors.cpp
|
||||
|
|
@ -198,6 +200,8 @@ set(HEADERS
|
|||
src/components/core/event-count-notifier/AbstractEventCountNotifier.hpp
|
||||
src/components/file/FileDownloader.hpp
|
||||
src/components/file/FileExtractor.hpp
|
||||
src/components/history/HistoryModel.hpp
|
||||
src/components/history/HistoryProxyModel.hpp
|
||||
src/components/notifier/Notifier.hpp
|
||||
src/components/other/clipboard/Clipboard.hpp
|
||||
src/components/other/colors/Colors.hpp
|
||||
|
|
|
|||
|
|
@ -830,6 +830,25 @@ Server url ikke konfigureret.</translation>
|
|||
<translation>Det er nødvendigt at genstarte applikationen. Vil du gøre det nu?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HistoryView</name>
|
||||
<message>
|
||||
<source>removeAllEntriesDescription</source>
|
||||
<translation type="unfinished">Er du sikker på at du vil rydde op historikken?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactEdit</source>
|
||||
<translation type="unfinished">Rediger kontakt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactAdd</source>
|
||||
<translation type="unfinished">Tilføj kontakt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>cleanHistory</source>
|
||||
<translation type="unfinished">Slet historik</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Home</name>
|
||||
<message>
|
||||
|
|
|
|||
|
|
@ -830,6 +830,25 @@ Server URL ist nicht konfiguriert.</translation>
|
|||
<translation>Ein Neustart der Anwendung ist notwendig. Möchten Sie die Anwendung jetzt neu starten?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HistoryView</name>
|
||||
<message>
|
||||
<source>removeAllEntriesDescription</source>
|
||||
<translation type="unfinished">Möchten Sie diese Historie wirklich löschen?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactEdit</source>
|
||||
<translation type="unfinished">Kontakt bearbeiten</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactAdd</source>
|
||||
<translation type="unfinished">Kontakt hinzufügen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>cleanHistory</source>
|
||||
<translation type="unfinished">Verlauf löschen</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Home</name>
|
||||
<message>
|
||||
|
|
|
|||
|
|
@ -832,6 +832,25 @@ Server URL not configured.</translation>
|
|||
<translation>It is necessary to restart the application. Do you want to restart now?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HistoryView</name>
|
||||
<message>
|
||||
<source>removeAllEntriesDescription</source>
|
||||
<translation type="unfinished">Are you sure you want to clear this history?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactEdit</source>
|
||||
<translation type="unfinished">Edit contact</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactAdd</source>
|
||||
<translation type="unfinished">Add contact</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>cleanHistory</source>
|
||||
<translation type="unfinished">Delete history</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Home</name>
|
||||
<message>
|
||||
|
|
|
|||
|
|
@ -830,6 +830,25 @@ URL del servidor no configurada.</translation>
|
|||
<translation>Es necesario reiniciar la aplicación. ¿Desea reiniciarla ahora?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HistoryView</name>
|
||||
<message>
|
||||
<source>removeAllEntriesDescription</source>
|
||||
<translation type="unfinished">¿Estás seguro de que quieres limpiar este historial?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactEdit</source>
|
||||
<translation type="unfinished">Editar contacto</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactAdd</source>
|
||||
<translation type="unfinished">Añadir contacto</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>cleanHistory</source>
|
||||
<translation type="unfinished">Eliminar historial</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Home</name>
|
||||
<message>
|
||||
|
|
|
|||
|
|
@ -830,6 +830,25 @@ Url du serveur non configurée.</translation>
|
|||
<translation>Voulez-vous redémarrer maintenant pour prendre en compte ces modifications ?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HistoryView</name>
|
||||
<message>
|
||||
<source>removeAllEntriesDescription</source>
|
||||
<translation type="unfinished">Êtes-vous sûr de vouloir supprimer cet historique ?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactEdit</source>
|
||||
<translation type="unfinished">Editer le contact</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactAdd</source>
|
||||
<translation type="unfinished">Ajouter le contact</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>cleanHistory</source>
|
||||
<translation type="unfinished">Supprimer l'historique</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Home</name>
|
||||
<message>
|
||||
|
|
|
|||
|
|
@ -830,6 +830,25 @@ A kiszolgáló URL-je nincs konfigurálva.</translation>
|
|||
<translation>Az alkalmazás újraindítása szükséges. Szeretné most újraindítani?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HistoryView</name>
|
||||
<message>
|
||||
<source>removeAllEntriesDescription</source>
|
||||
<translation type="unfinished">Biztosan törölni kívánja ezt az előzményt?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactEdit</source>
|
||||
<translation type="unfinished">Kapcsolat szerkesztése</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactAdd</source>
|
||||
<translation type="unfinished">Kapcsolat hozzáadása</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>cleanHistory</source>
|
||||
<translation type="unfinished">Előzmények törlése</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Home</name>
|
||||
<message>
|
||||
|
|
|
|||
|
|
@ -830,6 +830,25 @@ URL del server non configurato.</translation>
|
|||
<translation>È necessario riavviare l'applicazione. Vuoi riavviare ora?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HistoryView</name>
|
||||
<message>
|
||||
<source>removeAllEntriesDescription</source>
|
||||
<translation type="unfinished">Sei sicuro di voler cancellare questa cronologia?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactEdit</source>
|
||||
<translation type="unfinished">Modifica contatto</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactAdd</source>
|
||||
<translation type="unfinished">Aggiungi contatto</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>cleanHistory</source>
|
||||
<translation type="unfinished">Cancella cronologia</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Home</name>
|
||||
<message>
|
||||
|
|
|
|||
|
|
@ -830,6 +830,25 @@
|
|||
<translation>アプリケーションを再起動する必要があります。今すぐ再起動しますか?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HistoryView</name>
|
||||
<message>
|
||||
<source>removeAllEntriesDescription</source>
|
||||
<translation type="unfinished">履歴をクリアしてよろしいですか?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactEdit</source>
|
||||
<translation type="unfinished">連絡先の編集</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactAdd</source>
|
||||
<translation type="unfinished">連絡先の追加</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>cleanHistory</source>
|
||||
<translation type="unfinished">履歴の削除</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Home</name>
|
||||
<message>
|
||||
|
|
|
|||
|
|
@ -830,6 +830,25 @@ Nesukonfigūruotas serverio url.</translation>
|
|||
<translation>Yra būtina paleisti programą iš naujo. Ar norite tai atlikti dabar?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HistoryView</name>
|
||||
<message>
|
||||
<source>removeAllEntriesDescription</source>
|
||||
<translation type="unfinished">Ar tikrai norite išvalyti šią istoriją?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactEdit</source>
|
||||
<translation type="unfinished">Redaguoti kontaktą</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactAdd</source>
|
||||
<translation type="unfinished">Pridėti kontaktą</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>cleanHistory</source>
|
||||
<translation type="unfinished">Ištrinti istoriją</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Home</name>
|
||||
<message>
|
||||
|
|
|
|||
|
|
@ -830,6 +830,25 @@ URL do servidor não configurado.</translation>
|
|||
<translation>É necessário reiniciar o aplicativo. Deseja reiniciar agora?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HistoryView</name>
|
||||
<message>
|
||||
<source>removeAllEntriesDescription</source>
|
||||
<translation type="unfinished">Tem certeza de que deseja limpar esse histórico?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactEdit</source>
|
||||
<translation type="unfinished">Editar contato</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactAdd</source>
|
||||
<translation type="unfinished">Adicionar contato</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>cleanHistory</source>
|
||||
<translation type="unfinished">Excluir histórico</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Home</name>
|
||||
<message>
|
||||
|
|
|
|||
|
|
@ -830,6 +830,25 @@
|
|||
<translation>Требуется перезапустить приложение. Хотите перезапустить сейчас?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HistoryView</name>
|
||||
<message>
|
||||
<source>removeAllEntriesDescription</source>
|
||||
<translation type="unfinished">Вы уверены, что хотите очистить эту историю?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactEdit</source>
|
||||
<translation type="unfinished">Изменить контакт</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactAdd</source>
|
||||
<translation type="unfinished">Добавить контакт</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>cleanHistory</source>
|
||||
<translation type="unfinished">Удалить историю</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Home</name>
|
||||
<message>
|
||||
|
|
|
|||
|
|
@ -830,6 +830,25 @@ Serverwebbadressen är inte konfigurerad.</translation>
|
|||
<translation>Det är nödvändigt att starta om programmet. Vill du starta om nu?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HistoryView</name>
|
||||
<message>
|
||||
<source>removeAllEntriesDescription</source>
|
||||
<translation type="unfinished">Är du säker på att du vill rensa den här historiken?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactEdit</source>
|
||||
<translation type="unfinished">Redigera kontakt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactAdd</source>
|
||||
<translation type="unfinished">Lägg till kontakt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>cleanHistory</source>
|
||||
<translation type="unfinished">Radera historik</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Home</name>
|
||||
<message>
|
||||
|
|
|
|||
|
|
@ -830,6 +830,25 @@ Sunucu url'si yapılandırılmadı.</translation>
|
|||
<translation>Uygulamanın yeniden başlaması gerekiyor. Şimdi yeniden başlatmak ister misiniz?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HistoryView</name>
|
||||
<message>
|
||||
<source>removeAllEntriesDescription</source>
|
||||
<translation type="unfinished">Bu geçmişi temizlemek istediğinize emin misiniz?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactEdit</source>
|
||||
<translation type="unfinished">Kişi düzenle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactAdd</source>
|
||||
<translation type="unfinished">Kişi ekle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>cleanHistory</source>
|
||||
<translation type="unfinished">Geçmişi sil</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Home</name>
|
||||
<message>
|
||||
|
|
|
|||
|
|
@ -830,6 +830,25 @@
|
|||
<translation>Потрібно перезапустити застосунок. Бажаєте перезапустити зараз?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HistoryView</name>
|
||||
<message>
|
||||
<source>removeAllEntriesDescription</source>
|
||||
<translation type="unfinished">Ви впевнені, що волієте вичистити цю історію?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactEdit</source>
|
||||
<translation type="unfinished">Редагувати контакт</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactAdd</source>
|
||||
<translation type="unfinished">Додати контакт</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>cleanHistory</source>
|
||||
<translation type="unfinished">Вилучити історію</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Home</name>
|
||||
<message>
|
||||
|
|
|
|||
|
|
@ -830,6 +830,25 @@
|
|||
<translation>需要重启应用程序。您想要立刻重启吗?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HistoryView</name>
|
||||
<message>
|
||||
<source>removeAllEntriesDescription</source>
|
||||
<translation type="unfinished">你确定要清除该历史吗?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactEdit</source>
|
||||
<translation type="unfinished">编辑联系人</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>tooltipContactAdd</source>
|
||||
<translation type="unfinished">添加联系人</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>cleanHistory</source>
|
||||
<translation type="unfinished">删除历史记录</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Home</name>
|
||||
<message>
|
||||
|
|
|
|||
|
|
@ -229,6 +229,7 @@
|
|||
<file>ui/modules/Common/Form/ListForm.qml</file>
|
||||
<file>ui/modules/Common/Form/ListItemSelector.js</file>
|
||||
<file>ui/modules/Common/Form/ListItemSelector.qml</file>
|
||||
<file>ui/modules/Common/Form/MouseArea.qml</file>
|
||||
<file>ui/modules/Common/Form/Placements/FormEmptyLine.qml</file>
|
||||
<file>ui/modules/Common/Form/Placements/FormGroup.qml</file>
|
||||
<file>ui/modules/Common/Form/Placements/FormHGroup.qml</file>
|
||||
|
|
@ -338,6 +339,9 @@
|
|||
<file>ui/modules/Linphone/Contact/ContactMessageCounter.qml</file>
|
||||
<file>ui/modules/Linphone/Contact/Contact.qml</file>
|
||||
<file>ui/modules/Linphone/Dialog/OnlineInstallerDialog.qml</file>
|
||||
<file>ui/modules/Linphone/History/History.qml</file>
|
||||
<file>ui/modules/Linphone/History/History.js</file>
|
||||
<file>ui/modules/Linphone/History/Event.qml</file>
|
||||
<file>ui/modules/Linphone/Menus/SipAddressesMenu.qml</file>
|
||||
<file>ui/modules/Linphone/Misc/MessageCounter.qml</file>
|
||||
<file>ui/modules/Linphone/Notifications/NotificationBasic.qml</file>
|
||||
|
|
@ -365,6 +369,7 @@
|
|||
<file>ui/modules/Linphone/Styles/Contact/ContactMessageCounterStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Contact/ContactStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Dialog/OnlineInstallerDialogStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/History/HistoryStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Menus/SipAddressesMenuStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Misc/MessageCounterStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Notifications/NotificationBasicStyle.qml</file>
|
||||
|
|
@ -428,10 +433,13 @@
|
|||
<file>ui/views/App/Main/Dialogs/ManageAccount.js</file>
|
||||
<file>ui/views/App/Main/Dialogs/ManageAccounts.qml</file>
|
||||
<file>ui/views/App/Main/Home.qml</file>
|
||||
<file>ui/views/App/Main/HistoryView.qml</file>
|
||||
<file>ui/views/App/Main/HistoryView.js</file>
|
||||
<file>ui/views/App/Main/InviteFriends.qml</file>
|
||||
<file>ui/views/App/Main/MainWindow.js</file>
|
||||
<file>ui/views/App/Main/MainWindowMenuBar.qml</file>
|
||||
<file>ui/views/App/Main/MainWindow.qml</file>
|
||||
<file>ui/views/App/Main/MainWindowTopMenuBar.qml</file>
|
||||
<file>ui/views/App/Settings/Dialogs/SettingsSipAccountsEdit.js</file>
|
||||
<file>ui/views/App/Settings/Dialogs/SettingsSipAccountsEdit.qml</file>
|
||||
<file>ui/views/App/Settings/Dialogs/SettingsVideoPreview.qml</file>
|
||||
|
|
@ -469,6 +477,7 @@
|
|||
<file>ui/views/App/Styles/Main/Dialogs/ManageAccountsStyle.qml</file>
|
||||
<file>ui/views/App/Styles/Main/HomeStyle.qml</file>
|
||||
<file>ui/views/App/Styles/Main/InviteFriendsStyle.qml</file>
|
||||
<file>ui/views/App/Styles/Main/HistoryViewStyle.qml</file>
|
||||
<file>ui/views/App/Styles/Main/MainWindowStyle.qml</file>
|
||||
<file>ui/views/App/Styles/qmldir</file>
|
||||
<file>ui/views/App/Styles/Settings/Dialogs/SettingsSipAccountsEditStyle.qml</file>
|
||||
|
|
@ -477,7 +486,6 @@
|
|||
<file>ui/views/App/Styles/Settings/SettingsAudioStyle.qml</file>
|
||||
<file>ui/views/App/Styles/Settings/SettingsWindowStyle.qml</file>
|
||||
<file>assets/images/linphone_logo.svg</file>
|
||||
<file>ui/views/App/Main/MainWindowTopMenuBar.qml</file>
|
||||
<file>ui/dev-modules/Colors/Colors.qml</file>
|
||||
<file>ui/dev-modules/Units/Units.qml</file>
|
||||
<file>assets/icon.ico</file>
|
||||
|
|
|
|||
|
|
@ -520,6 +520,7 @@ void App::registerTypes () {
|
|||
registerType<ContactsListProxyModel>("ContactsListProxyModel");
|
||||
registerType<FileDownloader>("FileDownloader");
|
||||
registerType<FileExtractor>("FileExtractor");
|
||||
registerType<HistoryProxyModel>("HistoryProxyModel");
|
||||
registerType<SipAddressesProxyModel>("SipAddressesProxyModel");
|
||||
registerType<SoundPlayer>("SoundPlayer");
|
||||
registerType<TelephoneNumbersModel>("TelephoneNumbersModel");
|
||||
|
|
@ -535,6 +536,7 @@ void App::registerTypes () {
|
|||
registerUncreatableType<ChatModel>("ChatModel");
|
||||
registerUncreatableType<ConferenceHelperModel::ConferenceAddModel>("ConferenceAddModel");
|
||||
registerUncreatableType<ContactModel>("ContactModel");
|
||||
registerUncreatableType<HistoryModel>("HistoryModel");
|
||||
registerUncreatableType<SipAddressObserver>("SipAddressObserver");
|
||||
registerUncreatableType<VcardModel>("VcardModel");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "core/CoreManager.hpp"
|
||||
#include "file/FileDownloader.hpp"
|
||||
#include "file/FileExtractor.hpp"
|
||||
#include "history/HistoryProxyModel.hpp"
|
||||
#include "notifier/Notifier.hpp"
|
||||
#include "presence/OwnPresenceModel.hpp"
|
||||
#include "settings/AccountSettingsModel.hpp"
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ void CallsListModel::launchAudioCall (const QString &sipAddress, const QHash<QSt
|
|||
iterator.next();
|
||||
params->addCustomHeader(Utils::appStringToCoreString(iterator.key()), Utils::appStringToCoreString(iterator.value()));
|
||||
}
|
||||
|
||||
params->setProxyConfig(core->getDefaultProxyConfig());
|
||||
CallModel::setRecordFile(params, Utils::coreStringToAppString(address->getUsername()));
|
||||
core->inviteAddressWithParams(address, params);
|
||||
}
|
||||
|
|
@ -130,7 +130,7 @@ void CallsListModel::launchVideoCall (const QString &sipAddress) const {
|
|||
|
||||
shared_ptr<linphone::CallParams> params = core->createCallParams(nullptr);
|
||||
params->enableVideo(true);
|
||||
|
||||
params->setProxyConfig(core->getDefaultProxyConfig());
|
||||
CallModel::setRecordFile(params, Utils::coreStringToAppString(address->getUsername()));
|
||||
core->inviteAddressWithParams(address, params);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "components/chat/ChatModel.hpp"
|
||||
#include "components/contact/VcardModel.hpp"
|
||||
#include "components/contacts/ContactsListModel.hpp"
|
||||
#include "components/history/HistoryModel.hpp"
|
||||
#include "components/settings/AccountSettingsModel.hpp"
|
||||
#include "components/settings/SettingsModel.hpp"
|
||||
#include "components/sip-addresses/SipAddressesModel.hpp"
|
||||
|
|
@ -145,6 +146,13 @@ bool CoreManager::chatModelExists (const QString &peerAddress, const QString &lo
|
|||
return mChatModels.contains({ peerAddress, localAddress });
|
||||
}
|
||||
|
||||
HistoryModel* CoreManager::getHistoryModel(){
|
||||
if(!mHistoryModel){
|
||||
mHistoryModel = new HistoryModel(this);
|
||||
emit historyModelCreated(mHistoryModel);
|
||||
}
|
||||
return mHistoryModel;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void CoreManager::init (QObject *parent, const QString &configPath) {
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ class ChatModel;
|
|||
class ContactsListModel;
|
||||
class CoreHandlers;
|
||||
class EventCountNotifier;
|
||||
class HistoryModel;
|
||||
class SettingsModel;
|
||||
class SipAddressesModel;
|
||||
class VcardModel;
|
||||
|
|
@ -44,9 +45,9 @@ class VcardModel;
|
|||
class CoreManager : public QObject {
|
||||
Q_OBJECT;
|
||||
|
||||
Q_PROPERTY(QString version READ getVersion CONSTANT);
|
||||
Q_PROPERTY(QString downloadUrl READ getDownloadUrl CONSTANT);
|
||||
Q_PROPERTY(int eventCount READ getEventCount NOTIFY eventCountChanged);
|
||||
Q_PROPERTY(QString version READ getVersion CONSTANT)
|
||||
Q_PROPERTY(QString downloadUrl READ getDownloadUrl CONSTANT)
|
||||
Q_PROPERTY(int eventCount READ getEventCount NOTIFY eventCountChanged)
|
||||
|
||||
public:
|
||||
bool started () const {
|
||||
|
|
@ -65,6 +66,8 @@ public:
|
|||
|
||||
std::shared_ptr<ChatModel> getChatModel (const QString &peerAddress, const QString &localAddress);
|
||||
bool chatModelExists (const QString &sipAddress, const QString &localAddress);
|
||||
|
||||
HistoryModel* getHistoryModel();
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Video render lock.
|
||||
|
|
@ -138,6 +141,7 @@ signals:
|
|||
void coreStarted ();
|
||||
|
||||
void chatModelCreated (const std::shared_ptr<ChatModel> &chatModel);
|
||||
void historyModelCreated (HistoryModel *historyModel);
|
||||
|
||||
void logsUploaded (const QString &url);
|
||||
|
||||
|
|
@ -177,6 +181,7 @@ private:
|
|||
EventCountNotifier *mEventCountNotifier = nullptr;
|
||||
|
||||
QHash<QPair<QString, QString>, std::weak_ptr<ChatModel>> mChatModels;
|
||||
HistoryModel * mHistoryModel = nullptr;
|
||||
|
||||
QTimer *mCbsTimer = nullptr;
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "components/chat/ChatModel.hpp"
|
||||
#include "components/core/CoreHandlers.hpp"
|
||||
#include "components/core/CoreManager.hpp"
|
||||
#include "components/history/HistoryModel.hpp"
|
||||
#include "components/settings/SettingsModel.hpp"
|
||||
#include "utils/Utils.hpp"
|
||||
|
||||
|
|
@ -40,6 +41,10 @@ AbstractEventCountNotifier::AbstractEventCountNotifier (QObject *parent) : QObje
|
|||
coreManager, &CoreManager::chatModelCreated,
|
||||
this, &AbstractEventCountNotifier::handleChatModelCreated
|
||||
);
|
||||
QObject::connect(
|
||||
coreManager, &CoreManager::historyModelCreated,
|
||||
this, &AbstractEventCountNotifier::handleHistoryModelCreated
|
||||
);
|
||||
QObject::connect(
|
||||
coreManager->getHandlers().get(), &CoreHandlers::messageReceived,
|
||||
this, &AbstractEventCountNotifier::updateUnreadMessageCount
|
||||
|
|
@ -98,11 +103,26 @@ void AbstractEventCountNotifier::handleChatModelCreated (const shared_ptr<ChatMo
|
|||
);
|
||||
QObject::connect(
|
||||
chatModelPtr, &ChatModel::focused,
|
||||
this, [this, chatModelPtr]() { handleChatModelFocused(chatModelPtr); }
|
||||
this, [this, chatModelPtr]() { handleResetMissedCalls(chatModelPtr); }
|
||||
);
|
||||
QObject::connect(
|
||||
chatModelPtr, &ChatModel::messageCountReset,
|
||||
this, [this, chatModelPtr]() { handleResetMissedCalls(chatModelPtr); }
|
||||
);
|
||||
}
|
||||
|
||||
void AbstractEventCountNotifier::handleChatModelFocused (ChatModel *chatModel) {
|
||||
void AbstractEventCountNotifier::handleHistoryModelCreated (HistoryModel *historyModel) {
|
||||
QObject::connect(historyModel, &HistoryModel::callCountReset
|
||||
, this, &AbstractEventCountNotifier::handleResetAllMissedCalls);
|
||||
}
|
||||
|
||||
void AbstractEventCountNotifier::handleResetAllMissedCalls () {
|
||||
mMissedCalls.clear();
|
||||
internalnotifyEventCount();
|
||||
}
|
||||
|
||||
|
||||
void AbstractEventCountNotifier::handleResetMissedCalls (ChatModel *chatModel) {
|
||||
auto it = mMissedCalls.find({ Utils::cleanSipAddress(chatModel->getPeerAddress()), Utils::cleanSipAddress(chatModel->getLocalAddress()) });
|
||||
if (it != mMissedCalls.cend()) {
|
||||
mMissedCalls.erase(it);
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ namespace linphone {
|
|||
|
||||
class CallModel;
|
||||
class ChatModel;
|
||||
class HistoryModel;
|
||||
|
||||
class AbstractEventCountNotifier : public QObject {
|
||||
Q_OBJECT;
|
||||
|
|
@ -68,7 +69,11 @@ private:
|
|||
|
||||
void handleChatModelCreated (const std::shared_ptr<ChatModel> &chatModel);
|
||||
|
||||
void handleChatModelFocused (ChatModel *chatModel);
|
||||
void handleHistoryModelCreated (HistoryModel *historyModel);
|
||||
|
||||
|
||||
void handleResetAllMissedCalls ();
|
||||
void handleResetMissedCalls (ChatModel *chatModel);
|
||||
void handleCallMissed (CallModel *callModel);
|
||||
|
||||
QHash<ConferenceId, int> mMissedCalls;
|
||||
|
|
|
|||
256
linphone-app/src/components/history/HistoryModel.cpp
Normal file
256
linphone-app/src/components/history/HistoryModel.cpp
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2020 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDesktopServices>
|
||||
#include <QElapsedTimer>
|
||||
#include <QFileInfo>
|
||||
#include <QMimeDatabase>
|
||||
#include <QTimer>
|
||||
#include <QUuid>
|
||||
#include <QMessageBox>
|
||||
#include <QUrlQuery>
|
||||
#include <QImageReader>
|
||||
|
||||
#include "app/App.hpp"
|
||||
#include "app/paths/Paths.hpp"
|
||||
#include "app/providers/ThumbnailProvider.hpp"
|
||||
#include "components/core/CoreHandlers.hpp"
|
||||
#include "components/core/CoreManager.hpp"
|
||||
#include "components/notifier/Notifier.hpp"
|
||||
#include "components/settings/SettingsModel.hpp"
|
||||
#include "utils/QExifImageHeader.hpp"
|
||||
#include "utils/Utils.hpp"
|
||||
|
||||
#include "HistoryModel.hpp"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
using namespace std;
|
||||
|
||||
static inline void fillCallStartEntry (QVariantMap &dest, const shared_ptr<linphone::CallLog> &callLog) {
|
||||
dest["type"] = HistoryModel::CallEntry;
|
||||
dest["timestamp"] = QDateTime::fromMSecsSinceEpoch(callLog->getStartDate() * 1000);
|
||||
dest["isOutgoing"] = callLog->getDir() == linphone::Call::Dir::Outgoing;
|
||||
dest["status"] = static_cast<HistoryModel::CallStatus>(callLog->getStatus());
|
||||
dest["isStart"] = true;
|
||||
dest["sipAddress"] = Utils::coreStringToAppString(callLog->getRemoteAddress()->asString());
|
||||
}
|
||||
|
||||
static inline void fillCallEndEntry (QVariantMap &dest, const shared_ptr<linphone::CallLog> &callLog) {
|
||||
dest["type"] = HistoryModel::CallEntry;
|
||||
dest["timestamp"] = QDateTime::fromMSecsSinceEpoch((callLog->getStartDate() + callLog->getDuration()) * 1000);
|
||||
dest["isOutgoing"] = callLog->getDir() == linphone::Call::Dir::Outgoing;
|
||||
dest["status"] = static_cast<HistoryModel::CallStatus>(callLog->getStatus());
|
||||
dest["isStart"] = false;
|
||||
dest["sipAddress"] = Utils::coreStringToAppString(callLog->getRemoteAddress()->asString());
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
HistoryModel::HistoryModel (QObject *parent) :QAbstractListModel(parent){
|
||||
CoreManager *coreManager = CoreManager::getInstance();
|
||||
|
||||
mCoreHandlers = coreManager->getHandlers();
|
||||
|
||||
setSipAddresses();
|
||||
CoreHandlers *coreHandlers = mCoreHandlers.get();
|
||||
QObject::connect(coreHandlers, &CoreHandlers::callStateChanged, this, &HistoryModel::handleCallStateChanged);
|
||||
|
||||
}
|
||||
|
||||
HistoryModel::~HistoryModel () {
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> HistoryModel::roleNames () const {
|
||||
QHash<int, QByteArray> roles;
|
||||
roles[Roles::HistoryEntry] = "$historyEntry";
|
||||
roles[Roles::SectionDate] = "$sectionDate";
|
||||
return roles;
|
||||
}
|
||||
|
||||
int HistoryModel::rowCount (const QModelIndex &) const {
|
||||
return mEntries.count();
|
||||
}
|
||||
|
||||
QVariant HistoryModel::data (const QModelIndex &index, int role) const {
|
||||
int row = index.row();
|
||||
|
||||
if (!index.isValid() || row < 0 || row >= mEntries.count())
|
||||
return QVariant();
|
||||
|
||||
switch (role) {
|
||||
case Roles::HistoryEntry: {
|
||||
auto &data = mEntries[row].first;
|
||||
return QVariant::fromValue(data);
|
||||
}
|
||||
case Roles::SectionDate:
|
||||
return QVariant::fromValue(mEntries[row].first["timestamp"].toDate());
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool HistoryModel::removeRow (int row, const QModelIndex &) {
|
||||
return removeRows(row, 1);
|
||||
}
|
||||
|
||||
bool HistoryModel::removeRows (int row, int count, const QModelIndex &parent) {
|
||||
int limit = row + count - 1;
|
||||
|
||||
if (row < 0 || count < 0 || limit >= mEntries.count())
|
||||
return false;
|
||||
|
||||
beginRemoveRows(parent, row, limit);
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
removeEntry(mEntries[row]);
|
||||
mEntries.removeAt(row);
|
||||
}
|
||||
|
||||
endRemoveRows();
|
||||
|
||||
if (mEntries.count() == 0)
|
||||
emit allEntriesRemoved();
|
||||
else if (limit == mEntries.count())
|
||||
emit lastEntryRemoved();
|
||||
emit focused();// Removing rows is like having focus. Don't wait asynchronous events.
|
||||
return true;
|
||||
}
|
||||
|
||||
void HistoryModel::setSipAddresses () {
|
||||
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
|
||||
mEntries.clear();
|
||||
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
|
||||
// Get calls.
|
||||
for (auto &callLog : core->getCallLogs())
|
||||
insertCall(callLog);
|
||||
|
||||
qInfo() << QStringLiteral("HistoryModel loaded in %3 milliseconds.").arg(timer.elapsed());
|
||||
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void HistoryModel::removeEntry (int id) {
|
||||
qInfo() << QStringLiteral("Removing call entry: %1.").arg(id);
|
||||
|
||||
if (!removeRow(id))
|
||||
qWarning() << QStringLiteral("Unable to remove call entry: %1").arg(id);
|
||||
}
|
||||
|
||||
void HistoryModel::removeAllEntries () {
|
||||
qInfo() << QStringLiteral("Removing all call entries.");
|
||||
|
||||
beginResetModel();
|
||||
|
||||
for (auto &entry : mEntries)
|
||||
removeEntry(entry);
|
||||
|
||||
mEntries.clear();
|
||||
|
||||
endResetModel();
|
||||
|
||||
emit allEntriesRemoved();
|
||||
emit focused();// Removing all entries is like having focus. Don't wait asynchronous events.
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void HistoryModel::removeEntry (HistoryEntryData &entry) {
|
||||
int type = entry.first["type"].toInt();
|
||||
|
||||
switch (type) {
|
||||
|
||||
case HistoryModel::CallEntry: {
|
||||
if (entry.first["status"].toInt() == CallStatusSuccess) {
|
||||
// WARNING: Unable to remove symmetric call here. (start/end)
|
||||
// We are between `beginRemoveRows` and `endRemoveRows`.
|
||||
// A solution is to schedule a `removeEntry` call in the Qt main loop.
|
||||
shared_ptr<void> linphonePtr = entry.second;
|
||||
QTimer::singleShot(0, this, [this, linphonePtr]() {
|
||||
auto it = find_if(mEntries.begin(), mEntries.end(), [linphonePtr](const HistoryEntryData &entry) {
|
||||
return entry.second == linphonePtr;
|
||||
});
|
||||
|
||||
if (it != mEntries.end())
|
||||
removeEntry(int(distance(mEntries.begin(), it)));
|
||||
});
|
||||
}
|
||||
|
||||
CoreManager::getInstance()->getCore()->removeCallLog(static_pointer_cast<linphone::CallLog>(entry.second));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
qWarning() << QStringLiteral("Unknown history entry type: %1.").arg(type);
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryModel::insertCall (const shared_ptr<linphone::CallLog> &callLog) {
|
||||
linphone::Call::Status status = callLog->getStatus();
|
||||
|
||||
auto insertEntry = [this](
|
||||
const HistoryEntryData &entry,
|
||||
const QList<HistoryEntryData>::iterator *start = nullptr
|
||||
) {
|
||||
auto it = lower_bound(start ? *start : mEntries.begin(), mEntries.end(), entry, [](const HistoryEntryData &a, const HistoryEntryData &b) {
|
||||
return a.first["timestamp"] < b.first["timestamp"];
|
||||
});
|
||||
|
||||
int row = int(distance(mEntries.begin(), it));
|
||||
|
||||
beginInsertRows(QModelIndex(), row, row);
|
||||
it = mEntries.insert(it, entry);
|
||||
endInsertRows();
|
||||
|
||||
return it;
|
||||
};
|
||||
|
||||
// Add start call.
|
||||
QVariantMap start;
|
||||
fillCallStartEntry(start, callLog);
|
||||
auto it = insertEntry(qMakePair(start, static_pointer_cast<void>(callLog)));
|
||||
|
||||
if (status == linphone::Call::Status::Success) {
|
||||
QVariantMap end;
|
||||
fillCallEndEntry(end, callLog);
|
||||
insertEntry(qMakePair(end, static_pointer_cast<void>(callLog)), &it);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void HistoryModel::resetMessageCount () {
|
||||
emit callCountReset();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void HistoryModel::handleCallStateChanged (const shared_ptr<linphone::Call> &call, linphone::Call::State state) {
|
||||
if (state == linphone::Call::State::End || state == linphone::Call::State::Error)
|
||||
insertCall(call->getCallLog());
|
||||
}
|
||||
|
||||
96
linphone-app/src/components/history/HistoryModel.hpp
Normal file
96
linphone-app/src/components/history/HistoryModel.hpp
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2020 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HISTORY_MODEL_H_
|
||||
#define HISTORY_MODEL_H_
|
||||
|
||||
#include <linphone++/linphone.hh>
|
||||
#include <QAbstractListModel>
|
||||
|
||||
// =============================================================================
|
||||
// Fetch all N messages of the History.
|
||||
// =============================================================================
|
||||
|
||||
class CoreHandlers;
|
||||
|
||||
class HistoryModel : public QAbstractListModel {
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Roles {
|
||||
HistoryEntry = Qt::DisplayRole,
|
||||
SectionDate
|
||||
};
|
||||
|
||||
enum EntryType {
|
||||
GenericEntry,
|
||||
CallEntry
|
||||
};
|
||||
Q_ENUM(EntryType)
|
||||
|
||||
enum CallStatus {
|
||||
CallStatusDeclined = int(linphone::Call::Status::Declined),
|
||||
CallStatusMissed = int(linphone::Call::Status::Missed),
|
||||
CallStatusSuccess = int(linphone::Call::Status::Success),
|
||||
CallStatusAborted = int(linphone::Call::Status::Aborted),
|
||||
CallStatusEarlyAborted = int(linphone::Call::Status::EarlyAborted),
|
||||
CallStatusAcceptedElsewhere = int(linphone::Call::Status::AcceptedElsewhere),
|
||||
CallStatusDeclinedElsewhere = int(linphone::Call::Status::DeclinedElsewhere)
|
||||
};
|
||||
Q_ENUM(CallStatus)
|
||||
|
||||
HistoryModel (QObject *parent = Q_NULLPTR);
|
||||
virtual ~HistoryModel ();
|
||||
|
||||
int rowCount (const QModelIndex &index = QModelIndex()) const override;
|
||||
|
||||
QHash<int, QByteArray> roleNames () const override;
|
||||
QVariant data (const QModelIndex &index, int role) const override;
|
||||
|
||||
bool removeRow (int row, const QModelIndex &parent = QModelIndex());
|
||||
bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||
|
||||
void removeEntry (int id);
|
||||
void removeAllEntries ();
|
||||
|
||||
void resetMessageCount ();
|
||||
|
||||
signals:
|
||||
void allEntriesRemoved ();
|
||||
void lastEntryRemoved ();
|
||||
|
||||
void focused ();
|
||||
void callCountReset();
|
||||
|
||||
private:
|
||||
typedef QPair<QVariantMap, std::shared_ptr<void>> HistoryEntryData;
|
||||
|
||||
void setSipAddresses ();
|
||||
void removeEntry (HistoryEntryData &entry);
|
||||
void insertCall (const std::shared_ptr<linphone::CallLog> &callLog);
|
||||
void handleCallStateChanged (const std::shared_ptr<linphone::Call> &call, linphone::Call::State state);
|
||||
|
||||
mutable QList<HistoryEntryData> mEntries;
|
||||
|
||||
std::shared_ptr<CoreHandlers> mCoreHandlers;
|
||||
};
|
||||
|
||||
#endif // HISTORY_MODEL_H_
|
||||
161
linphone-app/src/components/history/HistoryProxyModel.cpp
Normal file
161
linphone-app/src/components/history/HistoryProxyModel.cpp
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2020 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QQuickWindow>
|
||||
|
||||
#include "app/App.hpp"
|
||||
#include "components/core/CoreManager.hpp"
|
||||
|
||||
#include "HistoryProxyModel.hpp"
|
||||
#include "components/sip-addresses/SipAddressesModel.hpp"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Fetch the L last filtered history entries.
|
||||
class HistoryProxyModel::HistoryModelFilter : public QSortFilterProxyModel {
|
||||
public:
|
||||
HistoryModelFilter (QObject *parent) : QSortFilterProxyModel(parent) { }
|
||||
|
||||
HistoryModel::EntryType getEntryTypeFilter () {
|
||||
return mEntryTypeFilter;
|
||||
}
|
||||
|
||||
void setEntryTypeFilter (HistoryModel::EntryType type) {
|
||||
mEntryTypeFilter = type;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow (int sourceRow, const QModelIndex &) const override {
|
||||
if (mEntryTypeFilter == HistoryModel::EntryType::GenericEntry)
|
||||
return true;
|
||||
|
||||
QModelIndex index = sourceModel()->index(sourceRow, 0, QModelIndex());
|
||||
const QVariantMap data = index.data().toMap();
|
||||
|
||||
return data["type"].toInt() == mEntryTypeFilter;
|
||||
}
|
||||
|
||||
private:
|
||||
HistoryModel::EntryType mEntryTypeFilter = HistoryModel::EntryType::GenericEntry;
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
|
||||
HistoryProxyModel::HistoryProxyModel (QObject *parent) : QSortFilterProxyModel(parent) {
|
||||
|
||||
setSourceModel(new HistoryModelFilter(this));
|
||||
reload();
|
||||
|
||||
App *app = App::getInstance();
|
||||
QObject::connect(app->getMainWindow(), &QWindow::activeChanged, this, [this]() {
|
||||
handleIsActiveChanged(App::getInstance()->getMainWindow());
|
||||
});
|
||||
|
||||
QQuickWindow *callsWindow = app->getCallsWindow();
|
||||
if (callsWindow)
|
||||
QObject::connect(callsWindow, &QWindow::activeChanged, this, [this, callsWindow]() {
|
||||
handleIsActiveChanged(callsWindow);
|
||||
});
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void HistoryProxyModel::removeAllEntries(){
|
||||
auto model = CoreManager::getInstance()->getHistoryModel();
|
||||
if (!model)
|
||||
return;
|
||||
model->removeAllEntries();
|
||||
}
|
||||
void HistoryProxyModel::removeEntry (int id){
|
||||
auto model = CoreManager::getInstance()->getHistoryModel();
|
||||
if (!model)
|
||||
return;
|
||||
QModelIndex sourceIndex = mapToSource(index(id, 0));
|
||||
model->removeEntry(static_cast<HistoryModelFilter *>(sourceModel())->mapToSource(sourceIndex).row() );
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void HistoryProxyModel::loadMoreEntries () {
|
||||
int count = rowCount();
|
||||
int parentCount = sourceModel()->rowCount();
|
||||
|
||||
if (count < parentCount) {
|
||||
// Do not increase `mMaxDisplayedEntries` if it's not necessary...
|
||||
// Limit qml calls.
|
||||
if (count == mMaxDisplayedEntries)
|
||||
mMaxDisplayedEntries += EntriesChunkSize;
|
||||
|
||||
invalidateFilter();
|
||||
|
||||
count = rowCount() - count;
|
||||
if (count > 0)
|
||||
emit moreEntriesLoaded(count);
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryProxyModel::setEntryTypeFilter (HistoryModel::EntryType type) {
|
||||
HistoryModelFilter *HistoryModelFilter = static_cast<HistoryProxyModel::HistoryModelFilter *>(sourceModel());
|
||||
|
||||
if (HistoryModelFilter->getEntryTypeFilter() != type) {
|
||||
HistoryModelFilter->setEntryTypeFilter(type);
|
||||
emit entryTypeFilterChanged(type);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
bool HistoryProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex &) const {
|
||||
return sourceModel()->rowCount() - sourceRow <= mMaxDisplayedEntries;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void HistoryProxyModel::reload () {
|
||||
mMaxDisplayedEntries = EntriesChunkSize;
|
||||
static_cast<HistoryModelFilter *>(sourceModel())->setSourceModel(CoreManager::getInstance()->getHistoryModel());
|
||||
}
|
||||
void HistoryProxyModel::resetMessageCount(){
|
||||
auto model = CoreManager::getInstance()->getHistoryModel();
|
||||
if( model){
|
||||
model->resetMessageCount();
|
||||
}
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
static inline QWindow *getParentWindow (QObject *object) {
|
||||
App *app = App::getInstance();
|
||||
const QWindow *mainWindow = app->getMainWindow();
|
||||
const QWindow *callsWindow = app->getCallsWindow();
|
||||
for (QObject *parent = object->parent(); parent; parent = parent->parent())
|
||||
if (parent == mainWindow || parent == callsWindow)
|
||||
return static_cast<QWindow *>(parent);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void HistoryProxyModel::handleIsActiveChanged (QWindow *window) {
|
||||
auto model = CoreManager::getInstance()->getHistoryModel();
|
||||
if (model && window->isActive() && getParentWindow(this) == window) {
|
||||
model->focused();
|
||||
model->resetMessageCount();
|
||||
}
|
||||
}
|
||||
68
linphone-app/src/components/history/HistoryProxyModel.hpp
Normal file
68
linphone-app/src/components/history/HistoryProxyModel.hpp
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2020 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HISTORY_PROXY_MODEL_H_
|
||||
#define HISTORY_PROXY_MODEL_H_
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
#include "HistoryModel.hpp"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
class QWindow;
|
||||
|
||||
class HistoryProxyModel : public QSortFilterProxyModel {
|
||||
class HistoryModelFilter;
|
||||
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
HistoryProxyModel (QObject *parent = Q_NULLPTR);
|
||||
|
||||
Q_INVOKABLE void loadMoreEntries ();
|
||||
Q_INVOKABLE void setEntryTypeFilter (HistoryModel::EntryType type = HistoryModel::EntryType::CallEntry);
|
||||
Q_INVOKABLE void removeEntry (int id);
|
||||
|
||||
Q_INVOKABLE void removeAllEntries ();
|
||||
|
||||
Q_INVOKABLE void resetMessageCount();
|
||||
|
||||
signals:
|
||||
|
||||
void moreEntriesLoaded (int n);
|
||||
|
||||
void entryTypeFilterChanged (HistoryModel::EntryType type);
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
|
||||
private:
|
||||
|
||||
void reload ();
|
||||
|
||||
void handleIsActiveChanged (QWindow *window);
|
||||
|
||||
int mMaxDisplayedEntries = EntriesChunkSize;
|
||||
|
||||
static constexpr int EntriesChunkSize = 50;
|
||||
};
|
||||
|
||||
#endif // HISTORY_PROXY_MODEL_H_
|
||||
|
|
@ -30,6 +30,7 @@
|
|||
#include "components/contacts/ContactsListModel.hpp"
|
||||
#include "components/core/CoreHandlers.hpp"
|
||||
#include "components/core/CoreManager.hpp"
|
||||
#include "components/history/HistoryModel.hpp"
|
||||
#include "components/settings/AccountSettingsModel.hpp"
|
||||
#include "utils/LinphoneUtils.hpp"
|
||||
#include "utils/Utils.hpp"
|
||||
|
|
@ -59,6 +60,7 @@ SipAddressesModel::SipAddressesModel (QObject *parent) : QAbstractListModel(pare
|
|||
mCoreHandlers = coreManager->getHandlers();
|
||||
|
||||
QObject::connect(coreManager, &CoreManager::chatModelCreated, this, &SipAddressesModel::handleChatModelCreated);
|
||||
QObject::connect(coreManager, &CoreManager::historyModelCreated, this, &SipAddressesModel::handleHistoryModelCreated);
|
||||
|
||||
ContactsListModel *contacts = CoreManager::getInstance()->getContactsListModel();
|
||||
QObject::connect(contacts, &ContactsListModel::contactAdded, this, &SipAddressesModel::handleContactAdded);
|
||||
|
|
@ -261,6 +263,11 @@ void SipAddressesModel::handleChatModelCreated (const shared_ptr<ChatModel> &cha
|
|||
QObject::connect(ptr, &ChatModel::messageSent, this, &SipAddressesModel::handleMessageSent);
|
||||
}
|
||||
|
||||
void SipAddressesModel::handleHistoryModelCreated (HistoryModel *historyModel) {
|
||||
QObject::connect(historyModel, &HistoryModel::callCountReset, this, [this] {
|
||||
handleAllCallCountReset();
|
||||
});
|
||||
}
|
||||
void SipAddressesModel::handleContactAdded (ContactModel *contact) {
|
||||
for (const auto &sipAddress : contact->getVcardModel()->getSipAddresses())
|
||||
addOrUpdateSipAddress(sipAddress.toString(), contact);
|
||||
|
|
@ -385,7 +392,16 @@ void SipAddressesModel::handleLastEntryRemoved (ChatModel *chatModel) {
|
|||
it2->timestamp = map["timestamp"].toDateTime();
|
||||
emit dataChanged(index(row, 0), index(row, 0));
|
||||
}
|
||||
|
||||
void SipAddressesModel::handleAllCallCountReset () {
|
||||
for( auto peer = mPeerAddressToSipAddressEntry.begin() ; peer != mPeerAddressToSipAddressEntry.end() ; ++peer){
|
||||
for( auto local = peer->localAddressToConferenceEntry.begin() ; local != peer->localAddressToConferenceEntry.end() ; ++local){
|
||||
local->missedCallCount = 0;
|
||||
updateObservers(peer.key(), local.key(), local->unreadMessageCount, local->missedCallCount);
|
||||
}
|
||||
int row = mRefs.indexOf(&(*peer));
|
||||
emit dataChanged(index(row, 0), index(row, 0));
|
||||
}
|
||||
}
|
||||
void SipAddressesModel::handleMessageCountReset (ChatModel *chatModel) {
|
||||
const QString &peerAddress = Utils::cleanSipAddress(chatModel->getPeerAddress());
|
||||
auto it = mPeerAddressToSipAddressEntry.find(peerAddress);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ class QUrl;
|
|||
|
||||
class ChatModel;
|
||||
class CoreHandlers;
|
||||
class HistoryModel;
|
||||
|
||||
class SipAddressesModel : public QAbstractListModel {
|
||||
Q_OBJECT;
|
||||
|
|
@ -82,6 +83,9 @@ public:
|
|||
// ---------------------------------------------------------------------------
|
||||
signals:
|
||||
void sipAddressReset();// The model has been reset
|
||||
|
||||
public slots:
|
||||
void handleAllCallCountReset ();
|
||||
|
||||
private:
|
||||
bool removeRow (int row, const QModelIndex &parent = QModelIndex());
|
||||
|
|
@ -90,6 +94,7 @@ private:
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
void handleChatModelCreated (const std::shared_ptr<ChatModel> &chatModel);
|
||||
void handleHistoryModelCreated (HistoryModel *historyModel) ;
|
||||
|
||||
void handleContactAdded (ContactModel *contact);
|
||||
void handleContactRemoved (const ContactModel *contact);
|
||||
|
|
@ -103,6 +108,7 @@ private:
|
|||
|
||||
void handleAllEntriesRemoved (ChatModel *chatModel);
|
||||
void handleLastEntryRemoved (ChatModel *chatModel);
|
||||
|
||||
void handleMessageCountReset (ChatModel *chatModel);
|
||||
|
||||
void handleMessageSent (const std::shared_ptr<linphone::ChatMessage> &message);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include "TimelineModel.hpp"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
// =============================================================================
|
||||
|
||||
|
|
@ -72,8 +74,8 @@ QVariant TimelineModel::data (const QModelIndex &index, int role) const {
|
|||
}
|
||||
|
||||
bool TimelineModel::filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const {
|
||||
const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
|
||||
return getLocalToConferenceEntry(index.data().toMap())->contains(getCleanedLocalAddress());
|
||||
const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
|
||||
return getLocalToConferenceEntry(index.data().toMap())->contains(getCleanedLocalAddress());
|
||||
}
|
||||
|
||||
bool TimelineModel::lessThan (const QModelIndex &left, const QModelIndex &right) const {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
|
||||
import Common 1.0
|
||||
import Common.Styles 1.0
|
||||
|
||||
// =============================================================================
|
||||
|
|
@ -76,15 +77,10 @@ Item {
|
|||
|
||||
hoverEnabled: true
|
||||
|
||||
MouseArea
|
||||
{
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
onPressed: mouse.accepted = false
|
||||
hoverEnabled: true
|
||||
cursorShape: containsMouse
|
||||
? Qt.PointingHandCursor
|
||||
: Qt.ArrowCursor
|
||||
}
|
||||
|
||||
height: parent.height
|
||||
|
|
|
|||
|
|
@ -101,7 +101,6 @@ TextField {
|
|||
|
||||
anchors.fill: parent
|
||||
enabled: !textField.readOnly
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: fileDialog.open()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
|
||||
import Common 1.0
|
||||
import Common.Styles 1.0
|
||||
|
||||
// =============================================================================
|
||||
|
|
@ -32,14 +33,9 @@ Button {
|
|||
rightPadding: SmallButtonStyle.rightPadding
|
||||
}
|
||||
hoverEnabled: true
|
||||
MouseArea
|
||||
{
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
onPressed: mouse.accepted = false
|
||||
hoverEnabled: true
|
||||
cursorShape: containsMouse
|
||||
? Qt.PointingHandCursor
|
||||
: Qt.ArrowCursor
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ Rectangle {
|
|||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.ArrowCursor
|
||||
visible: field.readOnly
|
||||
|
||||
onWheel: wheel.accepted = true
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ Controls.TextField {
|
|||
MouseArea {
|
||||
anchors.right: parent.right
|
||||
height: parent.height
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.ArrowCursor
|
||||
implicitWidth: tools ? tools.width : 0
|
||||
|
||||
Rectangle {
|
||||
|
|
|
|||
11
linphone-app/ui/modules/Common/Form/MouseArea.qml
Normal file
11
linphone-app/ui/modules/Common/Form/MouseArea.qml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import QtQuick 2.7 as Quick
|
||||
|
||||
import Common 1.0
|
||||
import Common.Styles 1.0
|
||||
|
||||
Quick.MouseArea {
|
||||
cursorShape: containsMouse
|
||||
? Qt.PointingHandCursor
|
||||
: Qt.ArrowCursor
|
||||
hoverEnabled: true
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
|
||||
import Common 1.0
|
||||
import Common.Styles 1.0
|
||||
|
||||
// =============================================================================
|
||||
|
|
@ -97,7 +98,7 @@ Switch {
|
|||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
|
||||
|
||||
onClicked: control.enabled && control.clicked()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import QtQuick 2.7
|
||||
|
||||
import Common 1.0
|
||||
// =============================================================================
|
||||
|
||||
Item {
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ Item {
|
|||
id: builder
|
||||
|
||||
MouseArea {
|
||||
cursorShape: Qt.ArrowCursor
|
||||
property var _timeout
|
||||
|
||||
function _checkPosition (positionEvent) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import QtQuick 2.7
|
|||
import QtTest 1.1
|
||||
|
||||
import Utils 1.0
|
||||
|
||||
import Common 1.0
|
||||
// =============================================================================
|
||||
|
||||
Rectangle {
|
||||
|
|
|
|||
|
|
@ -94,7 +94,6 @@ Rectangle {
|
|||
id: mouseArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: entry.select()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import QtQuick 2.7
|
||||
|
||||
import Common 1.0
|
||||
import Common.Styles 1.0
|
||||
|
||||
// =============================================================================
|
||||
|
|
@ -42,7 +43,6 @@ Rectangle {
|
|||
id: mouseArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: entry.clicked()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import QtQuick 2.7
|
||||
|
||||
import Common 1.0
|
||||
import Common.Styles 1.0
|
||||
import Utils 1.0
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.5
|
||||
|
||||
import Common 1.0
|
||||
import Common.Styles 1.0
|
||||
import 'Window.js' as Logic
|
||||
|
||||
|
|
@ -57,6 +58,7 @@ StackView{
|
|||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onWheel: wheel.accepted = true
|
||||
cursorShape: Qt.ArrowCursor
|
||||
}
|
||||
Rectangle {
|
||||
id: content
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ CommonItemDelegate 1.0 Form/CommonItemDelegate.qml
|
|||
DroppableTextArea 1.0 Form/DroppableTextArea.qml
|
||||
ListForm 1.0 Form/ListForm.qml
|
||||
ListItemSelector 1.0 Form/ListItemSelector.qml
|
||||
MouseArea 1.0 Form/MouseArea.qml
|
||||
SearchBox 1.0 Form/SearchBox.qml
|
||||
Slider 1.0 Form/Slider.qml
|
||||
StaticListForm 1.0 Form/StaticListForm.qml
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ Item {
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
signal clicked
|
||||
property alias cursorShape:mouseArea.cursorShape
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -94,11 +95,8 @@ Item {
|
|||
}
|
||||
|
||||
MouseArea {
|
||||
id:mouseArea
|
||||
anchors.fill: parent
|
||||
cursorShape: containsMouse
|
||||
? Qt.PointingHandCursor
|
||||
: Qt.ArrowCursor
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: accountStatus.clicked()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ Rectangle {
|
|||
MouseArea {
|
||||
id: mouseArea
|
||||
|
||||
cursorShape: Qt.ArrowCursor
|
||||
hoverEnabled: true
|
||||
implicitHeight: layout.height
|
||||
width: parent.width + parent.anchors.rightMargin
|
||||
|
|
|
|||
|
|
@ -253,10 +253,6 @@ Row {
|
|||
}
|
||||
|
||||
anchors.fill: parent
|
||||
cursorShape: containsMouse
|
||||
? Qt.PointingHandCursor
|
||||
: Qt.ArrowCursor
|
||||
hoverEnabled: true
|
||||
visible: (rectangle.isUploaded || rectangle.isRead) && !$chatEntry.isOutgoing
|
||||
|
||||
onClicked: {
|
||||
|
|
@ -296,10 +292,6 @@ Row {
|
|||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: containsMouse
|
||||
? Qt.PointingHandCursor
|
||||
: Qt.ArrowCursor
|
||||
hoverEnabled: true
|
||||
visible: (rectangle.isError || $chatEntry.status === ChatModel.MessageStatusIdle) && $chatEntry.isOutgoing
|
||||
onClicked: proxyModel.resendMessage(index)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ Column {
|
|||
|
||||
delegate: MouseArea {
|
||||
id: dragArea
|
||||
cursorShape: Qt.ArrowCursor
|
||||
|
||||
property bool held: false
|
||||
|
||||
|
|
@ -189,7 +190,7 @@ Column {
|
|||
id: mouseArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.ArrowCursor
|
||||
|
||||
onPressed: mouse.accepted = false
|
||||
}
|
||||
|
|
|
|||
105
linphone-app/ui/modules/Linphone/History/Event.qml
Normal file
105
linphone-app/ui/modules/Linphone/History/Event.qml
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
import QtQuick 2.7
|
||||
|
||||
import Common 1.0
|
||||
import Linphone 1.0
|
||||
import LinphoneUtils 1.0
|
||||
import Linphone.Styles 1.0
|
||||
import Utils 1.0
|
||||
|
||||
// =============================================================================
|
||||
|
||||
Row {
|
||||
signal entryClicked(string sipAddress)
|
||||
|
||||
readonly property var _sipAddressObserver: SipAddressesModel.getSipAddressObserver($historyEntry.sipAddress, '')
|
||||
|
||||
property string _type: {
|
||||
var status = $historyEntry.status
|
||||
|
||||
if (status === HistoryModel.CallStatusSuccess) {
|
||||
if (!$historyEntry.isStart) {
|
||||
return 'ended_call'
|
||||
}
|
||||
return $historyEntry.isOutgoing ? 'outgoing_call' : 'incoming_call'
|
||||
}
|
||||
if (status === HistoryModel.CallStatusDeclined) {
|
||||
return $historyEntry.isOutgoing ? 'declined_outgoing_call' : 'declined_incoming_call'
|
||||
}
|
||||
if (status === HistoryModel.CallStatusMissed) {
|
||||
return $historyEntry.isOutgoing ? 'missed_outgoing_call' : 'missed_incoming_call'
|
||||
}
|
||||
if (status === HistoryModel.CallStatusAborted) {
|
||||
return $historyEntry.isOutgoing ? 'outgoing_call' : 'incoming_call'
|
||||
}
|
||||
if (status === HistoryModel.CallStatusEarlyAborted) {
|
||||
return $historyEntry.isOutgoing ? 'missed_outgoing_call' : 'missed_incoming_call'
|
||||
}
|
||||
if (status === HistoryModel.CallStatusAcceptedElsewhere) {
|
||||
return $historyEntry.isOutgoing ? 'outgoing_call' : 'incoming_call'
|
||||
}
|
||||
if (status === HistoryModel.CallStatusDeclinedElsewhere) {
|
||||
return $historyEntry.isOutgoing ? 'declined_outgoing_call' : 'declined_incoming_call'
|
||||
}
|
||||
|
||||
return 'unknown_call_event'
|
||||
}
|
||||
|
||||
height: HistoryStyle.entry.lineHeight
|
||||
spacing: HistoryStyle.entry.message.extraContent.spacing
|
||||
|
||||
Icon {
|
||||
height: parent.height
|
||||
icon: _type
|
||||
iconSize: HistoryStyle.entry.event.iconSize
|
||||
width: HistoryStyle.entry.metaWidth
|
||||
}
|
||||
|
||||
Text {
|
||||
Component {
|
||||
// Never created.
|
||||
// Private data for `lupdate`.
|
||||
Item {
|
||||
property var i18n: [
|
||||
QT_TR_NOOP('declinedIncomingCall'),
|
||||
QT_TR_NOOP('declinedOutgoingCall'),
|
||||
QT_TR_NOOP('endedCall'),
|
||||
QT_TR_NOOP('incomingCall'),
|
||||
QT_TR_NOOP('missedIncomingCall'),
|
||||
QT_TR_NOOP('missedOutgoingCall'),
|
||||
QT_TR_NOOP('outgoingCall')
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
color: HistoryStyle.entry.event.text.color
|
||||
font {
|
||||
bold: true
|
||||
pointSize: HistoryStyle.entry.event.text.pointSize
|
||||
}
|
||||
height: parent.height
|
||||
text: qsTr(Utils.snakeToCamel(_type)) +' - '
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
Text {
|
||||
color: HistoryStyle.entry.event.text.color
|
||||
font {
|
||||
bold: true
|
||||
pointSize: HistoryStyle.entry.event.text.pointSize
|
||||
}
|
||||
height: parent.height
|
||||
text: LinphoneUtils.getContactUsername(_sipAddressObserver)
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
MouseArea{
|
||||
anchors.fill:parent
|
||||
onClicked:entryClicked($historyEntry.sipAddress)
|
||||
}
|
||||
}
|
||||
ActionButton {
|
||||
height: HistoryStyle.entry.lineHeight
|
||||
icon: 'delete'
|
||||
iconSize: HistoryStyle.entry.deleteIconSize
|
||||
visible: isHoverEntry()
|
||||
|
||||
onClicked: removeEntry()
|
||||
}
|
||||
}
|
||||
67
linphone-app/ui/modules/Linphone/History/History.js
Normal file
67
linphone-app/ui/modules/Linphone/History/History.js
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2020 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// =============================================================================
|
||||
// `Chat.qml` Logic.
|
||||
// =============================================================================
|
||||
|
||||
.import QtQuick 2.7 as QtQuick
|
||||
|
||||
.import Linphone 1.0 as Linphone
|
||||
|
||||
.import 'qrc:/ui/scripts/LinphoneUtils/linphone-utils.js' as LinphoneUtils
|
||||
|
||||
// =============================================================================
|
||||
|
||||
function initView () {
|
||||
history.tryToLoadMoreEntries = false
|
||||
history.bindToEnd = true
|
||||
}
|
||||
|
||||
function loadMoreEntries () {
|
||||
if (history.atYBeginning && !history.tryToLoadMoreEntries) {
|
||||
history.tryToLoadMoreEntries = true
|
||||
history.positionViewAtBeginning()
|
||||
container.proxyModel.loadMoreEntries()
|
||||
}
|
||||
}
|
||||
|
||||
function getComponentFromEntry (historyEntry) {
|
||||
|
||||
if (historyEntry.type === Linphone.HistoryModel.CallEntry) {
|
||||
return 'Event.qml'
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
function handleMoreEntriesLoaded (n) {
|
||||
history.positionViewAtIndex(n - 1, QtQuick.ListView.Beginning)
|
||||
history.tryToLoadMoreEntries = false
|
||||
}
|
||||
|
||||
function handleMovementEnded () {
|
||||
if (history.atYEnd) {
|
||||
history.bindToEnd = true
|
||||
}
|
||||
}
|
||||
|
||||
function handleMovementStarted () {
|
||||
history.bindToEnd = false
|
||||
}
|
||||
205
linphone-app/ui/modules/Linphone/History/History.qml
Normal file
205
linphone-app/ui/modules/Linphone/History/History.qml
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import Common 1.0
|
||||
import Linphone 1.0
|
||||
import Linphone.Styles 1.0
|
||||
|
||||
import 'History.js' as Logic
|
||||
|
||||
// =============================================================================
|
||||
|
||||
Rectangle {
|
||||
id: container
|
||||
|
||||
property alias proxyModel: history.model
|
||||
signal entryClicked(string sipAddress)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
color: HistoryStyle.color
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
|
||||
ScrollableListView {
|
||||
id: history
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
property bool bindToEnd: false
|
||||
property bool tryToLoadMoreEntries: true
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
|
||||
highlightFollowsCurrentItem: false
|
||||
|
||||
section {
|
||||
criteria: ViewSection.FullString
|
||||
delegate: sectionHeading
|
||||
property: '$sectionDate'
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
Component.onCompleted: Logic.initView()
|
||||
|
||||
onContentYChanged: Logic.loadMoreEntries()
|
||||
onMovementEnded: Logic.handleMovementEnded()
|
||||
onMovementStarted: Logic.handleMovementStarted()
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
Connections {
|
||||
target: proxyModel
|
||||
|
||||
// When the view is changed (for example `Calls` -> `Messages`),
|
||||
// the position is set at end and it can be possible to load
|
||||
// more entries.
|
||||
onEntryTypeFilterChanged: Logic.initView()
|
||||
onMoreEntriesLoaded: Logic.handleMoreEntriesLoaded(n)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Heading.
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
Component {
|
||||
id: sectionHeading
|
||||
|
||||
Item {
|
||||
implicitHeight: container.height + HistoryStyle.sectionHeading.bottomMargin
|
||||
width: parent.width
|
||||
|
||||
Borders {
|
||||
id: container
|
||||
|
||||
borderColor: HistoryStyle.sectionHeading.border.color
|
||||
bottomWidth: HistoryStyle.sectionHeading.border.width
|
||||
implicitHeight: text.contentHeight +
|
||||
HistoryStyle.sectionHeading.padding * 2 +
|
||||
HistoryStyle.sectionHeading.border.width * 2
|
||||
topWidth: HistoryStyle.sectionHeading.border.width
|
||||
width: parent.width
|
||||
|
||||
Text {
|
||||
id: text
|
||||
|
||||
anchors.fill: parent
|
||||
color: HistoryStyle.sectionHeading.text.color
|
||||
font {
|
||||
bold: true
|
||||
pointSize: HistoryStyle.sectionHeading.text.pointSize
|
||||
}
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
// Cast section to integer because Qt converts the
|
||||
// sectionDate in string!!!
|
||||
text: new Date(section).toLocaleDateString(
|
||||
Qt.locale(App.locale)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Message/Event renderer.
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
delegate: Rectangle {
|
||||
id: entry
|
||||
|
||||
function isHoverEntry () {
|
||||
return mouseArea.containsMouse
|
||||
}
|
||||
|
||||
function removeEntry () {
|
||||
proxyModel.removeEntry(index)
|
||||
}
|
||||
|
||||
anchors {
|
||||
left: parent ? parent.left : undefined
|
||||
leftMargin: HistoryStyle.entry.leftMargin
|
||||
right: parent ? parent.right : undefined
|
||||
|
||||
rightMargin: HistoryStyle.entry.deleteIconSize +
|
||||
HistoryStyle.entry.message.extraContent.spacing +
|
||||
HistoryStyle.entry.message.extraContent.rightMargin +
|
||||
HistoryStyle.entry.message.extraContent.leftMargin
|
||||
}
|
||||
|
||||
color: HistoryStyle.color
|
||||
implicitHeight: layout.height + HistoryStyle.entry.bottomMargin
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
|
||||
cursorShape: Qt.ArrowCursor
|
||||
hoverEnabled: true
|
||||
implicitHeight: layout.height
|
||||
width: parent.width + parent.anchors.rightMargin
|
||||
|
||||
RowLayout {
|
||||
id: layout
|
||||
|
||||
spacing: 0
|
||||
width: entry.width
|
||||
|
||||
// Display time.
|
||||
Text {
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.preferredHeight: HistoryStyle.entry.lineHeight
|
||||
Layout.preferredWidth: HistoryStyle.entry.time.width
|
||||
|
||||
color: HistoryStyle.entry.time.color
|
||||
font.pointSize: HistoryStyle.entry.time.pointSize
|
||||
|
||||
text: $historyEntry.timestamp.toLocaleString(
|
||||
Qt.locale(App.locale),
|
||||
'hh:mm'
|
||||
)
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
TooltipArea {
|
||||
text: $historyEntry.timestamp.toLocaleString(Qt.locale(App.locale))
|
||||
}
|
||||
}
|
||||
|
||||
// Display content.
|
||||
Loader {
|
||||
id:entryLoader
|
||||
Layout.fillWidth: true
|
||||
source: Logic.getComponentFromEntry($historyEntry)
|
||||
}
|
||||
Connections{
|
||||
target:entryLoader.item
|
||||
onEntryClicked:{entryClicked(sipAddress)}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Scroll at end if necessary.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Timer {
|
||||
interval: 100
|
||||
repeat: true
|
||||
running: true
|
||||
|
||||
onTriggered: history.bindToEnd && history.positionViewAtEnd()
|
||||
}
|
||||
}
|
||||
|
|
@ -101,7 +101,6 @@ Item {
|
|||
id: mouseArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: {
|
||||
menu.close()
|
||||
|
|
|
|||
|
|
@ -35,8 +35,6 @@ Notification {
|
|||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: notification._close(notification.handler)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,8 +65,6 @@ Notification {
|
|||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: notification._close(function () {
|
||||
var uri = Utils.getUriFromSystemPath(notification.fileUri)
|
||||
|
|
|
|||
|
|
@ -71,8 +71,6 @@ Notification {
|
|||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: notification._close(function () {
|
||||
AccountSettingsModel.setDefaultProxyConfigFromSipAddress(notification.localAddress)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
pragma Singleton
|
||||
import QtQml 2.2
|
||||
|
||||
import Colors 1.0
|
||||
import Units 1.0
|
||||
|
||||
// =============================================================================
|
||||
|
||||
QtObject {
|
||||
property color color: Colors.q
|
||||
|
||||
property QtObject sectionHeading: QtObject {
|
||||
property int padding: 5
|
||||
property int bottomMargin: 20
|
||||
|
||||
property QtObject border: QtObject {
|
||||
property color color: Colors.g10
|
||||
property int width: 1
|
||||
}
|
||||
|
||||
property QtObject text: QtObject {
|
||||
property int pointSize: Units.dp * 10
|
||||
property color color: Colors.g
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
property QtObject entry: QtObject {
|
||||
property int bottomMargin: 10
|
||||
property int deleteIconSize: 22
|
||||
property int leftMargin: 18
|
||||
property int lineHeight: 30
|
||||
property int metaWidth: 40
|
||||
|
||||
property QtObject event: QtObject {
|
||||
property int iconSize: 18
|
||||
|
||||
property QtObject text: QtObject {
|
||||
property color color: Colors.d
|
||||
property int pointSize: Units.dp * 10
|
||||
}
|
||||
}
|
||||
|
||||
property QtObject message: QtObject {
|
||||
property int padding: 8
|
||||
property int radius: 4
|
||||
|
||||
property QtObject extraContent: QtObject {
|
||||
property int leftMargin: 10
|
||||
property int spacing: 5
|
||||
property int rightMargin: 5
|
||||
}
|
||||
}
|
||||
|
||||
property QtObject time: QtObject {
|
||||
property color color: Colors.d
|
||||
property int pointSize: Units.dp * 10
|
||||
property int width: 44
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -34,7 +34,10 @@ QtObject {
|
|||
}
|
||||
|
||||
property QtObject legend: QtObject {
|
||||
property color backgroundColor: Colors.f
|
||||
property QtObject backgroundColor: QtObject {
|
||||
property color normal: Colors.f
|
||||
property color hovered: Colors.c
|
||||
}
|
||||
property color color: Colors.d
|
||||
property int pointSize: Units.dp * 11
|
||||
property int height: 30
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ singleton ContactStyle 1.0 Contact/ContactStyle.qml
|
|||
|
||||
singleton OnlineInstallerDialogStyle 1.0 Dialog/OnlineInstallerDialogStyle.qml
|
||||
|
||||
singleton HistoryStyle 1.0 History/HistoryStyle.qml
|
||||
|
||||
singleton SipAddressesMenuStyle 1.0 Menus/SipAddressesMenuStyle.qml
|
||||
|
||||
singleton MessageCounterStyle 1.0 Misc/MessageCounterStyle.qml
|
||||
|
|
|
|||
|
|
@ -55,7 +55,16 @@ Rectangle {
|
|||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: TimelineStyle.legend.height
|
||||
color: TimelineStyle.legend.backgroundColor
|
||||
color: showHistory.containsMouse?TimelineStyle.legend.backgroundColor.hovered:TimelineStyle.legend.backgroundColor.normal
|
||||
|
||||
MouseArea{
|
||||
id:showHistory
|
||||
anchors.fill:parent
|
||||
onClicked: {
|
||||
view.currentIndex = -1
|
||||
timeline.entrySelected('')
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors {
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ ScrollableListView {
|
|||
// Workaround to handle mouse.
|
||||
// Without it, the mouse can be given to items list when mouse is hover header.
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.ArrowCursor
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
|
|
@ -194,7 +195,7 @@ ScrollableListView {
|
|||
id: mouseArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.ArrowCursor
|
||||
|
||||
RowLayout {
|
||||
anchors {
|
||||
|
|
@ -215,12 +216,6 @@ ScrollableListView {
|
|||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
|
||||
cursorShape: containsMouse
|
||||
? Qt.PointingHandCursor
|
||||
: Qt.ArrowCursor
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: sipAddressesView.entryClicked($sipAddress)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ CallStatistics 1.0 Calls/CallStatistics.qml
|
|||
|
||||
Chat 1.0 Chat/Chat.qml
|
||||
|
||||
History 1.0 History/History.qml
|
||||
|
||||
CodecsViewer 1.0 Codecs/CodecsViewer.qml
|
||||
|
||||
Avatar 1.0 Contact/Avatar.qml
|
||||
|
|
|
|||
|
|
@ -84,28 +84,31 @@ function _getUsername (str) {
|
|||
|
||||
// Returns the username of a contact/sipAddressObserver object or URI string.
|
||||
function getContactUsername (contact) {
|
||||
var object = contact.contact || // Contact object from `SipAddressObserver`.
|
||||
(contact.vcard && contact) // Contact object.
|
||||
|
||||
// 1. `object` is a contact.
|
||||
if (object) {
|
||||
return object.vcard.username
|
||||
}
|
||||
|
||||
// 2. `object` is just a string.
|
||||
object = Utils.isString(contact.peerAddress)
|
||||
? contact.peerAddress // String from `SipAddressObserver`.
|
||||
: contact // Just a String.
|
||||
|
||||
// Use display name.
|
||||
var name = _getDisplayName(object)
|
||||
if (name != null) {
|
||||
return name
|
||||
}
|
||||
|
||||
// Use username.
|
||||
name = _getUsername(object)
|
||||
return name == null ? 'Bad EGG' : name
|
||||
if(contact){
|
||||
var object = contact.contact || // Contact object from `SipAddressObserver`.
|
||||
(contact.vcard && contact) // Contact object.
|
||||
|
||||
// 1. `object` is a contact.
|
||||
if (object) {
|
||||
return object.vcard.username
|
||||
}
|
||||
|
||||
// 2. `object` is just a string.
|
||||
object = Utils.isString(contact.peerAddress)
|
||||
? contact.peerAddress // String from `SipAddressObserver`.
|
||||
: contact // Just a String.
|
||||
|
||||
// Use display name.
|
||||
var name = _getDisplayName(object)
|
||||
if (name != null) {
|
||||
return name
|
||||
}
|
||||
|
||||
// Use username.
|
||||
name = _getUsername(object)
|
||||
return name == null ? 'Bad EGG' : name
|
||||
}else
|
||||
return '';
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
|
|
|
|||
|
|
@ -101,8 +101,8 @@ Window {
|
|||
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.NoButton
|
||||
hoverEnabled: true
|
||||
propagateComposedEvents: true
|
||||
cursorShape: Qt.ArrowCursor
|
||||
|
||||
onEntered: hideButtonsTimer.start()
|
||||
onExited: hideButtonsTimer.stop()
|
||||
|
|
|
|||
|
|
@ -208,14 +208,10 @@ ColumnLayout {
|
|||
id: mouseArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.ArrowCursor
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: containsMouse
|
||||
? Qt.PointingHandCursor
|
||||
: Qt.ArrowCursor
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: window.setView('ContactEdit', {
|
||||
sipAddress: $contact.vcard.sipAddresses[0]
|
||||
|
|
|
|||
|
|
@ -102,9 +102,9 @@ ColumnLayout {
|
|||
onClicked: window.setView('ContactEdit', {
|
||||
sipAddress: conversation.peerAddress
|
||||
})
|
||||
TooltipArea {
|
||||
text: Logic.getEditTooltipText()
|
||||
}
|
||||
TooltipArea {
|
||||
text: Logic.getEditTooltipText()
|
||||
}
|
||||
}
|
||||
|
||||
ActionButton {
|
||||
|
|
|
|||
65
linphone-app/ui/views/App/Main/HistoryView.js
Normal file
65
linphone-app/ui/views/App/Main/HistoryView.js
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2020 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// =============================================================================
|
||||
// `Conversation.qml` Logic.
|
||||
// =============================================================================
|
||||
|
||||
.import Linphone 1.0 as Linphone
|
||||
|
||||
.import 'qrc:/ui/scripts/LinphoneUtils/linphone-utils.js' as LinphoneUtils
|
||||
.import 'qrc:/ui/scripts/Utils/utils.js' as Utils
|
||||
|
||||
// =============================================================================
|
||||
|
||||
function removeAllEntries () {
|
||||
window.attachVirtualWindow(Utils.buildDialogUri('ConfirmDialog'), {
|
||||
descriptionText: qsTr('removeAllEntriesDescription'),
|
||||
}, function (status) {
|
||||
if (status) {
|
||||
historyProxyModel.removeAllEntries()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function getAvatar () {
|
||||
var contact = historyView._sipAddressObserver.contact
|
||||
return contact ? contact.vcard.avatar : ''
|
||||
}
|
||||
|
||||
function getEditIcon () {
|
||||
return historyView._sipAddressObserver && historyView._sipAddressObserver.contact ? 'contact_edit' : 'contact_add'
|
||||
}
|
||||
|
||||
function getEditTooltipText() {
|
||||
return historyView._sipAddressObserver && historyView._sipAddressObserver.contact ? qsTr('tooltipContactEdit') : qsTr('tooltipContactAdd')
|
||||
}
|
||||
|
||||
function getUsername () {
|
||||
return LinphoneUtils.getContactUsername(historyView._sipAddressObserver)
|
||||
}
|
||||
|
||||
function updateHistoryFilter (button) {
|
||||
var HistoryModel = Linphone.HistoryModel
|
||||
if (button === 0) {
|
||||
historyProxyModel.setEntryTypeFilter(HistoryModel.GenericEntry)
|
||||
} else if (button === 1) {
|
||||
historyProxyModel.setEntryTypeFilter(HistoryModel.CallEntry)
|
||||
}
|
||||
}
|
||||
150
linphone-app/ui/views/App/Main/HistoryView.qml
Normal file
150
linphone-app/ui/views/App/Main/HistoryView.qml
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import Common 1.0
|
||||
import Linphone 1.0
|
||||
|
||||
import App.Styles 1.0
|
||||
|
||||
import 'HistoryView.js' as Logic
|
||||
|
||||
// =============================================================================
|
||||
|
||||
ColumnLayout {
|
||||
id: historyView
|
||||
|
||||
property string peerAddress
|
||||
property string fullPeerAddress
|
||||
|
||||
readonly property var _sipAddressObserver: peerAddress?SipAddressesModel.getSipAddressObserver((fullPeerAddress?fullPeerAddress:peerAddress), ''):null
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
spacing: 0
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Contact bar.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: peerAddress?HistoryViewStyle.bar.height:HistoryViewStyle.bar.height/2
|
||||
|
||||
color: HistoryViewStyle.bar.backgroundColor
|
||||
|
||||
RowLayout {
|
||||
anchors {
|
||||
fill: parent
|
||||
leftMargin: HistoryViewStyle.bar.leftMargin
|
||||
rightMargin: HistoryViewStyle.bar.rightMargin
|
||||
}
|
||||
spacing: HistoryViewStyle.bar.spacing
|
||||
|
||||
layoutDirection: peerAddress?Qt.LeftToRight :Qt.RightToLeft
|
||||
|
||||
Avatar {
|
||||
id: avatar
|
||||
|
||||
Layout.preferredHeight: HistoryViewStyle.bar.avatarSize
|
||||
Layout.preferredWidth: HistoryViewStyle.bar.avatarSize
|
||||
|
||||
image: peerAddress?Logic.getAvatar():null
|
||||
|
||||
presenceLevel: historyView._sipAddressObserver?Presence.getPresenceLevel(
|
||||
historyView._sipAddressObserver.presenceStatus
|
||||
):null
|
||||
|
||||
username: peerAddress?Logic.getUsername():null
|
||||
visible:peerAddress
|
||||
}
|
||||
|
||||
ContactDescription {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
|
||||
sipAddress: historyView.peerAddress
|
||||
sipAddressColor: HistoryViewStyle.bar.description.sipAddressColor
|
||||
username: avatar.username
|
||||
usernameColor: HistoryViewStyle.bar.description.usernameColor
|
||||
visible:peerAddress
|
||||
}
|
||||
|
||||
Row {
|
||||
Layout.fillHeight: true
|
||||
|
||||
spacing: HistoryViewStyle.bar.actions.spacing
|
||||
|
||||
ActionBar {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
iconSize: HistoryViewStyle.bar.actions.call.iconSize
|
||||
|
||||
ActionButton {
|
||||
icon: 'video_call'
|
||||
visible: peerAddress && SettingsModel.videoSupported && SettingsModel.outgoingCallsEnabled
|
||||
|
||||
onClicked: CallsListModel.launchVideoCall(historyView.peerAddress)
|
||||
}
|
||||
|
||||
ActionButton {
|
||||
icon: 'call'
|
||||
visible: peerAddress && SettingsModel.outgoingCallsEnabled
|
||||
|
||||
onClicked: CallsListModel.launchAudioCall(historyView.peerAddress)
|
||||
}
|
||||
}
|
||||
|
||||
ActionBar {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
ActionButton {
|
||||
icon: Logic.getEditIcon()
|
||||
iconSize: HistoryViewStyle.bar.actions.edit.iconSize
|
||||
visible: peerAddress && SettingsModel.contactsEnabled
|
||||
|
||||
onClicked: window.setView('ContactEdit', { sipAddress: historyView.peerAddress })
|
||||
TooltipArea {
|
||||
text: peerAddress?Logic.getEditTooltipText():''
|
||||
}
|
||||
}
|
||||
|
||||
ActionButton {
|
||||
icon: 'delete'
|
||||
iconSize: HistoryViewStyle.bar.actions.edit.iconSize
|
||||
|
||||
onClicked: Logic.removeAllEntries()
|
||||
|
||||
TooltipArea {
|
||||
text: qsTr('cleanHistory')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// History.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
History {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
|
||||
onEntryClicked:{
|
||||
historyView.fullPeerAddress=sipAddress
|
||||
historyView.peerAddress=sipAddress
|
||||
historyProxyModel.resetMessageCount()
|
||||
}
|
||||
|
||||
proxyModel: HistoryProxyModel {
|
||||
id: historyProxyModel
|
||||
|
||||
Component.onCompleted: {
|
||||
setEntryTypeFilter()
|
||||
resetMessageCount()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -110,6 +110,7 @@ ApplicationWindow {
|
|||
|
||||
TooltipArea {
|
||||
text: AccountSettingsModel.sipAddress
|
||||
hoveringCursor: Qt.PointingHandCursor
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
|
|
@ -260,12 +261,14 @@ ApplicationWindow {
|
|||
Layout.fillWidth: true
|
||||
model: TimelineModel
|
||||
|
||||
onEntrySelected: setView('Conversation', {
|
||||
peerAddress: entry,
|
||||
localAddress: AccountSettingsModel.sipAddress,
|
||||
fullPeerAddress: entry,
|
||||
fullLocalAddress: AccountSettingsModel.fullSipAddress
|
||||
})
|
||||
onEntrySelected: (entry?setView('Conversation', {
|
||||
peerAddress: entry,
|
||||
localAddress: AccountSettingsModel.sipAddress,
|
||||
fullPeerAddress: entry,
|
||||
fullLocalAddress: AccountSettingsModel.fullSipAddress
|
||||
}):
|
||||
setView('HistoryView', {})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -279,7 +282,7 @@ ApplicationWindow {
|
|||
Layout.fillWidth: true
|
||||
|
||||
source: 'Home.qml'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -287,7 +290,7 @@ ApplicationWindow {
|
|||
// ---------------------------------------------------------------------------
|
||||
// Url handlers.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
Connections {
|
||||
target: UrlHandlers
|
||||
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ ApplicationWindow {
|
|||
anchors.fill: parent
|
||||
|
||||
onClicked: konami.forceActiveFocus()
|
||||
cursorShape: Qt.ArrowCursor
|
||||
|
||||
Konami {
|
||||
id: konami
|
||||
|
|
|
|||
50
linphone-app/ui/views/App/Styles/Main/HistoryViewStyle.qml
Normal file
50
linphone-app/ui/views/App/Styles/Main/HistoryViewStyle.qml
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
pragma Singleton
|
||||
import QtQml 2.2
|
||||
|
||||
import Colors 1.0
|
||||
|
||||
// =============================================================================
|
||||
|
||||
QtObject {
|
||||
property QtObject bar: QtObject {
|
||||
property color backgroundColor: Colors.e
|
||||
property int avatarSize: 60
|
||||
property int height: 80
|
||||
property int leftMargin: 40
|
||||
property int rightMargin: 30
|
||||
property int spacing: 20
|
||||
|
||||
property QtObject actions: QtObject {
|
||||
property int spacing: 40
|
||||
|
||||
property QtObject call: QtObject {
|
||||
property int iconSize: 40
|
||||
}
|
||||
|
||||
property QtObject del: QtObject {
|
||||
property int iconSize: 22
|
||||
}
|
||||
|
||||
property QtObject edit: QtObject {
|
||||
property int iconSize: 22
|
||||
}
|
||||
}
|
||||
|
||||
property QtObject description: QtObject {
|
||||
property color sipAddressColor: Colors.g
|
||||
property color usernameColor: Colors.j
|
||||
}
|
||||
}
|
||||
|
||||
property QtObject filters: QtObject {
|
||||
property color backgroundColor: Colors.q
|
||||
property int height: 51
|
||||
property int leftMargin: 40
|
||||
|
||||
property QtObject border: QtObject {
|
||||
property color color: Colors.g10
|
||||
property int bottomWidth: 1
|
||||
property int topWidth: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -29,6 +29,7 @@ singleton ContactEditStyle 1.0 Main/ContactEditSty
|
|||
singleton ContactsStyle 1.0 Main/ContactsStyle.qml
|
||||
singleton ConversationStyle 1.0 Main/ConversationStyle.qml
|
||||
singleton HomeStyle 1.0 Main/HomeStyle.qml
|
||||
singleton HistoryViewStyle 1.0 Main/HistoryViewStyle.qml
|
||||
singleton InviteFriendsStyle 1.0 Main/InviteFriendsStyle.qml
|
||||
singleton MainWindowStyle 1.0 Main/MainWindowStyle.qml
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue