diff --git a/tests/src/components/contacts/ContactsListModel.cpp b/tests/src/components/contacts/ContactsListModel.cpp index d95753259..69aed371e 100644 --- a/tests/src/components/contacts/ContactsListModel.cpp +++ b/tests/src/components/contacts/ContactsListModel.cpp @@ -65,6 +65,8 @@ bool ContactsListModel::removeRows (int row, int count, const QModelIndex &paren ContactModel *contact = m_list.takeAt(row); m_linphone_friends->removeFriend(contact->m_linphone_friend); + + emit contactRemoved(contact); contact->deleteLater(); } @@ -96,6 +98,8 @@ ContactModel *ContactsListModel::addContact (VcardModel *vcard) { m_list << contact; endInsertRows(); + emit contactAdded(contact); + return contact; } diff --git a/tests/src/components/contacts/ContactsListModel.hpp b/tests/src/components/contacts/ContactsListModel.hpp index bd53abb86..89eedc143 100644 --- a/tests/src/components/contacts/ContactsListModel.hpp +++ b/tests/src/components/contacts/ContactsListModel.hpp @@ -29,6 +29,10 @@ public slots: ContactModel *addContact (VcardModel *vcard); void removeContact (ContactModel *contact); +signals: + void contactAdded (ContactModel *contact); + void contactRemoved (const ContactModel *contact); + private: 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 17fc5d48a..c9ad8552f 100644 --- a/tests/src/components/sip-addresses/SipAddressesModel.cpp +++ b/tests/src/components/sip-addresses/SipAddressesModel.cpp @@ -1,8 +1,8 @@ #include #include +#include #include "../../utils.hpp" -#include "../contacts/ContactsListModel.hpp" #include "../core/CoreManager.hpp" #include "SipAddressesModel.hpp" @@ -10,6 +10,101 @@ // ============================================================================= SipAddressesModel::SipAddressesModel (QObject *parent) : QAbstractListModel(parent) { + fetchSipAddresses(); + + QObject::connect( + CoreManager::getInstance()->getContactsListModel(), &ContactsListModel::contactAdded, + this, &SipAddressesModel::updateFromContact + ); + + 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) { + int row = static_cast(distance(m_sip_addresses.begin(), it)); + emit dataChanged(index(row, 0), index(row, 0)); + } + } + } + ); + + // TODO: handle data changed from contact +} + +// ----------------------------------------------------------------------------- + +int SipAddressesModel::rowCount (const QModelIndex &) const { + return m_refs.count(); +} + +QHash SipAddressesModel::roleNames () const { + QHash roles; + roles[Qt::DisplayRole] = "$sipAddress"; + return roles; +} + +QVariant SipAddressesModel::data (const QModelIndex &index, int role) const { + int row = index.row(); + + if (!index.isValid() || row < 0 || row >= m_refs.count()) + return QVariant(); + + if (role == Qt::DisplayRole) + return QVariant::fromValue(*m_refs[row]); + + return QVariant(); +} + +// ----------------------------------------------------------------------------- + +ContactModel *SipAddressesModel::mapSipAddressToContact (const QString &sip_address) const { + auto it = m_sip_addresses.find(sip_address); + if (it == m_sip_addresses.end()) + return nullptr; + + return it->value("contact").value(); +} + +// ----------------------------------------------------------------------------- + +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); + + // New sip address from contact = new entry. + if (it == m_sip_addresses.end()) { + QVariantMap map; + map["sipAddress"] = sip_address; + map["contact"] = QVariant::fromValue(contact); + + m_sip_addresses[sip_address_str] = map; + m_refs << &m_sip_addresses[sip_address_str]; + + int row = m_refs.count() - 1; + emit dataChanged(index(row, 0), index(row, 0)); + continue; + } + + // 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::fetchSipAddresses () { shared_ptr core = CoreManager::getInstance()->getCore(); // Get sip addresses from chatrooms. @@ -48,55 +143,10 @@ SipAddressesModel::SipAddressesModel (QObject *parent) : QAbstractListModel(pare m_sip_addresses[sip_address] = map; } - // Get sip addresses from contacts. - for (auto &contact : CoreManager::getInstance()->getContactsListModel()->m_list) { - for (const auto &sip_address : contact->getVcardModel()->getSipAddresses()) { - auto it = m_sip_addresses.find(sip_address.toString()); - - if (it == m_sip_addresses.end()) { - QVariantMap map; - map["sipAddress"] = sip_address; - map["contact"] = QVariant::fromValue(contact); - m_sip_addresses[sip_address.toString()] = map; - } else - (*it)["contact"] = QVariant::fromValue(contact); - } - } - for (const auto &map : m_sip_addresses) m_refs << ↦ -} - -// ----------------------------------------------------------------------------- - -int SipAddressesModel::rowCount (const QModelIndex &) const { - return m_refs.count(); -} - -QHash SipAddressesModel::roleNames () const { - QHash roles; - roles[Qt::DisplayRole] = "$sipAddress"; - return roles; -} - -QVariant SipAddressesModel::data (const QModelIndex &index, int role) const { - int row = index.row(); - - if (!index.isValid() || row < 0 || row >= m_refs.count()) - return QVariant(); - - if (role == Qt::DisplayRole) - return QVariant::fromValue(*m_refs[row]); - - return QVariant(); -} - -// ------------------------------------------------------------------------------ - -ContactModel *SipAddressesModel::mapSipAddressToContact (const QString &sip_address) const { - auto it = m_sip_addresses.find(sip_address); - if (it == m_sip_addresses.end()) - return nullptr; - - return it->value("contact").value(); + + // Get sip addresses from contacts. + for (auto &contact : CoreManager::getInstance()->getContactsListModel()->m_list) + updateFromContact(contact); } diff --git a/tests/src/components/sip-addresses/SipAddressesModel.hpp b/tests/src/components/sip-addresses/SipAddressesModel.hpp index 45109472f..3c8bc00f0 100644 --- a/tests/src/components/sip-addresses/SipAddressesModel.hpp +++ b/tests/src/components/sip-addresses/SipAddressesModel.hpp @@ -23,6 +23,9 @@ public slots: ContactModel *mapSipAddressToContact (const QString &sip_address) const; private: + void updateFromContact (ContactModel *contact); + void fetchSipAddresses (); + QHash m_sip_addresses; QList m_refs; }; diff --git a/tests/ui/modules/Linphone/Contact/Contact.qml b/tests/ui/modules/Linphone/Contact/Contact.qml index 8574f82ae..cbc6ecc38 100644 --- a/tests/ui/modules/Linphone/Contact/Contact.qml +++ b/tests/ui/modules/Linphone/Contact/Contact.qml @@ -5,6 +5,7 @@ import Common 1.0 import Linphone 1.0 import LinphoneUtils 1.0 import Linphone.Styles 1.0 +import Utils 1.0 // ============================================================================= @@ -16,11 +17,20 @@ Rectangle { property alias actions: actionBar.data property alias sipAddressColor: description.sipAddressColor property alias usernameColor: description.usernameColor - property string sipAddress - property var _contact: SipAddressesModel.mapSipAddressToContact(sipAddress) + + // Can be a SipAddress object of SipAddressesModel or just a string. + property var sipAddress + + property var _contact: Utils.isObject(sipAddress) + ? sipAddress.contact + : SipAddressesModel.mapSipAddressToContact(sipAddress) // --------------------------------------------------------------------------- + function _getSipAddress () { + return item.sipAddress.sipAddress || item.sipAddress + } + color: 'transparent' // No color by default. height: ContactStyle.height @@ -39,7 +49,7 @@ Rectangle { Layout.preferredWidth: ContactStyle.contentHeight image: _contact && _contact.vcard.avatar presenceLevel: _contact ? _contact.presenceLevel : Presence.White - username: LinphoneUtils.getContactUsername(_contact || sipAddress) + username: LinphoneUtils.getContactUsername(_contact || _getSipAddress()) } ContactDescription { @@ -47,7 +57,7 @@ Rectangle { Layout.fillHeight: true Layout.fillWidth: true - sipAddress: item.sipAddress + sipAddress: _getSipAddress() username: avatar.username } diff --git a/tests/ui/modules/Linphone/Timeline.qml b/tests/ui/modules/Linphone/Timeline.qml index f714a4a7b..cff7df61c 100644 --- a/tests/ui/modules/Linphone/Timeline.qml +++ b/tests/ui/modules/Linphone/Timeline.qml @@ -85,17 +85,6 @@ ColumnLayout { currentIndex: -1 delegate: Item { - property var contact: { - Utils.assert( - !Utils.isArray($timelineEntry.sipAddress), - 'Conferences are not supported at this moment.' - ) - - return SipAddressesModel.mapSipAddressToContact( - $timelineEntry.sipAddress - ) || $timelineEntry.sipAddress - } - height: TimelineStyle.contact.height width: parent ? parent.width : 0 @@ -108,7 +97,7 @@ ColumnLayout { ? TimelineStyle.contact.backgroundColor.a : TimelineStyle.contact.backgroundColor.b ) - sipAddress: $timelineEntry.sipAddress + sipAddress: $timelineEntry sipAddressColor: view.currentIndex === index ? TimelineStyle.contact.sipAddress.color.selected : TimelineStyle.contact.sipAddress.color.normal