diff --git a/tests/src/components/contact/ContactModel.cpp b/tests/src/components/contact/ContactModel.cpp index 51bae4779..3474d6fdd 100644 --- a/tests/src/components/contact/ContactModel.cpp +++ b/tests/src/components/contact/ContactModel.cpp @@ -1,3 +1,5 @@ +#include + #include "../../app/App.hpp" #include "ContactModel.hpp" @@ -11,7 +13,6 @@ ContactModel::ContactModel (shared_ptr linphone_friend) { m_vcard = make_shared(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 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 { diff --git a/tests/src/components/contact/ContactModel.hpp b/tests/src/components/contact/ContactModel.hpp index d80299837..b319073b3 100644 --- a/tests/src/components/contact/ContactModel.hpp +++ b/tests/src/components/contact/ContactModel.hpp @@ -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 m_vcard; std::shared_ptr m_linphone_friend; }; diff --git a/tests/src/components/contact/VcardModel.cpp b/tests/src/components/contact/VcardModel.cpp index 212f2321c..61f6aeaa2 100644 --- a/tests/src/components/contact/VcardModel.cpp +++ b/tests/src/components/contact/VcardModel.cpp @@ -156,7 +156,7 @@ inline shared_ptr getOrCreateBelCardAddress (shared_ptr if (addresses.empty()) { address = belcard::BelCardGeneric::create(); 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 value = belcard::BelCardGeneric::create(); 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 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 value = belcard::BelCardGeneric::create(); 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 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 value = belcard::BelCardGeneric::create(); 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 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 value = belcard::BelCardGeneric::create(); 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 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(); diff --git a/tests/src/components/contacts/ContactsListModel.cpp b/tests/src/components/contacts/ContactsListModel.cpp index 69aed371e..c9360edba 100644 --- a/tests/src/components/contacts/ContactsListModel.cpp +++ b/tests/src/components/contacts/ContactsListModel.cpp @@ -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; +} diff --git a/tests/src/components/contacts/ContactsListModel.hpp b/tests/src/components/contacts/ContactsListModel.hpp index 89eedc143..aebc1b0a4 100644 --- a/tests/src/components/contacts/ContactsListModel.hpp +++ b/tests/src/components/contacts/ContactsListModel.hpp @@ -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 m_list; std::shared_ptr m_linphone_friends; }; diff --git a/tests/src/components/sip-addresses/SipAddressesModel.cpp b/tests/src/components/sip-addresses/SipAddressesModel.cpp index 4df2f5959..4466b61ab 100644 --- a/tests/src/components/sip-addresses/SipAddressesModel.cpp +++ b/tests/src/components/sip-addresses/SipAddressesModel.cpp @@ -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); } diff --git a/tests/src/components/sip-addresses/SipAddressesModel.hpp b/tests/src/components/sip-addresses/SipAddressesModel.hpp index 7d5a83f8d..2db68dd84 100644 --- a/tests/src/components/sip-addresses/SipAddressesModel.hpp +++ b/tests/src/components/sip-addresses/SipAddressesModel.hpp @@ -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 m_sip_addresses;