From f181b6d6597c29472fd551050f0f3814f3e537cf Mon Sep 17 00:00:00 2001 From: Ronan Abhamon Date: Tue, 3 Jan 2017 15:43:47 +0100 Subject: [PATCH] feat(app): - supports linphone cbs - handle received messages - `SipAddressesModel` refactoring --- submodules/linphone | 2 +- tests/CMakeLists.txt | 3 + tests/src/app/App.cpp | 2 + tests/src/app/Database.cpp | 12 +++ tests/src/app/Database.hpp | 1 + tests/src/components/core/CoreHandlers.cpp | 34 +++++++ tests/src/components/core/CoreHandlers.hpp | 30 ++++++ tests/src/components/core/CoreManager.cpp | 27 +++++- tests/src/components/core/CoreManager.hpp | 10 +- .../settings/AccountSettingsModel.cpp | 18 +++- .../sip-addresses/SipAddressesModel.cpp | 95 +++++++++++-------- .../sip-addresses/SipAddressesModel.hpp | 15 ++- .../src/components/timeline/TimelineModel.cpp | 5 +- 13 files changed, 202 insertions(+), 52 deletions(-) create mode 100644 tests/src/components/core/CoreHandlers.cpp create mode 100644 tests/src/components/core/CoreHandlers.hpp diff --git a/submodules/linphone b/submodules/linphone index 7650064a1..fb3c9841e 160000 --- a/submodules/linphone +++ b/submodules/linphone @@ -1 +1 @@ -Subproject commit 7650064a1cb5b914b157c788e4ff8fa22d971f78 +Subproject commit fb3c9841ee5142d1826e2674591797343bd728ff diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1083e04c2..bfbde2f4c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -48,6 +48,7 @@ endforeach () list(APPEND LIBS "${CMAKE_SOURCE_DIR}/../OUTPUT/desktop/lib64/liblinphone++.so") list(APPEND LIBS "${CMAKE_SOURCE_DIR}/../OUTPUT/desktop/lib64/libbelcard.so") +list(APPEND LIBS "${CMAKE_SOURCE_DIR}/../OUTPUT/desktop/lib64/libbellesip.so") set(SOURCES src/app/App.cpp @@ -63,6 +64,7 @@ set(SOURCES src/components/contact/VcardModel.cpp src/components/contacts/ContactsListModel.cpp src/components/contacts/ContactsListProxyModel.cpp + src/components/core/CoreHandlers.cpp src/components/core/CoreManager.cpp src/components/notifier/Notifier.cpp src/components/settings/AccountSettingsModel.cpp @@ -87,6 +89,7 @@ set(HEADERS src/components/contact/VcardModel.hpp src/components/contacts/ContactsListModel.hpp src/components/contacts/ContactsListProxyModel.hpp + src/components/core/CoreHandlers.hpp src/components/core/CoreManager.hpp src/components/notifier/Notifier.hpp src/components/presence/Presence.hpp diff --git a/tests/src/app/App.cpp b/tests/src/app/App.cpp index 8d2aa7c71..db8ac49ef 100644 --- a/tests/src/app/App.cpp +++ b/tests/src/app/App.cpp @@ -70,6 +70,8 @@ void App::initContentApp () { registerTypes(); addContextProperties(); + CoreManager::getInstance()->enableHandlers(); + // Load main view. qInfo() << "Loading main view..."; m_engine.load(QUrl(QML_VIEW_MAIN_WINDOW)); diff --git a/tests/src/app/Database.cpp b/tests/src/app/Database.cpp index 40ede28ac..77beaf4f5 100644 --- a/tests/src/app/Database.cpp +++ b/tests/src/app/Database.cpp @@ -6,12 +6,20 @@ #include "Database.hpp" +// ============================================================================= + #ifdef _WIN32 + #define DATABASES_PATH \ QStandardPaths::writableLocation(QStandardPaths::DataLocation) +#define DATABASE_PATH_CONFIG "linphonerc" + #else + #define DATABASES_PATH \ QStandardPaths::writableLocation(QStandardPaths::HomeLocation) +#define DATABASE_PATH_CONFIG ".linphonerc" + #endif // ifdef _WIN32 #define DATABASE_PATH_AVATARS ".linphone/avatars/" @@ -56,6 +64,10 @@ string Database::getCallHistoryPath () { return getDatabaseFilePath(DATABASE_PATH_CALL_HISTORY_LIST); } +string Database::getConfigPath () { + return getDatabaseFilePath(DATABASE_PATH_CONFIG); +} + string Database::getFriendsListPath () { return getDatabaseFilePath(DATABASE_PATH_FRIENDS_LIST); } diff --git a/tests/src/app/Database.hpp b/tests/src/app/Database.hpp index 4e1a75f4d..7ce912540 100644 --- a/tests/src/app/Database.hpp +++ b/tests/src/app/Database.hpp @@ -12,6 +12,7 @@ namespace Database { std::string getAvatarsPath (); std::string getCallHistoryPath (); + std::string getConfigPath (); std::string getFriendsListPath (); std::string getMessageHistoryPath (); } diff --git a/tests/src/components/core/CoreHandlers.cpp b/tests/src/components/core/CoreHandlers.cpp new file mode 100644 index 000000000..7fe32faa6 --- /dev/null +++ b/tests/src/components/core/CoreHandlers.cpp @@ -0,0 +1,34 @@ +#include + +#include "CoreManager.hpp" + +#include "CoreHandlers.hpp" + +using namespace std; + +// ============================================================================= + +void CoreHandlers::onAuthenticationRequested ( + const std::shared_ptr &lc, + const std::shared_ptr &auth_info, + linphone::AuthMethod method +) { + qDebug() << "Auth request"; +} + +void CoreHandlers::onCallStateChanged ( + const shared_ptr &lc, + const shared_ptr &call, + linphone::CallState cstate, + const string &message +) { + qDebug() << "call"; +} + +void CoreHandlers::onMessageReceived ( + const shared_ptr &lc, + const shared_ptr &room, + const shared_ptr &message +) { + CoreManager::getInstance()->getSipAddressesModel()->handleReceivedMessage(room, message); +} diff --git a/tests/src/components/core/CoreHandlers.hpp b/tests/src/components/core/CoreHandlers.hpp new file mode 100644 index 000000000..f8336b4c2 --- /dev/null +++ b/tests/src/components/core/CoreHandlers.hpp @@ -0,0 +1,30 @@ +#ifndef CORE_HANDLERS_H_ +#define CORE_HANDLERS_H_ + +#include + +// ============================================================================= + +class CoreHandlers : public linphone::CoreListener { +public: + void onAuthenticationRequested ( + const std::shared_ptr &lc, + const std::shared_ptr &auth_info, + linphone::AuthMethod method + ) override; + + void onCallStateChanged ( + const std::shared_ptr &lc, + const std::shared_ptr &call, + linphone::CallState cstate, + const std::string &message + ) override; + + void onMessageReceived ( + const std::shared_ptr &lc, + const std::shared_ptr &room, + const std::shared_ptr &message + ) override; +}; + +#endif // CORE_HANDLERS_H_ diff --git a/tests/src/components/core/CoreManager.cpp b/tests/src/components/core/CoreManager.cpp index 55e6f1492..77d639475 100644 --- a/tests/src/components/core/CoreManager.cpp +++ b/tests/src/components/core/CoreManager.cpp @@ -1,4 +1,7 @@ +#include + #include "../../app/Database.hpp" +#include "CoreHandlers.hpp" #include "CoreManager.hpp" @@ -8,17 +11,37 @@ using namespace std; CoreManager *CoreManager::m_instance = nullptr; -CoreManager::CoreManager (QObject *parent) : QObject(parent), - m_core(linphone::Factory::get()->createCore(nullptr, "", "", nullptr)) { +CoreManager::CoreManager (QObject *parent) : QObject(parent), m_handlers(make_shared()) { + string config_path = Database::getConfigPath(); + if (config_path.length() == 0) + qFatal("Unable to get config path."); + m_core = linphone::Factory::get()->createCore(m_handlers, config_path, ""); setDatabasesPaths(); } +CoreManager::~CoreManager () { + delete m_cbs_timer; +} + +void CoreManager::enableHandlers () { + m_cbs_timer->start(); +} + void CoreManager::init () { if (!m_instance) { m_instance = new CoreManager(); m_instance->m_contacts_list_model = new ContactsListModel(m_instance); m_instance->m_sip_addresses_model = new SipAddressesModel(m_instance); + + QTimer *timer = m_instance->m_cbs_timer = new QTimer(m_instance); + timer->setInterval(20); + + QObject::connect( + timer, &QTimer::timeout, m_instance, []() { + m_instance->m_core->iterate(); + } + ); } } diff --git a/tests/src/components/core/CoreManager.hpp b/tests/src/components/core/CoreManager.hpp index dcc4867d7..5f12389f6 100644 --- a/tests/src/components/core/CoreManager.hpp +++ b/tests/src/components/core/CoreManager.hpp @@ -6,11 +6,13 @@ // ============================================================================= +class QTimer; + class CoreManager : public QObject { Q_OBJECT; public: - ~CoreManager () = default; + ~CoreManager (); std::shared_ptr getCore () { return m_core; @@ -28,6 +30,8 @@ public: return m_sip_addresses_model; } + void enableHandlers (); + static void init (); static CoreManager *getInstance () { @@ -44,9 +48,13 @@ private: void setDatabasesPaths (); std::shared_ptr m_core; + std::shared_ptr m_handlers; + ContactsListModel *m_contacts_list_model; SipAddressesModel *m_sip_addresses_model; + QTimer *m_cbs_timer; + static CoreManager *m_instance; }; diff --git a/tests/src/components/settings/AccountSettingsModel.cpp b/tests/src/components/settings/AccountSettingsModel.cpp index 650b96ea2..746f922b7 100644 --- a/tests/src/components/settings/AccountSettingsModel.cpp +++ b/tests/src/components/settings/AccountSettingsModel.cpp @@ -3,8 +3,7 @@ // =================================================================== AccountSettingsModel::AccountSettingsModel (QObject *parent) : - QObject(parent) { -} + QObject(parent) {} QString AccountSettingsModel::getUsername () const { return "Edward Miller "; @@ -12,7 +11,7 @@ QString AccountSettingsModel::getUsername () const { void AccountSettingsModel::setUsername (const QString &username) { // NOTHING TODO. - (void)username; + (void) username; } Presence::PresenceLevel AccountSettingsModel::getPresenceLevel () const { @@ -30,3 +29,16 @@ QString AccountSettingsModel::getSipAddress () const { bool AccountSettingsModel::getAutoAnswerStatus () const { return true; } + +// TODO: TMP +/* + shared_ptr cfg = m_core->getDefaultProxyConfig(); + shared_ptr address = cfg->getIdentityAddress(); + shared_ptr auth_info = m_core->findAuthInfo("", address->getUsername(), cfg->getDomain()); + + if (auth_info) + qDebug() << "OK"; + else + qDebug() << "FAIL"; + + */ diff --git a/tests/src/components/sip-addresses/SipAddressesModel.cpp b/tests/src/components/sip-addresses/SipAddressesModel.cpp index 2dfae1f8c..31d8a6670 100644 --- a/tests/src/components/sip-addresses/SipAddressesModel.cpp +++ b/tests/src/components/sip-addresses/SipAddressesModel.cpp @@ -8,20 +8,16 @@ #include "SipAddressesModel.hpp" +using namespace std; + // ============================================================================= SipAddressesModel::SipAddressesModel (QObject *parent) : QAbstractListModel(parent) { - fetchSipAddresses(); + initSipAddresses(); ContactsListModel *contacts = CoreManager::getInstance()->getContactsListModel(); - QObject::connect(contacts, &ContactsListModel::contactAdded, this, &SipAddressesModel::updateFromNewContact); - - QObject::connect( - contacts, &ContactsListModel::contactRemoved, this, [this](const ContactModel *contact) { - for (const auto &sip_address : contact->getVcardModel()->getSipAddresses()) - tryToRemoveSipAddress(sip_address.toString()); - } - ); + QObject::connect(contacts, &ContactsListModel::contactAdded, this, &SipAddressesModel::handleContactAdded); + QObject::connect(contacts, &ContactsListModel::contactRemoved, this, &SipAddressesModel::handleContactRemoved); QObject::connect( contacts, &ContactsListModel::sipAddressAdded, this, [this](ContactModel *contact, const QString &sip_address) { @@ -32,7 +28,7 @@ SipAddressesModel::SipAddressesModel (QObject *parent) : QAbstractListModel(pare return; } - updateFromNewContactSipAddress(contact, sip_address); + addOrUpdateSipAddress(sip_address, contact); } ); @@ -44,7 +40,7 @@ SipAddressesModel::SipAddressesModel (QObject *parent) : QAbstractListModel(pare return; } - tryToRemoveSipAddress(sip_address); + removeContactOfSipAddress(sip_address); } ); } @@ -133,6 +129,14 @@ void SipAddressesModel::handleAllHistoryEntriesRemoved () { emit dataChanged(index(row, 0), index(row, 0)); } +void SipAddressesModel::handleReceivedMessage ( + const shared_ptr &room, + const shared_ptr &message +) { + const QString &sip_address = ::Utils::linphoneStringToQString(message->getFromAddress()->asString()); + addOrUpdateSipAddress(sip_address, nullptr, static_cast(message->getTime())); +} + // ----------------------------------------------------------------------------- bool SipAddressesModel::removeRow (int row, const QModelIndex &parent) { @@ -160,49 +164,60 @@ bool SipAddressesModel::removeRows (int row, int count, const QModelIndex &paren return true; } -void SipAddressesModel::updateFromNewContact (ContactModel *contact) { +void SipAddressesModel::handleContactAdded (ContactModel *contact) { for (const auto &sip_address : contact->getVcardModel()->getSipAddresses()) - updateFromNewContactSipAddress(contact, sip_address.toString()); + addOrUpdateSipAddress(sip_address.toString(), contact); } -void SipAddressesModel::updateFromNewContactSipAddress (ContactModel *contact, const QString &sip_address) { +void SipAddressesModel::handleContactRemoved (const ContactModel *contact) { + for (const auto &sip_address : contact->getVcardModel()->getSipAddresses()) + removeContactOfSipAddress(sip_address.toString()); +} + +void SipAddressesModel::addOrUpdateSipAddress (const QString &sip_address, ContactModel *contact, qint64 timestamp) { auto it = m_sip_addresses.find(sip_address); + if (it != m_sip_addresses.end()) { + if (contact) { + (*it)["contact"] = QVariant::fromValue(contact); + updateObservers(sip_address, contact); + } - // New sip address. - if (it == m_sip_addresses.end()) { - QVariantMap map; - map["sipAddress"] = sip_address; - map["contact"] = QVariant::fromValue(contact); - - updateObservers(sip_address, contact); - - int row = m_refs.count(); - - beginInsertRows(QModelIndex(), row, row); - - qInfo() << QStringLiteral("Add sip address: `%1`.").arg(sip_address); - - m_sip_addresses[sip_address] = map; - m_refs << &m_sip_addresses[sip_address]; - - endInsertRows(); + if (timestamp) + (*it)["timestamp"] = QDateTime::fromMSecsSinceEpoch(timestamp * 1000); + int row = m_refs.indexOf(&(*it)); + Q_ASSERT(row != -1); emit dataChanged(index(row, 0), index(row, 0)); return; } - // Sip address exists, update contact. - (*it)["contact"] = QVariant::fromValue(contact); + QVariantMap map; + map["sipAddress"] = sip_address; - updateObservers(sip_address, contact); + if (contact) { + map["contact"] = QVariant::fromValue(contact); + updateObservers(sip_address, contact); + } + + if (timestamp) + map["timestamp"] = QDateTime::fromMSecsSinceEpoch(timestamp * 1000); + + int row = m_refs.count(); + + beginInsertRows(QModelIndex(), row, row); + + qInfo() << QStringLiteral("Add sip address: `%1`.").arg(sip_address); + + m_sip_addresses[sip_address] = map; + m_refs << &m_sip_addresses[sip_address]; + + endInsertRows(); - int row = m_refs.indexOf(&(*it)); - Q_ASSERT(row != -1); emit dataChanged(index(row, 0), index(row, 0)); } -void SipAddressesModel::tryToRemoveSipAddress (const QString &sip_address) { +void SipAddressesModel::removeContactOfSipAddress (const QString &sip_address) { auto it = m_sip_addresses.find(sip_address); if (it == m_sip_addresses.end()) { qWarning() << QStringLiteral("Unable to remove unavailable sip address: `%1`.").arg(sip_address); @@ -227,7 +242,7 @@ void SipAddressesModel::tryToRemoveSipAddress (const QString &sip_address) { removeRow(row); } -void SipAddressesModel::fetchSipAddresses () { +void SipAddressesModel::initSipAddresses () { shared_ptr core = CoreManager::getInstance()->getCore(); // Get sip addresses from chatrooms. @@ -275,7 +290,7 @@ void SipAddressesModel::fetchSipAddresses () { // Get sip addresses from contacts. for (auto &contact : CoreManager::getInstance()->getContactsListModel()->m_list) - updateFromNewContact(contact); + handleContactAdded(contact); } void SipAddressesModel::updateObservers (const QString &sip_address, ContactModel *contact) { diff --git a/tests/src/components/sip-addresses/SipAddressesModel.hpp b/tests/src/components/sip-addresses/SipAddressesModel.hpp index 61241dc83..8fc86aa31 100644 --- a/tests/src/components/sip-addresses/SipAddressesModel.hpp +++ b/tests/src/components/sip-addresses/SipAddressesModel.hpp @@ -25,15 +25,22 @@ public: Q_INVOKABLE void handleAllHistoryEntriesRemoved (); + void handleReceivedMessage ( + const std::shared_ptr &room, + const std::shared_ptr &message + ); + private: bool removeRow (int row, const QModelIndex &parent = QModelIndex()); bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override; - void updateFromNewContact (ContactModel *contact); - void updateFromNewContactSipAddress (ContactModel *contact, const QString &sip_address); - void tryToRemoveSipAddress (const QString &sip_address); + void handleContactAdded (ContactModel *contact); + void handleContactRemoved (const ContactModel *contact); - void fetchSipAddresses (); + void addOrUpdateSipAddress (const QString &sip_address, ContactModel *contact = nullptr, qint64 timestamp = 0); + void removeContactOfSipAddress (const QString &sip_address); + + void initSipAddresses (); void updateObservers (const QString &sip_address, ContactModel *contact); diff --git a/tests/src/components/timeline/TimelineModel.cpp b/tests/src/components/timeline/TimelineModel.cpp index 572927c35..4bfab2a58 100644 --- a/tests/src/components/timeline/TimelineModel.cpp +++ b/tests/src/components/timeline/TimelineModel.cpp @@ -1,3 +1,5 @@ +#include + #include "../core/CoreManager.hpp" #include "TimelineModel.hpp" @@ -23,5 +25,6 @@ bool TimelineModel::filterAcceptsRow (int source_row, const QModelIndex &source_ } bool TimelineModel::lessThan (const QModelIndex &left, const QModelIndex &right) const { - return sourceModel()->data(left).toMap()["timestamp"] > sourceModel()->data(right).toMap()["timestamp"]; + return sourceModel()->data(left).toMap()["timestamp"].toDateTime().toMSecsSinceEpoch() > + sourceModel()->data(right).toMap()["timestamp"].toDateTime().toMSecsSinceEpoch(); }