From 9f4af14662b524303a6710906f3daa91e47bc1ab Mon Sep 17 00:00:00 2001 From: gaelle Date: Fri, 11 Apr 2025 14:21:25 +0200 Subject: [PATCH] add friends manager --- Linphone/model/CMakeLists.txt | 3 +- Linphone/model/friend/FriendsManager.cpp | 118 +++++++++++++ Linphone/model/friend/FriendsManager.hpp | 67 ++++++++ Linphone/model/search/MagicSearchModel.cpp | 10 ++ Linphone/model/tool/ToolModel.cpp | 22 +++ Linphone/view/Page/Form/Call/NewCallForm.qml | 164 +++++++++---------- 6 files changed, 297 insertions(+), 87 deletions(-) create mode 100644 Linphone/model/friend/FriendsManager.cpp create mode 100644 Linphone/model/friend/FriendsManager.hpp diff --git a/Linphone/model/CMakeLists.txt b/Linphone/model/CMakeLists.txt index f09f9486a..b7d394a30 100644 --- a/Linphone/model/CMakeLists.txt +++ b/Linphone/model/CMakeLists.txt @@ -22,7 +22,8 @@ list(APPEND _LINPHONEAPP_SOURCES model/core/CoreModel.cpp model/friend/FriendModel.cpp - + model/friend/FriendsManager.cpp + model/listener/Listener.hpp model/logger/LoggerModel.cpp diff --git a/Linphone/model/friend/FriendsManager.cpp b/Linphone/model/friend/FriendsManager.cpp new file mode 100644 index 000000000..b36a77aa3 --- /dev/null +++ b/Linphone/model/friend/FriendsManager.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2010-2024 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "FriendsManager.hpp" + +#include "model/core/CoreModel.hpp" +#include "tool/Utils.hpp" +#include +#include + +DEFINE_ABSTRACT_OBJECT(FriendsManager) + +std::shared_ptr FriendsManager::gFriendsManager; +FriendsManager::FriendsManager(QObject *parent) : QObject(parent) { + moveToThread(CoreModel::getInstance()->thread()); +} + +FriendsManager::~FriendsManager() { +} + +std::shared_ptr FriendsManager::create(QObject *parent) { + auto model = std::make_shared(parent); + return model; +} + +std::shared_ptr FriendsManager::getInstance() { + if (!gFriendsManager) gFriendsManager = FriendsManager::create(nullptr); + return gFriendsManager; +} + +QVariantMap FriendsManager::getKnownFriends() const { + return mKnownFriends; +} + +QVariantMap FriendsManager::getUnknownFriends() const { + return mUnknownFriends; +} + +QStringList FriendsManager::getOtherAddresses() const { + return mOtherAddresses; +} + +std::shared_ptr FriendsManager::getKnownFriendAtKey(const QString& key) { + if (isInKnownFriends(key)) { + return mKnownFriends.value(key).value>(); + } else return nullptr; +} + +std::shared_ptr FriendsManager::getUnknownFriendAtKey(const QString& key) { + if (isInUnknownFriends(key)) { + return mUnknownFriends.value(key).value>(); + } else return nullptr; +} + +bool FriendsManager::isInKnownFriends(const QString& key) { + return mKnownFriends.contains(key); +} + +bool FriendsManager::isInUnknownFriends(const QString& key) { + return mUnknownFriends.contains(key); +} + +bool FriendsManager::isInOtherAddresses(const QString& key) { + return mOtherAddresses.contains(key); +} + +void FriendsManager::appendKnownFriend(std::shared_ptr address, std::shared_ptr f) { + auto key = Utils::coreStringToAppString(address->asStringUriOnly()); + if (mKnownFriends.contains(key)) { + qDebug() << "friend is already in konwn list, return"; + return; + } + mKnownFriends.insert(key, QVariant::fromValue(f)); +} + + +void FriendsManager::appendUnknownFriend(std::shared_ptr address, std::shared_ptr f) { + auto key = Utils::coreStringToAppString(address->asStringUriOnly()); + if (mUnknownFriends.contains(key)) { + qDebug() << "friend is already in unkonwn list, return"; + return; + } + mUnknownFriends.insert(key, QVariant::fromValue(f)); +} + + +void FriendsManager::appendOtherAddress(QString address) { + if (mOtherAddresses.contains(address)) { + qDebug() << "friend is already in other addresses, return"; + return; + } + mOtherAddresses.append(address); +} + +void FriendsManager::removeUnknownFriend(const QString& key) { + mUnknownFriends.remove(key); +} + +void FriendsManager::removeOtherAddress(const QString& key) { + mOtherAddresses.removeAll(key); +} diff --git a/Linphone/model/friend/FriendsManager.hpp b/Linphone/model/friend/FriendsManager.hpp new file mode 100644 index 000000000..c2656288d --- /dev/null +++ b/Linphone/model/friend/FriendsManager.hpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2010-2024 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 . + */ + +#ifndef FRIENDS_MANAGER_H_ +#define FRIENDS_MANAGER_H_ + +#include +#include +#include +#include +#include +#include "tool/AbstractObject.hpp" + +class FriendsManager : public QObject, public AbstractObject { + Q_OBJECT + +public: + FriendsManager(QObject *parent); + ~FriendsManager(); + static std::shared_ptr create(QObject *parent); + static std::shared_ptr getInstance(); + + QVariantMap getKnownFriends() const; + QVariantMap getUnknownFriends() const; + QStringList getOtherAddresses() const; + + std::shared_ptr getKnownFriendAtKey(const QString& key); + std::shared_ptr getUnknownFriendAtKey(const QString& key); + + bool isInKnownFriends(const QString& key); + bool isInUnknownFriends(const QString& key); + bool isInOtherAddresses(const QString& key); + + void appendKnownFriend(std::shared_ptr address, std::shared_ptr f); + void appendUnknownFriend(std::shared_ptr address, std::shared_ptr f); + void appendOtherAddress(QString address); + + void removeUnknownFriend(const QString& key); + void removeOtherAddress(const QString& key); + +private: + static std::shared_ptr gFriendsManager; + QVariantMap mKnownFriends; + QVariantMap mUnknownFriends; + QStringList mOtherAddresses; + //core model connection + reset unknown et other quand friend ajouté, supprimé, updated + DECLARE_ABSTRACT_OBJECT +}; + +#endif diff --git a/Linphone/model/search/MagicSearchModel.cpp b/Linphone/model/search/MagicSearchModel.cpp index cd2f085fe..34ef0ab99 100644 --- a/Linphone/model/search/MagicSearchModel.cpp +++ b/Linphone/model/search/MagicSearchModel.cpp @@ -23,6 +23,7 @@ #include #include "model/core/CoreModel.hpp" +#include "model/friend/FriendsManager.hpp" #include "model/setting/SettingsModel.hpp" #include "model/tool/ToolModel.hpp" #include "tool/Utils.hpp" @@ -83,6 +84,15 @@ void MagicSearchModel::onSearchResultsReceived(const std::shared_ptrgetFriend(); + auto friendsManager = FriendsManager::getInstance(); + if (f) { + qDebug() << "friend exists, append to unknown map"; + auto friendAddress = f->getAddress(); + friendsManager->appendUnknownFriend(friendAddress->clone(), f); + if (friendsManager->isInOtherAddresses(Utils::coreStringToAppString(friendAddress->asStringUriOnly()))) { + friendsManager->removeOtherAddress(Utils::coreStringToAppString(friendAddress->asStringUriOnly())); + } + } auto fList = f ? f->getFriendList() : nullptr; // qDebug() << log().arg("") << (f ? f->getName().c_str() : "NoFriend") << ", " diff --git a/Linphone/model/tool/ToolModel.cpp b/Linphone/model/tool/ToolModel.cpp index 0d830590b..6c5c61044 100644 --- a/Linphone/model/tool/ToolModel.cpp +++ b/Linphone/model/tool/ToolModel.cpp @@ -22,6 +22,7 @@ #include "core/App.hpp" #include "core/path/Paths.hpp" #include "model/core/CoreModel.hpp" +#include "model/friend/FriendsManager.hpp" #include "tool/Utils.hpp" #include #include @@ -126,8 +127,29 @@ std::shared_ptr ToolModel::findFriendByAddress(const QString & } std::shared_ptr ToolModel::findFriendByAddress(std::shared_ptr linphoneAddr) { + auto friendsManager = FriendsManager::getInstance(); + QString key = Utils::coreStringToAppString(linphoneAddr->asStringUriOnly()); + if (friendsManager->isInKnownFriends(key)) { + qDebug() << "Friend have been found in known friend, return it"; + return friendsManager->getKnownFriendAtKey(key); + } else if (friendsManager->isInUnknownFriends(key)) { + qDebug() << "Friend have been found in unknown friend, return it"; + return friendsManager->getUnknownFriendAtKey(key); + } auto f = CoreModel::getInstance()->getCore()->findFriend(linphoneAddr); + if (f) { + if (friendsManager->isInUnknownFriends(key)) { + friendsManager->removeUnknownFriend(key); + } + qDebug() << "found friend, add to known map"; + friendsManager->appendKnownFriend(linphoneAddr, f); + } if (!f) { + if (friendsManager->isInOtherAddresses(key)) { + qDebug() << "A magic search has already be done for this address and nothing was found, return"; + return nullptr; + } + friendsManager->appendOtherAddress(key); qDebug() << "Couldn't find friend" << linphoneAddr->asStringUriOnly() << "in core, use magic search"; CoreModel::getInstance()->searchInMagicSearch(Utils::coreStringToAppString(linphoneAddr->asStringUriOnly()), (int)linphone::MagicSearch::Source::LdapServers diff --git a/Linphone/view/Page/Form/Call/NewCallForm.qml b/Linphone/view/Page/Form/Call/NewCallForm.qml index c8d7dd27a..5844cea31 100644 --- a/Linphone/view/Page/Form/Call/NewCallForm.qml +++ b/Linphone/view/Page/Form/Call/NewCallForm.qml @@ -55,90 +55,82 @@ FocusScope { } } - Control.Control { - id: listLayout - Layout.fillWidth: true - Layout.fillHeight: true - background: Item { - anchors.fill: parent - } - onVisibleChanged: if (!visible) mainItem.numPadPopup.close() - contentItem: ColumnLayout { - spacing: Math.round(38 * DefaultStyle.dp) - SearchBar { - id: searchBar - Layout.alignment: Qt.AlignTop - Layout.fillWidth: true - Layout.rightMargin: Math.round(39 * DefaultStyle.dp) - focus: true - color: mainItem.searchBarColor - borderColor: mainItem.searchBarBorderColor - //: "Rechercher un contact" - placeholderText: qsTr("search_bar_look_for_contact_text") - numericPadPopup: mainItem.numPadPopup - KeyNavigation.down: grouCallButton - } - ColumnLayout { - id: content - spacing: Math.round(32 * DefaultStyle.dp) - Button { - id: grouCallButton - visible: mainItem.groupCallVisible && !SettingsCpp.disableMeetingsFeature - Layout.preferredWidth: Math.round(320 * DefaultStyle.dp) - Layout.preferredHeight: Math.round(44 * DefaultStyle.dp) - padding: 0 - KeyNavigation.up: searchBar - KeyNavigation.down: contactList - onClicked: mainItem.groupCallCreationRequested() - background: Rectangle { - anchors.fill: parent - radius: Math.round(50 * DefaultStyle.dp) - gradient: Gradient { - orientation: Gradient.Horizontal - GradientStop { position: 0.0; color: DefaultStyle.main2_100} - GradientStop { position: 1.0; color: DefaultStyle.grey_0} - } - } - contentItem: RowLayout { - spacing: Math.round(16 * DefaultStyle.dp) - anchors.verticalCenter: parent.verticalCenter - Image { - source: AppIcons.groupCall - Layout.preferredWidth: Math.round(44 * DefaultStyle.dp) - sourceSize.width: Math.round(44 * DefaultStyle.dp) - fillMode: Image.PreserveAspectFit - } - Text { - text: qsTr("call_start_group_call_title") - color: DefaultStyle.grey_1000 - font { - pixelSize: Typography.h4.pixelSize - weight: Typography.h4.weight - } - } - Item { - Layout.fillWidth: true - } - EffectImage { - imageSource: AppIcons.rightArrow - Layout.preferredWidth: Math.round(24 * DefaultStyle.dp) - Layout.preferredHeight: Math.round(24 * DefaultStyle.dp) - colorizationColor: DefaultStyle.main2_500main - } - } - } - AllContactListView{ - id: contactList - Layout.fillWidth: true - Layout.fillHeight: true - showContactMenu: false - searchBarText: searchBar.text - onContactSelected: (contact) => { - mainItem.contactClicked(contact) - } - } - } - } - } - } + ColumnLayout { + onVisibleChanged: if (!visible) mainItem.numPadPopup.close() + spacing: Math.round(38 * DefaultStyle.dp) + SearchBar { + id: searchBar + Layout.alignment: Qt.AlignTop + Layout.fillWidth: true + Layout.rightMargin: Math.round(39 * DefaultStyle.dp) + focus: true + color: mainItem.searchBarColor + borderColor: mainItem.searchBarBorderColor + //: "Rechercher un contact" + placeholderText: qsTr("search_bar_look_for_contact_text") + numericPadPopup: mainItem.numPadPopup + KeyNavigation.down: grouCallButton + } + ColumnLayout { + id: content + spacing: Math.round(32 * DefaultStyle.dp) + Button { + id: grouCallButton + visible: mainItem.groupCallVisible && !SettingsCpp.disableMeetingsFeature + Layout.preferredWidth: Math.round(320 * DefaultStyle.dp) + Layout.preferredHeight: Math.round(44 * DefaultStyle.dp) + padding: 0 + KeyNavigation.up: searchBar + KeyNavigation.down: contactList + onClicked: mainItem.groupCallCreationRequested() + background: Rectangle { + anchors.fill: parent + radius: Math.round(50 * DefaultStyle.dp) + gradient: Gradient { + orientation: Gradient.Horizontal + GradientStop { position: 0.0; color: DefaultStyle.main2_100} + GradientStop { position: 1.0; color: DefaultStyle.grey_0} + } + } + contentItem: RowLayout { + spacing: Math.round(16 * DefaultStyle.dp) + anchors.verticalCenter: parent.verticalCenter + Image { + source: AppIcons.groupCall + Layout.preferredWidth: Math.round(44 * DefaultStyle.dp) + sourceSize.width: Math.round(44 * DefaultStyle.dp) + fillMode: Image.PreserveAspectFit + } + Text { + text: qsTr("call_start_group_call_title") + color: DefaultStyle.grey_1000 + font { + pixelSize: Typography.h4.pixelSize + weight: Typography.h4.weight + } + } + Item { + Layout.fillWidth: true + } + EffectImage { + imageSource: AppIcons.rightArrow + Layout.preferredWidth: Math.round(24 * DefaultStyle.dp) + Layout.preferredHeight: Math.round(24 * DefaultStyle.dp) + colorizationColor: DefaultStyle.main2_500main + } + } + } + AllContactListView{ + id: contactList + Layout.fillWidth: true + Layout.fillHeight: true + showContactMenu: false + searchBarText: searchBar.text + onContactSelected: (contact) => { + mainItem.contactClicked(contact) + } + } + } + } + } }