diff --git a/tests/src/components/contacts/ContactModel.hpp b/tests/src/components/contacts/ContactModel.hpp index 5404710e0..2f59d765a 100644 --- a/tests/src/components/contacts/ContactModel.hpp +++ b/tests/src/components/contacts/ContactModel.hpp @@ -6,6 +6,8 @@ // =================================================================== class ContactModel : public QObject { + friend class ContactsListProxyModel; + Q_OBJECT; Q_PROPERTY( @@ -76,14 +78,14 @@ public: m_sip_addresses = sip_addresses; } - QString getUsername () const { - return m_username; - } - signals: void contactUpdated (); private: + QString getUsername () const { + return m_username; + } + void setUsername (const QString &username) { m_username = username; } diff --git a/tests/src/components/contacts/ContactsListModel.hpp b/tests/src/components/contacts/ContactsListModel.hpp index 55d756d34..d7e3a7976 100644 --- a/tests/src/components/contacts/ContactsListModel.hpp +++ b/tests/src/components/contacts/ContactsListModel.hpp @@ -8,6 +8,8 @@ // =================================================================== class ContactsListModel : public QAbstractListModel { + friend class ContactsListProxyModel; + Q_OBJECT; public: diff --git a/tests/src/components/contacts/ContactsListProxyModel.cpp b/tests/src/components/contacts/ContactsListProxyModel.cpp index 18ee4b17b..1851958a6 100644 --- a/tests/src/components/contacts/ContactsListProxyModel.cpp +++ b/tests/src/components/contacts/ContactsListProxyModel.cpp @@ -2,6 +2,10 @@ #include "ContactsListProxyModel.hpp" +#define USERNAME_WEIGHT 0.5 +#define MAIN_SIP_ADDRESS_WEIGHT 0.3 +#define OTHER_SIP_ADDRESSES_WEIGHT 0.2 + // =================================================================== ContactsListModel *ContactsListProxyModel::m_list = nullptr; @@ -9,6 +13,11 @@ ContactsListModel *ContactsListProxyModel::m_list = nullptr; ContactsListProxyModel::ContactsListProxyModel (QObject *parent) : QSortFilterProxyModel(parent) { setSourceModel(m_list); setDynamicSortFilter(true); + setFilterCaseSensitivity(Qt::CaseInsensitive); + + foreach (const ContactModel *contact, m_list->m_list) + m_weights[contact] = 0; + sort(0); } @@ -16,7 +25,7 @@ void ContactsListProxyModel::initContactsListModel (ContactsListModel *list) { if (!m_list) m_list = list; else - qWarning() << "Contacts list model already defined."; + qWarning() << "Contacts list model is already defined."; } bool ContactsListProxyModel::filterAcceptsRow (int source_row, const QModelIndex &source_parent) const { @@ -25,17 +34,45 @@ bool ContactsListProxyModel::filterAcceptsRow (int source_row, const QModelIndex index.data(ContactsListModel::ContactRole) ); - qDebug() << "A"; - - return contact->getUsername().contains( - filterRegExp().pattern(), - Qt::CaseInsensitive - ); + int weight = m_weights[contact] = computeContactWeight(*contact); + return weight > 0; } bool ContactsListProxyModel::lessThan (const QModelIndex &left, const QModelIndex &right) const { + const ContactModel *contact_a = qvariant_cast( + sourceModel()->data(left, ContactsListModel::ContactRole) + ); + const ContactModel *contact_b = qvariant_cast( + sourceModel()->data(right, ContactsListModel::ContactRole) + ); - qDebug() << "B"; + float weight_a = m_weights[contact_a]; + float weight_b = m_weights[contact_b]; - return true; + // Sort by weight and name. + return ( + weight_a > weight_b || + (weight_a == weight_b && contact_a->m_username <= contact_b->m_username) + ); +} + +float ContactsListProxyModel::computeContactWeight (const ContactModel &contact) const { + float weight = 0; + + if (filterRegExp().indexIn(contact.m_username) != -1) + weight += USERNAME_WEIGHT; + + const QStringList &addresses = contact.m_sip_addresses; + + if (filterRegExp().indexIn(addresses[0]) != -1) + weight += MAIN_SIP_ADDRESS_WEIGHT; + + int size = addresses.size(); + + if (size > 1) + for (auto it = ++addresses.constBegin(); it != addresses.constEnd(); ++it) + if (filterRegExp().indexIn(*it) != -1) + weight += OTHER_SIP_ADDRESSES_WEIGHT / size; + + return weight; } diff --git a/tests/src/components/contacts/ContactsListProxyModel.hpp b/tests/src/components/contacts/ContactsListProxyModel.hpp index b29fceeb9..2060ccdb3 100644 --- a/tests/src/components/contacts/ContactsListProxyModel.hpp +++ b/tests/src/components/contacts/ContactsListProxyModel.hpp @@ -16,10 +16,18 @@ public: protected: bool filterAcceptsRow (int source_row, const QModelIndex &source_parent) const; - bool lessThan(const QModelIndex &left, const QModelIndex &right) const; + bool lessThan (const QModelIndex &left, const QModelIndex &right) const; private: + float computeContactWeight (const ContactModel &contact) const; + + // The contacts list is shared between `ContactsListProxyModel` + // it's necessary to initialize it with `initContactsListModel`. static ContactsListModel *m_list; + + // It's just a cache to save values computed by `filterAcceptsRow` + // and reused by `lessThan`. + mutable QHash m_weights; }; #endif // CONTACTS_LIST_PROXY_MODEL_H diff --git a/tests/src/main.cpp b/tests/src/main.cpp index 3635269ed..1b469a30a 100644 --- a/tests/src/main.cpp +++ b/tests/src/main.cpp @@ -10,6 +10,8 @@ #include "app.hpp" #include "components/contacts/ContactsListProxyModel.hpp" + +#include "components/contacts/ContactsListModel.hpp" #include "components/notification/Notification.hpp" // =================================================================== diff --git a/tests/ui/views/MainWindow/Contacts.qml b/tests/ui/views/MainWindow/Contacts.qml index 2fd786abe..30ebae330 100644 --- a/tests/ui/views/MainWindow/Contacts.qml +++ b/tests/ui/views/MainWindow/Contacts.qml @@ -32,7 +32,9 @@ ColumnLayout { } placeholderText: qsTr('searchContactPlaceholder') - onTextChanged: contacts.setFilterRegExp(text) + onTextChanged: { + contacts.setFilterFixedString(text) + } } ExclusiveButtons {