Commit 4ce00a71 authored by Ronan's avatar Ronan

feat(app): handle correctly sip addresses changes (on contact, from history, ...)

parent 25b69259
#include <QSet>
#include "../../app/App.hpp"
#include "ContactModel.hpp"
......@@ -11,7 +13,6 @@ ContactModel::ContactModel (shared_ptr<linphone::Friend> linphone_friend) {
m_vcard = make_shared<VcardModel>(linphone_friend->getVcard());
App::getInstance()->getEngine()->setObjectOwnership(m_vcard.get(), QQmlEngine::CppOwnership);
QObject::connect(m_vcard.get(), &VcardModel::vcardUpdated, this, &ContactModel::contactUpdated);
}
ContactModel::ContactModel (VcardModel *vcard) {
......@@ -23,7 +24,53 @@ ContactModel::ContactModel (VcardModel *vcard) {
m_vcard.reset(vcard);
engine->setObjectOwnership(vcard, QQmlEngine::CppOwnership);
QObject::connect(vcard, &VcardModel::vcardUpdated, this, &ContactModel::contactUpdated);
}
void ContactModel::startEdit () {
m_linphone_friend->edit();
m_old_sip_addresses = m_vcard->getSipAddresses();
}
void ContactModel::endEdit () {
m_linphone_friend->done();
QVariantList sip_addresses = m_vcard->getSipAddresses();
QSet<QString> done;
for (const auto &variant_a : m_old_sip_addresses) {
next:
const QString &sip_address = variant_a.toString();
if (done.contains(sip_address))
continue;
done.insert(sip_address);
// Check if old sip address exists in new set => No changes.
for (const auto &variant_b : sip_addresses) {
if (sip_address == variant_b.toString())
goto next;
}
emit sipAddressRemoved(sip_address);
}
m_old_sip_addresses.clear();
for (const auto &variant : sip_addresses) {
const QString &sip_address = variant.toString();
if (done.contains(sip_address))
continue;
done.insert(sip_address);
emit sipAddressAdded(sip_address);
}
emit contactUpdated();
}
void ContactModel::abortEdit () {
// TODO: call linphone friend abort function when available.
// m_linphone_friend->abort();
m_old_sip_addresses.clear();
}
Presence::PresenceStatus ContactModel::getPresenceStatus () const {
......
......@@ -27,21 +27,14 @@ public:
}
public slots:
void startEdit () {
m_linphone_friend->edit();
}
void endEdit () {
m_linphone_friend->done();
}
void abortEdit () {
// TODO: call linphone friend abort function.
// m_linphone_friend->abort();
}
void startEdit ();
void endEdit ();
void abortEdit ();
signals:
void contactUpdated ();
void sipAddressAdded (const QString &sip_address);
void sipAddressRemoved (const QString &sip_address);
private:
Presence::PresenceStatus getPresenceStatus () const;
......@@ -51,6 +44,8 @@ private:
return m_vcard.get();
}
QVariantList m_old_sip_addresses;
std::shared_ptr<VcardModel> m_vcard;
std::shared_ptr<linphone::Friend> m_linphone_friend;
};
......
......@@ -156,7 +156,7 @@ inline shared_ptr<belcard::BelCardAddress> getOrCreateBelCardAddress (shared_ptr
if (addresses.empty()) {
address = belcard::BelCardGeneric::create<belcard::BelCardAddress>();
if (!belcard->addAddress(address))
qWarning() << "Unable to create a new address.";
qWarning() << "Unable to create a new address on vcard.";
} else
address = addresses.front();
......@@ -227,7 +227,7 @@ bool VcardModel::addSipAddress (const QString &sip_address) {
);
if (!l_address) {
qWarning() << QStringLiteral("Unable to add invalid sip address: `%1`.").arg(sip_address);
qWarning() << QStringLiteral("Unable to add invalid sip address on vcard: `%1`.").arg(sip_address);
return false;
}
......@@ -236,10 +236,10 @@ bool VcardModel::addSipAddress (const QString &sip_address) {
shared_ptr<belcard::BelCardImpp> value = belcard::BelCardGeneric::create<belcard::BelCardImpp>();
value->setValue(l_address->asStringUriOnly());
qInfo() << QStringLiteral("Add new sip address: `%1`.").arg(sip_address);
qInfo() << QStringLiteral("Add new sip address on vcard: `%1`.").arg(sip_address);
if (!belcard->addImpp(value)) {
qWarning() << QStringLiteral("Unable to add sip address: `%1`.").arg(sip_address);
qWarning() << QStringLiteral("Unable to add sip address on vcard: `%1`.").arg(sip_address);
return false;
}
......@@ -253,17 +253,17 @@ void VcardModel::removeSipAddress (const QString &sip_address) {
shared_ptr<belcard::BelCardImpp> value = findBelCardValue(addresses, sip_address);
if (!value) {
qWarning() << QStringLiteral("Unable to remove sip address: `%1`.").arg(sip_address);
qWarning() << QStringLiteral("Unable to remove sip address on vcard: `%1`.").arg(sip_address);
return;
}
if (addresses.size() == 1) {
qWarning() << QStringLiteral("Unable to remove the only existing sip address: `%1`.")
qWarning() << QStringLiteral("Unable to remove the only existing sip address on vcard: `%1`.")
.arg(sip_address);
return;
}
qInfo() << QStringLiteral("Remove sip address: `%1`.").arg(sip_address);
qInfo() << QStringLiteral("Remove sip address on vcard: `%1`.").arg(sip_address);
belcard->removeImpp(value);
emit vcardUpdated();
......@@ -294,10 +294,10 @@ bool VcardModel::addCompany (const QString &company) {
shared_ptr<belcard::BelCardRole> value = belcard::BelCardGeneric::create<belcard::BelCardRole>();
value->setValue(::Utils::qStringToLinphoneString(company));
qInfo() << QStringLiteral("Add new company: `%1`.").arg(company);
qInfo() << QStringLiteral("Add new company on vcard: `%1`.").arg(company);
if (!belcard->addRole(value)) {
qWarning() << QStringLiteral("Unable to add company: `%1`.").arg(company);
qWarning() << QStringLiteral("Unable to add company on vcard: `%1`.").arg(company);
return false;
}
......@@ -310,11 +310,11 @@ void VcardModel::removeCompany (const QString &company) {
shared_ptr<belcard::BelCardRole> value = findBelCardValue(belcard->getRoles(), company);
if (!value) {
qWarning() << QStringLiteral("Unable to remove company: `%1`.").arg(company);
qWarning() << QStringLiteral("Unable to remove company on vcard: `%1`.").arg(company);
return;
}
qInfo() << QStringLiteral("Remove company: `%1`.").arg(company);
qInfo() << QStringLiteral("Remove company on vcard: `%1`.").arg(company);
belcard->removeRole(value);
emit vcardUpdated();
......@@ -345,10 +345,10 @@ bool VcardModel::addEmail (const QString &email) {
shared_ptr<belcard::BelCardEmail> value = belcard::BelCardGeneric::create<belcard::BelCardEmail>();
value->setValue(::Utils::qStringToLinphoneString(email));
qInfo() << QStringLiteral("Add new email: `%1`.").arg(email);
qInfo() << QStringLiteral("Add new email on vcard: `%1`.").arg(email);
if (!belcard->addEmail(value)) {
qWarning() << QStringLiteral("Unable to add email: `%1`.").arg(email);
qWarning() << QStringLiteral("Unable to add email on vcard: `%1`.").arg(email);
return false;
}
......@@ -361,11 +361,11 @@ void VcardModel::removeEmail (const QString &email) {
shared_ptr<belcard::BelCardEmail> value = findBelCardValue(belcard->getEmails(), email);
if (!value) {
qWarning() << QStringLiteral("Unable to remove email: `%1`.").arg(email);
qWarning() << QStringLiteral("Unable to remove email on vcard: `%1`.").arg(email);
return;
}
qInfo() << QStringLiteral("Remove email: `%1`.").arg(email);
qInfo() << QStringLiteral("Remove email on vcard: `%1`.").arg(email);
belcard->removeEmail(value);
emit vcardUpdated();
......@@ -396,10 +396,10 @@ bool VcardModel::addUrl (const QString &url) {
shared_ptr<belcard::BelCardURL> value = belcard::BelCardGeneric::create<belcard::BelCardURL>();
value->setValue(::Utils::qStringToLinphoneString(url));
qInfo() << QStringLiteral("Add new url: `%1`.").arg(url);
qInfo() << QStringLiteral("Add new url on vcard: `%1`.").arg(url);
if (!belcard->addURL(value)) {
qWarning() << QStringLiteral("Unable to add url: `%1`.").arg(url);
qWarning() << QStringLiteral("Unable to add url on vcard: `%1`.").arg(url);
return false;
}
......@@ -412,11 +412,11 @@ void VcardModel::removeUrl (const QString &url) {
shared_ptr<belcard::BelCardURL> value = findBelCardValue(belcard->getURLs(), url);
if (!value) {
qWarning() << QStringLiteral("Unable to remove url: `%1`.").arg(url);
qWarning() << QStringLiteral("Unable to remove url on vcard: `%1`.").arg(url);
return;
}
qInfo() << QStringLiteral("Remove url: `%1`.").arg(url);
qInfo() << QStringLiteral("Remove url on vcard: `%1`.").arg(url);
belcard->removeURL(value);
emit vcardUpdated();
......
......@@ -23,7 +23,7 @@ ContactsListModel::ContactsListModel (QObject *parent) : QAbstractListModel(pare
contact, QQmlEngine::CppOwnership
);
m_list << contact;
addContact(contact);
}
}
......@@ -95,7 +95,7 @@ ContactModel *ContactsListModel::addContact (VcardModel *vcard) {
int row = rowCount();
beginInsertRows(QModelIndex(), row, row);
m_list << contact;
addContact(contact);
endInsertRows();
emit contactAdded(contact);
......@@ -110,3 +110,24 @@ void ContactsListModel::removeContact (ContactModel *contact) {
if (index == -1 || !removeRow(index))
qWarning() << "Unable to remove contact:" << contact;
}
void ContactsListModel::addContact (ContactModel *contact) {
QObject::connect(
contact, &ContactModel::contactUpdated,
this, [this, contact]() {
emit contactUpdated(contact);
}
);
QObject::connect(
contact, &ContactModel::sipAddressAdded, this, [this, contact](const QString &sip_address) {
emit sipAddressAdded(contact, sip_address);
}
);
QObject::connect(
contact, &ContactModel::sipAddressRemoved, this, [this, contact](const QString &sip_address) {
emit sipAddressRemoved(contact, sip_address);
}
);
m_list << contact;
}
......@@ -32,8 +32,14 @@ public slots:
signals:
void contactAdded (ContactModel *contact);
void contactRemoved (const ContactModel *contact);
void contactUpdated (ContactModel *contact);
void sipAddressAdded (ContactModel *contact, const QString &sip_address);
void sipAddressRemoved (ContactModel *contact, const QString &sip_address);
private:
void addContact (ContactModel *contact);
QList<ContactModel *> m_list;
std::shared_ptr<linphone::FriendList> m_linphone_friends;
};
......
......@@ -12,37 +12,39 @@
SipAddressesModel::SipAddressesModel (QObject *parent) : QAbstractListModel(parent) {
fetchSipAddresses();
ContactsListModel *contacts = CoreManager::getInstance()->getContactsListModel();
QObject::connect(contacts, &ContactsListModel::contactAdded, this, &SipAddressesModel::updateFromNewContact);
QObject::connect(
CoreManager::getInstance()->getContactsListModel(), &ContactsListModel::contactAdded,
this, &SipAddressesModel::updateFromContact
contacts, &ContactsListModel::contactRemoved, this, [this](const ContactModel *contact) {
for (const auto &sip_address : contact->getVcardModel()->getSipAddresses())
tryToRemoveSipAddress(sip_address.toString());
}
);
QObject::connect(
CoreManager::getInstance()->getContactsListModel(), &ContactsListModel::contactRemoved,
this, [this](const ContactModel *contact) {
for (const auto &sip_address : contact->getVcardModel()->getSipAddresses()) {
auto it = m_sip_addresses.find(sip_address.toString());
if (it == m_sip_addresses.end()) {
qWarning() << QStringLiteral("Unable to remove contact from sip address: `%1`.").arg(sip_address.toString());
continue;
}
if (it->remove("contact") == 0)
qWarning() << QStringLiteral("`contact` field is empty on sip address: `%1`.").arg(sip_address.toString());
int row = m_refs.indexOf(&(*it));
Q_ASSERT(row != -1);
// History exists, signal changes.
if (it->contains("timestamp")) {
emit dataChanged(index(row, 0), index(row, 0));
continue;
}
// Remove sip address if no history.
removeRow(row);
contacts, &ContactsListModel::sipAddressAdded, this, [this](ContactModel *contact, const QString &sip_address) {
// TODO: Avoid the limitation of one contact by sip address.
ContactModel *mapped_contact = mapSipAddressToContact(sip_address);
if (mapped_contact) {
qWarning() << "Unable to map sip address" << sip_address << "to" << contact << "- already used by" << mapped_contact;
return;
}
updateFromNewContactSipAddress(contact, sip_address);
}
);
QObject::connect(
contacts, &ContactsListModel::sipAddressRemoved, this, [this](ContactModel *contact, const QString &sip_address) {
ContactModel *mapped_contact = mapSipAddressToContact(sip_address);
if (contact != mapped_contact) {
qWarning() << "Unable to remove sip address" << sip_address << "of" << contact << "- already used by" << mapped_contact;
return;
}
tryToRemoveSipAddress(sip_address);
}
);
}
......@@ -137,32 +139,65 @@ bool SipAddressesModel::removeRows (int row, int count, const QModelIndex &paren
return true;
}
void SipAddressesModel::updateFromContact (ContactModel *contact) {
for (const auto &sip_address : contact->getVcardModel()->getSipAddresses()) {
const QString &sip_address_str = sip_address.toString();
auto it = m_sip_addresses.find(sip_address_str);
void SipAddressesModel::updateFromNewContact (ContactModel *contact) {
for (const auto &sip_address : contact->getVcardModel()->getSipAddresses())
updateFromNewContactSipAddress(contact, sip_address.toString());
}
// New sip address from contact = new entry.
if (it == m_sip_addresses.end()) {
QVariantMap map;
map["sipAddress"] = sip_address;
map["contact"] = QVariant::fromValue(contact);
void SipAddressesModel::updateFromNewContactSipAddress (ContactModel *contact, const QString &sip_address) {
auto it = m_sip_addresses.find(sip_address);
m_sip_addresses[sip_address_str] = map;
m_refs << &m_sip_addresses[sip_address_str];
// New sip address.
if (it == m_sip_addresses.end()) {
QVariantMap map;
map["sipAddress"] = sip_address;
map["contact"] = QVariant::fromValue(contact);
int row = m_refs.count() - 1;
emit dataChanged(index(row, 0), index(row, 0));
continue;
}
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();
// Sip address exists, update contact.
(*it)["contact"] = QVariant::fromValue(contact);
emit dataChanged(index(row, 0), index(row, 0));
return;
}
// Sip address exists, update contact.
(*it)["contact"] = QVariant::fromValue(contact);
int row = m_refs.indexOf(&(*it));
Q_ASSERT(row != -1);
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) {
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);
return;
}
if (it->remove("contact") == 0)
qWarning() << QStringLiteral("`contact` field is empty on sip address: `%1`.").arg(sip_address);
int row = m_refs.indexOf(&(*it));
Q_ASSERT(row != -1);
// History exists, signal changes.
if (it->contains("timestamp")) {
emit dataChanged(index(row, 0), index(row, 0));
return;
}
// Remove sip address if no history.
removeRow(row);
}
void SipAddressesModel::fetchSipAddresses () {
......@@ -213,5 +248,5 @@ void SipAddressesModel::fetchSipAddresses () {
// Get sip addresses from contacts.
for (auto &contact : CoreManager::getInstance()->getContactsListModel()->m_list)
updateFromContact(contact);
updateFromNewContact(contact);
}
......@@ -27,7 +27,10 @@ private:
bool removeRow (int row, const QModelIndex &parent = QModelIndex());
bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override;
void updateFromContact (ContactModel *contact);
void updateFromNewContact (ContactModel *contact);
void updateFromNewContactSipAddress (ContactModel *contact, const QString &sip_address);
void tryToRemoveSipAddress (const QString &sip_address);
void fetchSipAddresses ();
QHash<QString, QVariantMap> m_sip_addresses;
......
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