diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d7c51ca6c53b4abd999c0a5615c36c5606aca08..40437fd5c280e0eb399106ffb6d97192dec27c75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -343,6 +343,7 @@ SET( libringclient_LIB_SRCS src/authority/databasehelper.cpp src/lrc.cpp src/newaccountmodel.cpp + src/peerdiscoverymodel.cpp src/callbackshandler.cpp src/behaviorcontroller.cpp src/datatransfermodel.cpp @@ -483,6 +484,7 @@ SET(libringclient_api_LIB_HDRS src/api/lrc.h src/api/avmodel.h src/api/newaccountmodel.h + src/api/peerdiscoverymodel.h src/api/newcallmodel.h src/api/newcodecmodel.h src/api/newdevicemodel.h diff --git a/src/api/account.h b/src/api/account.h index 8d353d19349a38cf2688bc82dd2641553dd63264..6f9ecfe36b588b5dc6c4bee5957dd1ad7b49094d 100644 --- a/src/api/account.h +++ b/src/api/account.h @@ -40,6 +40,7 @@ class NewCallModel; class NewAccountModel; class NewDeviceModel; class NewCodecModel; +class PeerDiscoveryModel; namespace account { @@ -225,6 +226,7 @@ struct Info std::unique_ptr<lrc::api::NewCallModel> callModel; std::unique_ptr<lrc::api::NewDeviceModel> deviceModel; std::unique_ptr<lrc::api::NewCodecModel> codecModel; + std::unique_ptr<lrc::api::PeerDiscoveryModel> peerDiscoveryModel; NewAccountModel* accountModel {nullptr}; // daemon config diff --git a/src/api/peerdiscoverymodel.h b/src/api/peerdiscoverymodel.h new file mode 100644 index 0000000000000000000000000000000000000000..5112629e942e061de5360e7f1081e45a8c52eca8 --- /dev/null +++ b/src/api/peerdiscoverymodel.h @@ -0,0 +1,81 @@ +/**************************************************************************** + * Copyright (C) 2019 Savoir-faire Linux Inc. * + * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library 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 * + * Lesser 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/>. * + ***************************************************************************/ + +#pragma once + +// std +#include <vector> +#include <map> +#include <memory> +#include <string> + +// Qt +#include <qobject.h> + +// Lrc +#include "typedefs.h" + +namespace lrc +{ + +class CallbacksHandler; +class PeerDiscoveryModelPimpl; + +namespace api +{ + +struct PeerContact +{ + std::string uri; + std::string displayName; +}; + +enum class PeerModelChanged +{ + INSERT, + REMOVE +}; + + +/** + * @brief Class that manages local peer discovery info + */ +class LIB_EXPORT PeerDiscoveryModel : public QObject { + Q_OBJECT +public: + + PeerDiscoveryModel(const CallbacksHandler& callbackHandler, const std::string& accountID); + ~PeerDiscoveryModel(); + /** + * get a map of discovered peers account + * @return a std::vector<PeerContact> + */ + std::vector<PeerContact> getNearbyPeers() const; + +Q_SIGNALS: + /** + * Connect this signal to know when the status of local peer discovery map changed. + */ + void modelChanged(const std::string& contactUri, PeerModelChanged state, const std::string& displayname); + +private: + std::unique_ptr<PeerDiscoveryModelPimpl> pimpl_; +}; + +} // namespace api +} // namespace lrc diff --git a/src/callbackshandler.cpp b/src/callbackshandler.cpp index dad2607e865669fb4f384e9855c4bbd6d8cd99e0..283d54e33804afd14d2b36ac402053e2d9c97258 100644 --- a/src/callbackshandler.cpp +++ b/src/callbackshandler.cpp @@ -64,6 +64,12 @@ CallbacksHandler::CallbacksHandler(const Lrc& parent) &CallbacksHandler::slotNewBuddySubscription, Qt::QueuedConnection); + connect(&PresenceManager::instance(), + &PresenceManagerInterface::nearbyPeerNotification, + this, + &CallbacksHandler::slotNearbyPeerSubscription, + Qt::QueuedConnection); + connect(&ConfigurationManager::instance(), &ConfigurationManagerInterface::contactAdded, this, @@ -248,6 +254,15 @@ CallbacksHandler::slotNewBuddySubscription(const QString& accountId, emit newBuddySubscription(uri.toStdString(), status); } +void +CallbacksHandler::slotNearbyPeerSubscription(const QString& accountId, + const QString& contactUri, + int state, + const QString& displayname) +{ + emit newPeerSubscription(accountId.toStdString(), contactUri.toStdString(), state, displayname.toStdString()); +} + void CallbacksHandler::slotContactAdded(const QString& accountId, const QString& contactUri, diff --git a/src/callbackshandler.h b/src/callbackshandler.h index 098e7b9af70f9fc479ff9b4b0b932d2da1d40a96..31409cf187f9f078d2fd31113843781861a66852 100644 --- a/src/callbackshandler.h +++ b/src/callbackshandler.h @@ -68,6 +68,12 @@ Q_SIGNALS: * @param present if the peer is online. */ void newBuddySubscription(const std::string& contactUri, bool present); + /** + * Connect this signal to get information when peer discovery changes. + * @param contactUri the peer. + * @param state is 0 if the peer is added. + */ + void newPeerSubscription(const std::string& accountId, const std::string& contactUri, int state, const std::string& displayname); /** * Connect this signal to know when a contact is removed by the daemon. * @param accountId the one who lost a contact. @@ -467,6 +473,18 @@ private Q_SLOTS: */ void slotAudioMeterReceived(const QString& id, float level); + /** + * Emit newPeerSubscription + * @param accountId + * @param contactUri + * @param status if the peer is added or removed + * @param displayname is the account display name + */ + void slotNearbyPeerSubscription(const QString& accountId, + const QString& contactUri, + int state, + const QString& displayname); + private: const api::Lrc& parent; }; diff --git a/src/newaccountmodel.cpp b/src/newaccountmodel.cpp index c12703f56dbcfad1ea621f3060b73a2e4b1f75eb..887d613b9d174d6cc492d25e10987d09b219d9e1 100644 --- a/src/newaccountmodel.cpp +++ b/src/newaccountmodel.cpp @@ -31,6 +31,7 @@ #include "api/lrc.h" #include "api/contactmodel.h" #include "api/conversationmodel.h" +#include "api/peerdiscoverymodel.h" #include "api/newcallmodel.h" #include "api/newcodecmodel.h" #include "api/newdevicemodel.h" @@ -582,6 +583,7 @@ NewAccountModelPimpl::addToAccounts(const std::string& accountId) newAcc.callModel = std::make_unique<NewCallModel>(newAcc, callbacksHandler); newAcc.contactModel = std::make_unique<ContactModel>(newAcc, database, callbacksHandler, behaviorController); newAcc.conversationModel = std::make_unique<ConversationModel>(newAcc, lrc, database, callbacksHandler, behaviorController); + newAcc.peerDiscoveryModel = std::make_unique<PeerDiscoveryModel>(callbacksHandler, accountId); newAcc.deviceModel = std::make_unique<NewDeviceModel>(newAcc, callbacksHandler); newAcc.codecModel = std::make_unique<NewCodecModel>(newAcc, callbacksHandler); newAcc.accountModel = &linked; diff --git a/src/peerdiscoverymodel.cpp b/src/peerdiscoverymodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..759edc89e836e0f414976dd7e249fd4f30c2251c --- /dev/null +++ b/src/peerdiscoverymodel.cpp @@ -0,0 +1,107 @@ +/**************************************************************************** + * Copyright (C) 2019 Savoir-faire Linux Inc. * + * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library 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 * + * Lesser 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 "api/peerdiscoverymodel.h" + +// new LRC +#include "callbackshandler.h" + +// Dbus +#include "dbus/configurationmanager.h" + +namespace lrc +{ + +using namespace api; + +class PeerDiscoveryModelPimpl: public QObject +{ + Q_OBJECT +public: + PeerDiscoveryModelPimpl(PeerDiscoveryModel& linked, + const CallbacksHandler& callbackHandler, + const std::string& accountID); + ~PeerDiscoveryModelPimpl(); + + PeerDiscoveryModel& linked_; + const CallbacksHandler& callbacksHandler_; + const std::string accountID_; + +public Q_SLOTS: + + /** + * Emit peerMapStatusChanged. + * @param accountId + * @param status + */ + void slotPeerMapStatusChanged(const std::string& accountID, const std::string& contactUri, int state, const std::string& displayname); +}; + +PeerDiscoveryModel::PeerDiscoveryModel(const CallbacksHandler& callbacksHandler, const std::string& accountID) +: QObject() +, pimpl_(std::make_unique<PeerDiscoveryModelPimpl>(*this, callbacksHandler, accountID)) +{ +} + +PeerDiscoveryModel::~PeerDiscoveryModel() +{ +} + +PeerDiscoveryModelPimpl::PeerDiscoveryModelPimpl(PeerDiscoveryModel& linked, + const CallbacksHandler& callbacksHandler, + const std::string& accountID) +: linked_(linked) +, callbacksHandler_(callbacksHandler) +, accountID_(accountID) +{ + connect(&callbacksHandler_, &CallbacksHandler::newPeerSubscription, this, &PeerDiscoveryModelPimpl::slotPeerMapStatusChanged); +} + +PeerDiscoveryModelPimpl::~PeerDiscoveryModelPimpl() +{ + disconnect(&callbacksHandler_, &CallbacksHandler::newPeerSubscription, this, &PeerDiscoveryModelPimpl::slotPeerMapStatusChanged); +} + +void +PeerDiscoveryModelPimpl::slotPeerMapStatusChanged(const std::string& accountID, const std::string& contactUri, int state, const std::string& displayname) +{ + if(accountID != accountID_){ + return; + } + emit linked_.modelChanged(contactUri,state == 0 ? PeerModelChanged::INSERT : PeerModelChanged::REMOVE,displayname); + +} + +std::vector<PeerContact> +PeerDiscoveryModel::getNearbyPeers() const +{ + std::vector<PeerContact> result; + const MapStringString nearbyPeers = ConfigurationManager::instance().getNearbyPeers(QString::fromStdString(pimpl_->accountID_)); + result.reserve(nearbyPeers.size()); + + QMap<QString, QString>::const_iterator i = nearbyPeers.constBegin(); + while (i != nearbyPeers.constEnd()) { + result.emplace_back(PeerContact{i.key().toStdString(), i.value().toStdString()}); + ++i; + } + return result; +} + +} // namespace lrc + +#include "api/moc_peerdiscoverymodel.cpp" +#include "peerdiscoverymodel.moc" diff --git a/src/qtwrapper/configurationmanager_wrap.h b/src/qtwrapper/configurationmanager_wrap.h index 703bc068ebbb6d2323af62943cb67e88447fd372..49bfb04675c9c045541b5779a46a04e6d3bfd4a4 100644 --- a/src/qtwrapper/configurationmanager_wrap.h +++ b/src/qtwrapper/configurationmanager_wrap.h @@ -621,6 +621,10 @@ public Q_SLOTS: // METHODS return DRing::getMessageStatus(id); } + MapStringString getNearbyPeers(const QString &accountID){ + return convertMap(DRing::getNearbyPeers(accountID.toStdString())); + } + void connectivityChanged() { DRing::connectivityChanged(); } diff --git a/src/qtwrapper/presencemanager_wrap.h b/src/qtwrapper/presencemanager_wrap.h index f1019a7478272d4aaa030d6cbdf30245fe002bf2..1ca89e731afd2c5bb3f895cd1b3e43bae8f7561d 100644 --- a/src/qtwrapper/presencemanager_wrap.h +++ b/src/qtwrapper/presencemanager_wrap.h @@ -63,6 +63,10 @@ public: exportable_callback<PresenceSignal::SubscriptionStateChanged>( [this] (const std::string &accountID, const std::string &buddyUri, bool state) { Q_EMIT this->subscriptionStateChanged(QString(accountID.c_str()), QString(buddyUri.c_str()), state); + }), + exportable_callback<PresenceSignal::NearbyPeerNotification>( + [this] (const std::string &accountID, const std::string &buddyUri, int status, const std::string &displayname) { + Q_EMIT this->nearbyPeerNotification(QString(accountID.c_str()), QString(buddyUri.c_str()), status, QString(displayname.c_str())); }) }; } @@ -100,6 +104,7 @@ public Q_SLOTS: // METHODS } Q_SIGNALS: // SIGNALS + void nearbyPeerNotification(const QString &accountID, const QString &buddyUri, int status, const QString &displayname); void newServerSubscriptionRequest(const QString &buddyUri); void serverError(const QString &accountID, const QString &error, const QString &msg); void newBuddyNotification(const QString &accountID, const QString &buddyUri, bool status, const QString &lineStatus); diff --git a/test/mocks/presencemanager_mock.h b/test/mocks/presencemanager_mock.h index facd091943eace61e7b892a20dcb186ff04116bf..4d6e2c98419bb3e38966dcdc0e60e8ca5685171f 100644 --- a/test/mocks/presencemanager_mock.h +++ b/test/mocks/presencemanager_mock.h @@ -52,6 +52,10 @@ public: { emit newBuddyNotification(accountID, buddyUri, status, lineStatus); } + void emitNearbyPeerNotification(const QString &accountID, const QString &buddyUri, int status, const QString &displayname) + { + emit nearbyPeerNotification(accountID, buddyUri, status, displayname); + } public Q_SLOTS: // METHODS void answerServerRequest(const QString &uri, bool flag) @@ -91,6 +95,7 @@ Q_SIGNALS: // SIGNALS void newServerSubscriptionRequest(const QString &buddyUri); void serverError(const QString &accountID, const QString &error, const QString &msg); void newBuddyNotification(const QString &accountID, const QString &buddyUri, bool status, const QString &lineStatus); + void nearbyPeerNotification(const QString &accountID, const QString &buddyUri, int status, const QString &displayname); void subscriptionStateChanged(const QString &accountID, const QString &buddyUri, bool state); };