Commit 9813baf1 authored by Ronan's avatar Ronan

feat(app): add a `ContactObserver` component

parent ed17343d
......@@ -58,6 +58,7 @@ set(SOURCES
src/components/camera/Camera.cpp
src/components/chat/ChatModel.cpp
src/components/chat/ChatProxyModel.cpp
src/components/contact/ContactObserver.cpp
src/components/contact/ContactModel.cpp
src/components/contact/VcardModel.cpp
src/components/contacts/ContactsListModel.cpp
......@@ -66,7 +67,6 @@ set(SOURCES
src/components/notifier/Notifier.cpp
src/components/settings/AccountSettingsModel.cpp
src/components/settings/SettingsModel.cpp
src/components/sip-address/SipAddressModel.cpp
src/components/sip-addresses/SipAddressesModel.cpp
src/components/smart-search-bar/SmartSearchBarModel.cpp
src/components/timeline/TimelineModel.cpp
......@@ -82,6 +82,7 @@ set(HEADERS
src/components/camera/Camera.hpp
src/components/chat/ChatModel.hpp
src/components/chat/ChatProxyModel.hpp
src/components/contact/ContactObserver.hpp
src/components/contact/ContactModel.hpp
src/components/contact/VcardModel.hpp
src/components/contacts/ContactsListModel.hpp
......@@ -91,7 +92,6 @@ set(HEADERS
src/components/presence/Presence.hpp
src/components/settings/AccountSettingsModel.hpp
src/components/settings/SettingsModel.hpp
src/components/sip-address/SipAddressModel.hpp
src/components/sip-addresses/SipAddressesModel.hpp
src/components/smart-search-bar/SmartSearchBarModel.hpp
src/components/timeline/TimelineModel.hpp
......
......@@ -89,8 +89,8 @@ void App::registerTypes () {
qmlRegisterUncreatableType<ContactModel>(
"Linphone", 1, 0, "ContactModel", "ContactModel is uncreatable"
);
qmlRegisterUncreatableType<SipAddressModel>(
"Linphone", 1, 0, "SipAddressModel", "SipAddressModel is uncreatable"
qmlRegisterUncreatableType<ContactObserver>(
"Linphone", 1, 0, "ContactObserver", "ContactObserver is uncreatable"
);
qmlRegisterUncreatableType<VcardModel>(
"Linphone", 1, 0, "VcardModel", "VcardModel is uncreatable"
......
#include "../contact/ContactModel.hpp"
#include "SipAddressModel.hpp"
#include "ContactObserver.hpp"
// =============================================================================
SipAddressModel::SipAddressModel () {
// TODO
ContactObserver::ContactObserver (const QString &sip_address) {
m_sip_address = sip_address;
}
void ContactObserver::setContact (ContactModel *contact) {
m_contact = contact;
emit contactChanged(contact);
}
#ifndef SIP_ADDRESS_MODEL_H_
#define SIP_ADDRESS_MODEL_H_
#ifndef CONTACT_OBSERVER_H_
#define CONTACT_OBSERVER_H_
#include <QObject>
......@@ -7,15 +7,17 @@
class ContactModel;
class SipAddressModel : public QObject {
class ContactObserver : public QObject {
friend class SipAddressesModel;
Q_OBJECT;
Q_PROPERTY(QString sipAddress READ getSipAddress CONSTANT);
Q_PROPERTY(ContactModel * contact READ getContact NOTIFY contactChanged);
public:
SipAddressModel ();
~SipAddressModel () = default;
ContactObserver (const QString &sip_address);
~ContactObserver () = default;
ContactModel *getContact () const {
return m_contact;
......@@ -29,10 +31,12 @@ private:
return m_sip_address;
}
void setContact (ContactModel *contact);
QString m_sip_address;
ContactModel *m_contact = nullptr;
};
Q_DECLARE_METATYPE(SipAddressModel *);
Q_DECLARE_METATYPE(ContactObserver *);
#endif // SIP_ADDRESS_MODEL_H_
#endif // CONTACT_OBSERVER_H_
......@@ -115,6 +115,24 @@ void SipAddressesModel::handleAllHistoryEntriesRemoved () {
// -----------------------------------------------------------------------------
ContactObserver *SipAddressesModel::getContactObserver (const QString &sip_address) {
ContactObserver *model = new ContactObserver(sip_address);
model->setContact(mapSipAddressToContact(sip_address));
m_observers.insert(sip_address, model);
QObject::connect(
model, &ContactObserver::destroyed, this, [this, model]() {
const QString &sip_address = model->getSipAddress();
if (m_observers.remove(sip_address, model) == 0)
qWarning() << QStringLiteral("Unable to remove sip address `%1` from observers.").arg(sip_address);
}
);
return model;
}
// -----------------------------------------------------------------------------
bool SipAddressesModel::removeRow (int row, const QModelIndex &parent) {
return removeRows(row, 1, parent);
}
......@@ -130,6 +148,7 @@ bool SipAddressesModel::removeRows (int row, int count, const QModelIndex &paren
for (int i = 0; i < count; ++i) {
const QVariantMap *map = m_refs.takeAt(row);
QString sip_address = (*map)["sipAddress"].toString();
qInfo() << QStringLiteral("Remove sip address: `%1`.").arg(sip_address);
m_sip_addresses.remove(sip_address);
}
......@@ -153,6 +172,8 @@ void SipAddressesModel::updateFromNewContactSipAddress (ContactModel *contact, c
map["sipAddress"] = sip_address;
map["contact"] = QVariant::fromValue(contact);
updateObservers(sip_address, contact);
int row = m_refs.count();
beginInsertRows(QModelIndex(), row, row);
......@@ -172,6 +193,8 @@ void SipAddressesModel::updateFromNewContactSipAddress (ContactModel *contact, c
// Sip address exists, update contact.
(*it)["contact"] = QVariant::fromValue(contact);
updateObservers(sip_address, contact);
int row = m_refs.indexOf(&(*it));
Q_ASSERT(row != -1);
emit dataChanged(index(row, 0), index(row, 0));
......@@ -184,6 +207,8 @@ void SipAddressesModel::tryToRemoveSipAddress (const QString &sip_address) {
return;
}
updateObservers(sip_address, nullptr);
if (it->remove("contact") == 0)
qWarning() << QStringLiteral("`contact` field is empty on sip address: `%1`.").arg(sip_address);
......@@ -250,3 +275,10 @@ void SipAddressesModel::fetchSipAddresses () {
for (auto &contact : CoreManager::getInstance()->getContactsListModel()->m_list)
updateFromNewContact(contact);
}
void SipAddressesModel::updateObservers (const QString &sip_address, ContactModel *contact) {
for (auto &observer : m_observers.values(sip_address)) {
if (contact != observer->getContact())
observer->setContact(contact);
}
}
......@@ -4,6 +4,7 @@
#include <QAbstractListModel>
#include "../contact/ContactModel.hpp"
#include "../contact/ContactObserver.hpp"
// =============================================================================
......@@ -23,6 +24,8 @@ public slots:
ContactModel *mapSipAddressToContact (const QString &sip_address) const;
void handleAllHistoryEntriesRemoved ();
ContactObserver *getContactObserver (const QString &sip_address);
private:
bool removeRow (int row, const QModelIndex &parent = QModelIndex());
bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override;
......@@ -33,8 +36,12 @@ private:
void fetchSipAddresses ();
void updateObservers (const QString &sip_address, ContactModel *contact);
QHash<QString, QVariantMap> m_sip_addresses;
QList<const QVariantMap *> m_refs;
QMultiHash<QString, ContactObserver *> m_observers;
};
#endif // SIP_ADDRESSES_MODEL_H_
......@@ -11,9 +11,7 @@ import Linphone.Styles 1.0
ColumnLayout {
property alias proxyModel: chat.model
property var _contact: SipAddressesModel.mapSipAddressToContact(
proxyModel.sipAddress
) || proxyModel.sipAddress
property var _contactObserver: SipAddressesModel.getContactObserver(proxyModel.sipAddress)
// ---------------------------------------------------------------------------
......
......@@ -20,8 +20,8 @@ RowLayout {
Avatar {
anchors.centerIn: parent
height: ChatStyle.entry.message.incoming.avatarSize
image: _contact.avatar
username: LinphoneUtils.getContactUsername(_contact)
image: _contactObserver.contact ? _contactObserver.contact.avatar : ''
username: LinphoneUtils.getContactUsername(_contactObserver.contact || _contactObserver.sipAddress)
width: ChatStyle.entry.message.incoming.avatarSize
}
}
......
......@@ -16,9 +16,7 @@ Rectangle {
property bool isVideoCall: false
property string sipAddress
property var _contact: SipAddressesModel.mapSipAddressToContact(
sipAddress
) || sipAddress
property var _contactObserver: SipAddressesModel.getContactObserver(sipAddress)
// ---------------------------------------------------------------------------
......@@ -58,7 +56,7 @@ Rectangle {
anchors.centerIn: parent
horizontalTextAlignment: Text.AlignHCenter
sipAddress: call.sipAddress
username: LinphoneUtils.getContactUsername(_contact)
username: LinphoneUtils.getContactUsername(_contactObserver.contact || call.sipAddress)
height: parent.height
width: parent.width - cameraActions.width - callQuality.width - 150
......@@ -110,7 +108,7 @@ Rectangle {
}
backgroundColor: StartingCallStyle.avatar.backgroundColor
image: _contact.vcard.avatar
image: _contactObserver.contact ? _contactObserver.contact.vcard.avatar : ''
username: contactDescription.username
height: _computeAvatarSize()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment