mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-23 06:38:07 +00:00
feat(app): handle correctly sip addresses changes (on contact, from history, ...)
This commit is contained in:
parent
25b6925977
commit
4ce00a71f4
7 changed files with 188 additions and 81 deletions
|
|
@ -1,3 +1,5 @@
|
|||
#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();
|
||||
|
||||
// Sip address exists, update contact.
|
||||
(*it)["contact"] = QVariant::fromValue(contact);
|
||||
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));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Sip address exists, update contact.
|
||||
(*it)["contact"] = QVariant::fromValue(contact);
|
||||
|
||||
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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue