Change contacts list to take account of all contacts in database (multiple lists, bodyless, remote provision)

This commit is contained in:
Julien Wadel 2022-11-02 11:00:28 +01:00
parent 04f3997fd9
commit ced6a8b396
10 changed files with 187 additions and 33 deletions

View file

@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- New call layouts.
- Display a waiting room before going into a conference.
- Log viewer.
- Read contacts from all friends lists.
- Option to set the display name in "using an account" tab of assistant.
- Long pressed buttons.
- Phone dialpad on main window.

View file

@ -204,6 +204,7 @@ set(SOURCES
src/components/core/event-count-notifier/AbstractEventCountNotifier.cpp
src/components/file/FileDownloader.cpp
src/components/file/FileExtractor.cpp
src/components/friend/FriendListListener.cpp
src/components/history/HistoryModel.cpp
src/components/history/HistoryProxyModel.cpp
src/components/ldap/LdapModel.cpp
@ -338,6 +339,7 @@ set(HEADERS
src/components/core/event-count-notifier/AbstractEventCountNotifier.hpp
src/components/file/FileDownloader.hpp
src/components/file/FileExtractor.hpp
src/components/friend/FriendListListener.hpp
src/components/history/HistoryModel.hpp
src/components/history/HistoryProxyModel.hpp
src/components/ldap/LdapModel.hpp

View file

@ -215,3 +215,7 @@ Presence::PresenceLevel ContactModel::getPresenceLevel () const {
bool ContactModel::hasCapability(const LinphoneEnums::FriendCapability& capability){
return mLinphoneFriend->hasCapability(LinphoneEnums::toLinphone(capability));
}
std::shared_ptr<linphone::Friend> ContactModel::getFriend() const{
return mLinphoneFriend;
}

View file

@ -57,6 +57,8 @@ public:
Q_INVOKABLE VcardModel *cloneVcardModel () const;
Presence::PresenceLevel getPresenceLevel () const;
Q_INVOKABLE bool hasCapability(const LinphoneEnums::FriendCapability& capability);
std::shared_ptr<linphone::Friend> getFriend() const;
signals:
void contactUpdated ();

View file

@ -24,40 +24,26 @@
#include "components/contact/ContactModel.hpp"
#include "components/contact/VcardModel.hpp"
#include "components/core/CoreManager.hpp"
#include "components/friend/FriendListListener.hpp"
#include "ContactsListModel.hpp"
// =============================================================================
void ContactsListModel::connectTo(FriendListListener * listener){
connect(listener, &FriendListListener::contactCreated, this, &ContactsListModel::onContactCreated);
connect(listener, &FriendListListener::contactDeleted, this, &ContactsListModel::onContactDeleted);
connect(listener, &FriendListListener::contactUpdated, this, &ContactsListModel::onContactUpdated);
connect(listener, &FriendListListener::syncStatusChanged, this, &ContactsListModel::onSyncStatusChanged);
connect(listener, &FriendListListener::presenceReceived, this, &ContactsListModel::onPresenceReceived);
}
// =============================================================================
using namespace std;
ContactsListModel::ContactsListModel (QObject *parent) : ProxyListModel(parent) {
mLinphoneFriends = CoreManager::getInstance()->getCore()->getFriendsLists().front();
// Clean friends.
{
list<shared_ptr<linphone::Friend>> toRemove;
for (const auto &linphoneFriend : mLinphoneFriends->getFriends()) {
if (!linphoneFriend->getVcard())
toRemove.push_back(linphoneFriend);
}
for (const auto &linphoneFriend : toRemove) {
qWarning() << QStringLiteral("Remove one friend without vcard.");
mLinphoneFriends->removeFriend(linphoneFriend);
}
}
// Init contacts with linphone friends list.
QQmlEngine *engine = App::getInstance()->getEngine();
for (const auto &linphoneFriend : mLinphoneFriends->getFriends()) {
auto contact = QSharedPointer<ContactModel>::create(linphoneFriend);
// See: http://doc.qt.io/qt-5/qtqml-cppintegration-data.html#data-ownership
// The returned value must have a explicit parent or a QQmlEngine::CppOwnership.
engine->setObjectOwnership(contact.get(), QQmlEngine::CppOwnership);
addContact(contact);
}
mFriendListListener = std::make_shared<FriendListListener>();
connectTo(mFriendListListener.get());
update();
}
ContactsListModel::~ContactsListModel(){
@ -65,7 +51,7 @@ ContactsListModel::~ContactsListModel(){
beginResetModel();
mOptimizedSearch.clear();
mList.clear();
mLinphoneFriends = nullptr;
mLinphoneFriends.clear();
endResetModel();
}
}
@ -84,7 +70,8 @@ bool ContactsListModel::removeRows (int row, int count, const QModelIndex &paren
mOptimizedSearch.remove(address.toString());
}
mLinphoneFriends->removeFriend(contact->mLinphoneFriend);
for(auto l : mLinphoneFriends)
l->removeFriend(contact->mLinphoneFriend);
emit contactRemoved(contact);
}
@ -123,7 +110,7 @@ ContactModel *ContactsListModel::addContact (VcardModel *vcardModel) {
contact = QSharedPointer<ContactModel>::create(vcardModel);
App::getInstance()->getEngine()->setObjectOwnership(contact.get(), QQmlEngine::CppOwnership);
if (mLinphoneFriends->addFriend(contact->mLinphoneFriend) != linphone::FriendList::Status::OK) {
if (mLinphoneFriends.front()->addFriend(contact->mLinphoneFriend) != linphone::FriendList::Status::OK) {
qWarning() << QStringLiteral("Unable to add contact from vcard:") << vcardModel;
return nullptr;
}
@ -131,9 +118,8 @@ ContactModel *ContactsListModel::addContact (VcardModel *vcardModel) {
qInfo() << QStringLiteral("Add contact from vcard:") << contact.get() << vcardModel;
// Make sure new subscribe is issued.
mLinphoneFriends->updateSubscriptions();
mLinphoneFriends.front()->updateSubscriptions();
addContact(contact);
emit layoutChanged();
emit contactAdded(contact);
@ -177,3 +163,47 @@ void ContactsListModel::addContact (QSharedPointer<ContactModel> contact) {
mOptimizedSearch[address.toString()] = contact;
}
}
void ContactsListModel::update(){
beginResetModel();
for(auto l : mLinphoneFriends)
l->removeListener(mFriendListListener);
mLinphoneFriends.clear();
mOptimizedSearch.clear();
mList.clear();
endResetModel();
mLinphoneFriends = CoreManager::getInstance()->getCore()->getFriendsLists();
for(auto l : mLinphoneFriends){
l->addListener(mFriendListListener);
for (const auto &linphoneFriend : l->getFriends()) {
onContactCreated(linphoneFriend);
}
}
}
//------------------------------------------------------------------------------------------------
void ContactsListModel::onContactCreated(const std::shared_ptr<linphone::Friend> & linphoneFriend){
QQmlEngine *engine = App::getInstance()->getEngine();
auto haveContact = std::find_if(mList.begin(), mList.end(), [linphoneFriend] (const QSharedPointer<QObject>& item){
return item.objectCast<ContactModel>()->getFriend() == linphoneFriend;
});
if(haveContact == mList.end()) {
auto contact = QSharedPointer<ContactModel>::create(linphoneFriend);
// See: http://doc.qt.io/qt-5/qtqml-cppintegration-data.html#data-ownership
// The returned value must have a explicit parent or a QQmlEngine::CppOwnership.
engine->setObjectOwnership(contact.get(), QQmlEngine::CppOwnership);
addContact(contact);
}
}
void ContactsListModel::onContactDeleted(const std::shared_ptr<linphone::Friend> & linphoneFriend){
}
void ContactsListModel::onContactUpdated(const std::shared_ptr<linphone::Friend> & newFriend, const std::shared_ptr<linphone::Friend> & oldFriend){
}
void ContactsListModel::onSyncStatusChanged(linphone::FriendList::SyncStatus status, const std::string & message){
}
void ContactsListModel::onPresenceReceived(const std::list<std::shared_ptr<linphone::Friend>> & friends){
}

View file

@ -33,6 +33,7 @@ namespace linphone {
class ContactModel;
class VcardModel;
class FriendListListener;
class ContactsListModel : public ProxyListModel {
friend class SipAddressesModel;
@ -52,6 +53,16 @@ public:
Q_INVOKABLE void removeContact (ContactModel *contact);
Q_INVOKABLE void cleanAvatars ();
Q_INVOKABLE void update ();
void connectTo(FriendListListener * listener);
public slots:
void onContactCreated(const std::shared_ptr<linphone::Friend> & linphoneFriend);
void onContactDeleted(const std::shared_ptr<linphone::Friend> & linphoneFriend);
void onContactUpdated(const std::shared_ptr<linphone::Friend> & newFriend, const std::shared_ptr<linphone::Friend> & oldFriend);
void onSyncStatusChanged(linphone::FriendList::SyncStatus status, const std::string & message);
void onPresenceReceived(const std::list<std::shared_ptr<linphone::Friend>> & friends);
signals:
void contactAdded (QSharedPointer<ContactModel>);
@ -65,7 +76,8 @@ private:
void addContact (QSharedPointer<ContactModel> contact);
QMap<QString, QSharedPointer<ContactModel>> mOptimizedSearch;
std::shared_ptr<linphone::FriendList> mLinphoneFriends;
std::list<std::shared_ptr<linphone::FriendList>> mLinphoneFriends;
std::shared_ptr<FriendListListener> mFriendListListener;
};
#endif // CONTACTS_LIST_MODEL_H_

View file

@ -260,6 +260,7 @@ void CoreManager::createLinphoneCore (const QString &configPath) {
Paths::getFactoryConfigFilePath(),
nullptr
);
setDatabasesPaths();
// Enable LIME on your core to use encryption.
mCore->enableLimeX3Dh(mCore->limeX3DhAvailable());
// Now see the CoreService.CreateGroupChatRoom to see how to create a secure chat room
@ -279,7 +280,6 @@ void CoreManager::createLinphoneCore (const QString &configPath) {
QString userAgent = Utils::computeUserAgent(config);
mCore->setUserAgent(Utils::appStringToCoreString(userAgent), mCore->getVersion());
mCore->start();
setDatabasesPaths();
setOtherPaths();
mCore->enableFriendListSubscription(true);
mCore->enableRecordAware(true);

View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 2022 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 "FriendListListener.hpp"
#include "../../utils/Utils.hpp"
#include <QDebug>
// =============================================================================
FriendListListener::FriendListListener(QObject *parent) : QObject(parent) {
}
//--------------------------------------------------------------------
void FriendListListener::onContactCreated(const std::shared_ptr<linphone::FriendList> & friendList, const std::shared_ptr<linphone::Friend> & linphoneFriend) {
qDebug() << "onContactCreated: " << Utils::coreStringToAppString(linphoneFriend->getName());
emit contactCreated(linphoneFriend);
}
void FriendListListener::onContactDeleted(const std::shared_ptr<linphone::FriendList> & friendList, const std::shared_ptr<linphone::Friend> & linphoneFriend) {
qDebug() << "onContactDeleted: " << Utils::coreStringToAppString(linphoneFriend->getName());
emit contactDeleted(linphoneFriend);
}
void FriendListListener::onContactUpdated(const std::shared_ptr<linphone::FriendList> & friendList, const std::shared_ptr<linphone::Friend> & newFriend, const std::shared_ptr<linphone::Friend> & oldFriend) {
qDebug() << "onContactUpdated: " << Utils::coreStringToAppString(newFriend->getName());
emit contactUpdated(newFriend, oldFriend);
}
void FriendListListener::onSyncStatusChanged(const std::shared_ptr<linphone::FriendList> & friendList, linphone::FriendList::SyncStatus status, const std::string & message) {
qDebug() << "onSyncStatusChanged: [" << (int)status<<"] " << Utils::coreStringToAppString(message);
emit syncStatusChanged(status, message);
}
void FriendListListener::onPresenceReceived(const std::shared_ptr<linphone::FriendList> & friendList, const std::list<std::shared_ptr<linphone::Friend>> & friends) {
qDebug() << "onPresenceReceived: " <<friends.size();
emit presenceReceived(friends);
}

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2022 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 FRIEND_LIST_LISTENER_H_
#define FRIEND_LIST_LISTENER_H_
#include <linphone++/linphone.hh>
#include <QObject>
// =============================================================================
class FriendListListener : public QObject, public linphone::FriendListListener {
Q_OBJECT
public:
FriendListListener (QObject *parent = nullptr);
virtual void onContactCreated(const std::shared_ptr<linphone::FriendList> & friendList, const std::shared_ptr<linphone::Friend> & linphoneFriend) override;
virtual void onContactDeleted(const std::shared_ptr<linphone::FriendList> & friendList, const std::shared_ptr<linphone::Friend> & linphoneFriend) override;
virtual void onContactUpdated(const std::shared_ptr<linphone::FriendList> & friendList, const std::shared_ptr<linphone::Friend> & newFriend, const std::shared_ptr<linphone::Friend> & oldFriend) override;
virtual void onSyncStatusChanged(const std::shared_ptr<linphone::FriendList> & friendList, linphone::FriendList::SyncStatus status, const std::string & message) override;
virtual void onPresenceReceived(const std::shared_ptr<linphone::FriendList> & friendList, const std::list<std::shared_ptr<linphone::Friend>> & friends) override;
signals:
void contactCreated(const std::shared_ptr<linphone::Friend> & linphoneFriend);
void contactDeleted(const std::shared_ptr<linphone::Friend> & linphoneFriend);
void contactUpdated(const std::shared_ptr<linphone::Friend> & newFriend, const std::shared_ptr<linphone::Friend> & oldFriend);
void syncStatusChanged(linphone::FriendList::SyncStatus status, const std::string & message);
void presenceReceived(const std::list<std::shared_ptr<linphone::Friend>> & friends);
};
#endif

View file

@ -307,10 +307,12 @@ ApplicationWindow {
visible: SettingsModel.contactsEnabled
onSelected: {
ContactsListModel.update()
timeline.model.unselectAll()
setView('Contacts')
}
onClicked:{
ContactsListModel.update()
setView('Contacts')
}
Icon{