mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-02-07 15:08:24 +00:00
feat(app):
- supports linphone cbs - handle received messages - `SipAddressesModel` refactoring
This commit is contained in:
parent
555bf66047
commit
f181b6d659
13 changed files with 202 additions and 52 deletions
|
|
@ -1 +1 @@
|
|||
Subproject commit 7650064a1cb5b914b157c788e4ff8fa22d971f78
|
||||
Subproject commit fb3c9841ee5142d1826e2674591797343bd728ff
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ namespace Database {
|
|||
std::string getAvatarsPath ();
|
||||
|
||||
std::string getCallHistoryPath ();
|
||||
std::string getConfigPath ();
|
||||
std::string getFriendsListPath ();
|
||||
std::string getMessageHistoryPath ();
|
||||
}
|
||||
|
|
|
|||
34
tests/src/components/core/CoreHandlers.cpp
Normal file
34
tests/src/components/core/CoreHandlers.cpp
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#include <QtDebug>
|
||||
|
||||
#include "CoreManager.hpp"
|
||||
|
||||
#include "CoreHandlers.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// =============================================================================
|
||||
|
||||
void CoreHandlers::onAuthenticationRequested (
|
||||
const std::shared_ptr<linphone::Core> &lc,
|
||||
const std::shared_ptr<linphone::AuthInfo> &auth_info,
|
||||
linphone::AuthMethod method
|
||||
) {
|
||||
qDebug() << "Auth request";
|
||||
}
|
||||
|
||||
void CoreHandlers::onCallStateChanged (
|
||||
const shared_ptr<linphone::Core> &lc,
|
||||
const shared_ptr<linphone::Call> &call,
|
||||
linphone::CallState cstate,
|
||||
const string &message
|
||||
) {
|
||||
qDebug() << "call";
|
||||
}
|
||||
|
||||
void CoreHandlers::onMessageReceived (
|
||||
const shared_ptr<linphone::Core> &lc,
|
||||
const shared_ptr<linphone::ChatRoom> &room,
|
||||
const shared_ptr<linphone::ChatMessage> &message
|
||||
) {
|
||||
CoreManager::getInstance()->getSipAddressesModel()->handleReceivedMessage(room, message);
|
||||
}
|
||||
30
tests/src/components/core/CoreHandlers.hpp
Normal file
30
tests/src/components/core/CoreHandlers.hpp
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef CORE_HANDLERS_H_
|
||||
#define CORE_HANDLERS_H_
|
||||
|
||||
#include <linphone++/linphone.hh>
|
||||
|
||||
// =============================================================================
|
||||
|
||||
class CoreHandlers : public linphone::CoreListener {
|
||||
public:
|
||||
void onAuthenticationRequested (
|
||||
const std::shared_ptr<linphone::Core> &lc,
|
||||
const std::shared_ptr<linphone::AuthInfo> &auth_info,
|
||||
linphone::AuthMethod method
|
||||
) override;
|
||||
|
||||
void onCallStateChanged (
|
||||
const std::shared_ptr<linphone::Core> &lc,
|
||||
const std::shared_ptr<linphone::Call> &call,
|
||||
linphone::CallState cstate,
|
||||
const std::string &message
|
||||
) override;
|
||||
|
||||
void onMessageReceived (
|
||||
const std::shared_ptr<linphone::Core> &lc,
|
||||
const std::shared_ptr<linphone::ChatRoom> &room,
|
||||
const std::shared_ptr<linphone::ChatMessage> &message
|
||||
) override;
|
||||
};
|
||||
|
||||
#endif // CORE_HANDLERS_H_
|
||||
|
|
@ -1,4 +1,7 @@
|
|||
#include <QTimer>
|
||||
|
||||
#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<CoreHandlers>()) {
|
||||
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();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,11 +6,13 @@
|
|||
|
||||
// =============================================================================
|
||||
|
||||
class QTimer;
|
||||
|
||||
class CoreManager : public QObject {
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
~CoreManager () = default;
|
||||
~CoreManager ();
|
||||
|
||||
std::shared_ptr<linphone::Core> 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<linphone::Core> m_core;
|
||||
std::shared_ptr<linphone::CoreListener> m_handlers;
|
||||
|
||||
ContactsListModel *m_contacts_list_model;
|
||||
SipAddressesModel *m_sip_addresses_model;
|
||||
|
||||
QTimer *m_cbs_timer;
|
||||
|
||||
static CoreManager *m_instance;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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<linphone::ProxyConfig> cfg = m_core->getDefaultProxyConfig();
|
||||
shared_ptr<linphone::Address> address = cfg->getIdentityAddress();
|
||||
shared_ptr<linphone::AuthInfo> auth_info = m_core->findAuthInfo("", address->getUsername(), cfg->getDomain());
|
||||
|
||||
if (auth_info)
|
||||
qDebug() << "OK";
|
||||
else
|
||||
qDebug() << "FAIL";
|
||||
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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<linphone::ChatRoom> &room,
|
||||
const shared_ptr<linphone::ChatMessage> &message
|
||||
) {
|
||||
const QString &sip_address = ::Utils::linphoneStringToQString(message->getFromAddress()->asString());
|
||||
addOrUpdateSipAddress(sip_address, nullptr, static_cast<qint64>(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<linphone::Core> 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) {
|
||||
|
|
|
|||
|
|
@ -25,15 +25,22 @@ public:
|
|||
|
||||
Q_INVOKABLE void handleAllHistoryEntriesRemoved ();
|
||||
|
||||
void handleReceivedMessage (
|
||||
const std::shared_ptr<linphone::ChatRoom> &room,
|
||||
const std::shared_ptr<linphone::ChatMessage> &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);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#include <QDateTime>
|
||||
|
||||
#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();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue