From 36d63098a7e57ca14121cb4a03d6ca7a785bb984 Mon Sep 17 00:00:00 2001 From: Christophe Deschamps Date: Fri, 27 Sep 2024 09:29:32 +0200 Subject: [PATCH] - Support option for showing entire LDAP address book in contacts list ([ui]sync_ldap_contacts) - Make LDAP contacts read only in the app - Use different MagicSerach for contact list and contact searching --- Linphone/core/address-books/LdapCore.cpp | 7 +++++++ Linphone/core/friend/FriendCore.cpp | 13 +++++++++++++ Linphone/core/friend/FriendCore.hpp | 6 ++++++ Linphone/core/search/MagicSearchList.cpp | 5 +++-- Linphone/core/search/MagicSearchList.hpp | 2 +- Linphone/core/search/MagicSearchProxy.cpp | 1 + Linphone/core/search/MagicSearchProxy.hpp | 1 + Linphone/core/setting/SettingsCore.cpp | 3 +++ Linphone/core/setting/SettingsCore.hpp | 10 +++++++++- Linphone/model/address-books/LdapModel.cpp | 3 ++- Linphone/model/core/CoreModel.hpp | 1 + Linphone/model/setting/SettingsModel.cpp | 8 ++++++++ Linphone/model/setting/SettingsModel.hpp | 1 + .../Control/Display/Contact/ContactListView.qml | 14 ++++++++++++++ Linphone/view/Page/Main/Contact/ContactPage.qml | 3 +++ 15 files changed, 73 insertions(+), 5 deletions(-) diff --git a/Linphone/core/address-books/LdapCore.cpp b/Linphone/core/address-books/LdapCore.cpp index 40eeae893..fe5e43db1 100644 --- a/Linphone/core/address-books/LdapCore.cpp +++ b/Linphone/core/address-books/LdapCore.cpp @@ -103,4 +103,11 @@ void LdapCore::setSelf(QSharedPointer me) { DEFINE_CORE_GETSET_CONNECT(mLdapModelConnection, LdapCore, LdapModel, mLdapModel, QString, sipDomain, SipDomain) DEFINE_CORE_GETSET_CONNECT(mLdapModelConnection, LdapCore, LdapModel, mLdapModel, linphone::Ldap::DebugLevel, debugLevel, DebugLevel) + + mLdapModelConnection->makeConnectToModel(&LdapModel::saved, [this]() { + mLdapModelConnection->invokeToCore([this]() { emit App::getInstance() -> getSettings()->ldapConfigChanged(); }); + }); + mLdapModelConnection->makeConnectToModel(&LdapModel::removed, [this]() { + mLdapModelConnection->invokeToCore([this]() { emit App::getInstance() -> getSettings()->ldapConfigChanged(); }); + }); } diff --git a/Linphone/core/friend/FriendCore.cpp b/Linphone/core/friend/FriendCore.cpp index f03e0db46..2788c38f6 100644 --- a/Linphone/core/friend/FriendCore.cpp +++ b/Linphone/core/friend/FriendCore.cpp @@ -648,3 +648,16 @@ void FriendCore::undo() { // Retrieve values from model }); } } + +bool FriendCore::getIsLdap() const { + return mIsLdap; +} +void FriendCore::setIsLdap(bool data) { + if (mIsLdap != data) { + mIsLdap = data; + } +} + +bool FriendCore::getReadOnly() const { + return getIsLdap(); // TODO add conditions for friends retrieved via HTTP [misc]vcards-contacts-list= & CardDAV +} diff --git a/Linphone/core/friend/FriendCore.hpp b/Linphone/core/friend/FriendCore.hpp index 782ebf413..c053dbd33 100644 --- a/Linphone/core/friend/FriendCore.hpp +++ b/Linphone/core/friend/FriendCore.hpp @@ -67,6 +67,7 @@ class FriendCore : public QObject, public AbstractObject { Q_PROPERTY(bool isSaved READ getIsSaved NOTIFY isSavedChanged) Q_PROPERTY(QString pictureUri READ getPictureUri WRITE setPictureUri NOTIFY pictureUriChanged) Q_PROPERTY(bool starred READ getStarred WRITE lSetStarred NOTIFY starredChanged) + Q_PROPERTY(bool readOnly READ getReadOnly CONSTANT) public: // Should be call from model Thread. Will be automatically in App thread after initialization @@ -134,6 +135,10 @@ public: void onPresenceReceived(LinphoneEnums::ConsolidatedPresence consolidatedPresence, QDateTime presenceTimestamp); + bool getIsLdap() const; + void setIsLdap(bool isLdap); + bool getReadOnly() const; + Q_INVOKABLE void remove(); Q_INVOKABLE void save(); Q_INVOKABLE void undo(); @@ -184,6 +189,7 @@ protected: QString mPictureUri; bool mIsSaved; QString mVCardString; + bool mIsLdap; std::shared_ptr mFriendModel; QSharedPointer> mFriendModelConnection; QSharedPointer> mCoreModelConnection; diff --git a/Linphone/core/search/MagicSearchList.cpp b/Linphone/core/search/MagicSearchList.cpp index 1033d02c7..186ea1a6f 100644 --- a/Linphone/core/search/MagicSearchList.cpp +++ b/Linphone/core/search/MagicSearchList.cpp @@ -122,6 +122,8 @@ void MagicSearchList::setSelf(QSharedPointer me) { contact->appendPhoneNumber(tr("Phone"), Utils::coreStringToAppString(it->getPhoneNumber())); contacts->append(contact); } + bool isLdap = (it->getSourceFlags() & (int)LinphoneEnums::MagicSearchSource::LdapServers) != 0; + if (contact) contact->setIsLdap(isLdap); } mModelConnection->invokeToCore([this, contacts]() { setResults(*contacts); @@ -129,7 +131,6 @@ void MagicSearchList::setSelf(QSharedPointer me) { }); }); emit initialized(); - emit lSearch(mSearchFilter); }); }); } @@ -207,4 +208,4 @@ int MagicSearchList::findFriendIndexByAddress(const QString &address) { ++i; } return -1; -} \ No newline at end of file +} diff --git a/Linphone/core/search/MagicSearchList.hpp b/Linphone/core/search/MagicSearchList.hpp index d7e72b395..395146512 100644 --- a/Linphone/core/search/MagicSearchList.hpp +++ b/Linphone/core/search/MagicSearchList.hpp @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2010-2024 Belledonne Communications SARL. * * This file is part of linphone-desktop diff --git a/Linphone/core/search/MagicSearchProxy.cpp b/Linphone/core/search/MagicSearchProxy.cpp index 6c625a9bd..c67106eba 100644 --- a/Linphone/core/search/MagicSearchProxy.cpp +++ b/Linphone/core/search/MagicSearchProxy.cpp @@ -55,6 +55,7 @@ void MagicSearchProxy::setSourceModel(QAbstractItemModel *model) { connect(newMagicSearchList, &MagicSearchList::initialized, this, [this, newMagicSearchList] { emit newMagicSearchList->lSetSourceFlags(mSourceFlags); emit newMagicSearchList->lSetAggregationFlag(mAggregationFlag); + emit initialized(); }); } QSortFilterProxyModel::setSourceModel(model); diff --git a/Linphone/core/search/MagicSearchProxy.hpp b/Linphone/core/search/MagicSearchProxy.hpp index 9a56f2af7..12a01831e 100644 --- a/Linphone/core/search/MagicSearchProxy.hpp +++ b/Linphone/core/search/MagicSearchProxy.hpp @@ -64,6 +64,7 @@ signals: void forceUpdate(); void friendCreated(int index); void showFavoriteOnlyChanged(); + void initialized(); protected: QString mSearchText; diff --git a/Linphone/core/setting/SettingsCore.cpp b/Linphone/core/setting/SettingsCore.cpp index eb749a2e1..70a54930e 100644 --- a/Linphone/core/setting/SettingsCore.cpp +++ b/Linphone/core/setting/SettingsCore.cpp @@ -91,6 +91,7 @@ SettingsCore::SettingsCore(QObject *parent) : QObject(parent) { INIT_CORE_MEMBER(AssistantThirdPartySipAccountDomain, mSettingsModel) INIT_CORE_MEMBER(AssistantThirdPartySipAccountTransport, mSettingsModel) INIT_CORE_MEMBER(AutoStart, mSettingsModel) + INIT_CORE_MEMBER(SyncLdapContacts, mSettingsModel) } SettingsCore::~SettingsCore() { @@ -307,6 +308,8 @@ void SettingsCore::setSelf(QSharedPointer me) { assistantThirdPartySipAccountTransport, AssistantThirdPartySipAccountTransport) DEFINE_CORE_GETSET_CONNECT(mSettingsModelConnection, SettingsCore, SettingsModel, mSettingsModel, bool, autoStart, AutoStart) + DEFINE_CORE_GETSET_CONNECT(mSettingsModelConnection, SettingsCore, SettingsModel, mSettingsModel, bool, + syncLdapContacts, SyncLdapContacts) auto coreModelConnection = QSharedPointer>( new SafeConnection(me, CoreModel::getInstance()), &QObject::deleteLater); diff --git a/Linphone/core/setting/SettingsCore.hpp b/Linphone/core/setting/SettingsCore.hpp index 66f134d8c..cdd6e5220 100644 --- a/Linphone/core/setting/SettingsCore.hpp +++ b/Linphone/core/setting/SettingsCore.hpp @@ -157,7 +157,13 @@ public: DECLARE_CORE_GETSET(QString, assistantThirdPartySipAccountDomain, AssistantThirdPartySipAccountDomain) DECLARE_CORE_GETSET(QString, assistantThirdPartySipAccountTransport, AssistantThirdPartySipAccountTransport) DECLARE_CORE_GETSET(bool, autoStart, AutoStart) - bool getAutoStart() { return mAutoStart; }; + bool getAutoStart() { + return mAutoStart; + }; + DECLARE_CORE_GETSET(bool, syncLdapContacts, SyncLdapContacts) + bool getSyncLdapContacts() { + return mSyncLdapContacts; + }; signals: @@ -217,6 +223,8 @@ signals: void dndChanged(); void lEnableDnd(bool value); + void ldapConfigChanged(); + private: std::shared_ptr mSettingsModel; diff --git a/Linphone/model/address-books/LdapModel.cpp b/Linphone/model/address-books/LdapModel.cpp index c6f368687..9fdd57435 100644 --- a/Linphone/model/address-books/LdapModel.cpp +++ b/Linphone/model/address-books/LdapModel.cpp @@ -33,8 +33,9 @@ LdapModel::LdapModel(const std::shared_ptr &ldap, QObject *paren mLdap = nullptr; mLdapParamsClone = CoreModel::getInstance()->getCore()->createLdapParams(); mLdapParamsClone->setTimeout(5); + mLdapParamsClone->setMaxResults(50); mLdapParamsClone->setDelay(2000); - mLdapParamsClone->setMinChars(3); + mLdapParamsClone->setMinChars(0); // Needs to be 0 if Contacts list should be synchronized with LDAP AB mLdapParamsClone->enableTls(true); } } diff --git a/Linphone/model/core/CoreModel.hpp b/Linphone/model/core/CoreModel.hpp index d47af6da8..252b4f0a8 100644 --- a/Linphone/model/core/CoreModel.hpp +++ b/Linphone/model/core/CoreModel.hpp @@ -71,6 +71,7 @@ signals: void unreadNotificationsChanged(); void requestFetchConfig(QString path); void requestRestart(); + void enabledLdapAddressBookSaved(); private: QString mConfigPath; diff --git a/Linphone/model/setting/SettingsModel.cpp b/Linphone/model/setting/SettingsModel.cpp index 5db5f87c8..7f9ebf82f 100644 --- a/Linphone/model/setting/SettingsModel.cpp +++ b/Linphone/model/setting/SettingsModel.cpp @@ -493,6 +493,7 @@ void SettingsModel::notifyConfigReady(){ DEFINE_NOTIFY_CONFIG_READY(assistantThirdPartySipAccountDomain, AssistantThirdPartySipAccountDomain) DEFINE_NOTIFY_CONFIG_READY(assistantThirdPartySipAccountTransport, AssistantThirdPartySipAccountTransport) DEFINE_NOTIFY_CONFIG_READY(autoStart, AutoStart) + DEFINE_NOTIFY_CONFIG_READY(syncLdapContacts, SyncLdapContacts) } DEFINE_GETSET_CONFIG(SettingsModel, bool, Bool, disableChatFeature, DisableChatFeature, "disable_chat_feature", false) @@ -575,4 +576,11 @@ DEFINE_GETSET_CONFIG(SettingsModel, AutoStart, "auto_start", false) +DEFINE_GETSET_CONFIG(SettingsModel, + bool, + Bool, + syncLdapContacts, + SyncLdapContacts, + "sync_ldap_contacts", + true) // clang-format on diff --git a/Linphone/model/setting/SettingsModel.hpp b/Linphone/model/setting/SettingsModel.hpp index 4701019a2..86257af0b 100644 --- a/Linphone/model/setting/SettingsModel.hpp +++ b/Linphone/model/setting/SettingsModel.hpp @@ -140,6 +140,7 @@ public: DECLARE_GETSET(QString, assistantThirdPartySipAccountDomain, AssistantThirdPartySipAccountDomain) DECLARE_GETSET(QString, assistantThirdPartySipAccountTransport, AssistantThirdPartySipAccountTransport) DECLARE_GETSET(bool, autoStart, AutoStart) + DECLARE_GETSET(bool, syncLdapContacts, SyncLdapContacts) signals: diff --git a/Linphone/view/Control/Display/Contact/ContactListView.qml b/Linphone/view/Control/Display/Contact/ContactListView.qml index 16d13fb2d..d8bf8d081 100644 --- a/Linphone/view/Control/Display/Contact/ContactListView.qml +++ b/Linphone/view/Control/Display/Contact/ContactListView.qml @@ -5,6 +5,7 @@ import QtQuick.Controls as Control import Linphone import UtilsCpp 1.0 import ConstantsCpp 1.0 +import SettingsCpp ListView { id: mainItem @@ -97,6 +98,18 @@ ListView { } aggregationFlag: mainItem.aggregationFlag sourceModel: mainItem.sourceModel + sourceFlags: LinphoneEnums.MagicSearchSource.Friends | ((mainItem.searchText.length > 0 && mainItem.searchText != "*") || SettingsCpp.syncLdapContacts ? LinphoneEnums.MagicSearchSource.LdapServers : 0) + onInitialized: { + magicSearchProxy.forceUpdate() + } + } + + Connections { + target: SettingsCpp + onLdapConfigChanged: { + if (SettingsCpp.syncLdapContacts) + magicSearchProxy.forceUpdate() + } } Control.ScrollBar.vertical: ScrollBar { @@ -295,6 +308,7 @@ ListView { textWeight: 400 * DefaultStyle.dp textColor: DefaultStyle.danger_500main contentImageColor: DefaultStyle.danger_500main + visible: !modelData.core.readOnly onClicked: { mainItem.contactDeletionRequested(modelData) friendPopup.close() diff --git a/Linphone/view/Page/Main/Contact/ContactPage.qml b/Linphone/view/Page/Main/Contact/ContactPage.qml index e1ed7078d..b697f7aaf 100644 --- a/Linphone/view/Page/Main/Contact/ContactPage.qml +++ b/Linphone/view/Page/Main/Contact/ContactPage.qml @@ -398,6 +398,7 @@ AbstractMainPage { background: Item{} onClicked: mainItem.editContact(mainItem.selectedContact) icon.source: AppIcons.pencil + visible: !mainItem.selectedContact.core.readOnly } detailContent: ColumnLayout { Layout.fillWidth: false @@ -694,6 +695,7 @@ AbstractMainPage { iconSource: AppIcons.pencil text: qsTr("Edit") onClicked: mainItem.editContact(mainItem.selectedContact) + visible: !mainItem.selectedContact.core.readOnly } Rectangle { Layout.fillWidth: true @@ -788,6 +790,7 @@ AbstractMainPage { iconSource: AppIcons.trashCan color: DefaultStyle.danger_500main text: qsTr("Delete this contact") + visible: !mainItem.selectedContact.core.readOnly onClicked: { mainItem.deleteContact(contact) }