From e5d9bf20f7d7faf686f0023b294b637203388ca2 Mon Sep 17 00:00:00 2001 From: Ronan Abhamon Date: Tue, 20 Dec 2016 17:20:01 +0100 Subject: [PATCH] feat(app): - remove useless smart-search-bar from cpp - create a new `SipAddressesModel` component - create a `UnregisteredSipAddressesModel` (it uses the previous model) - `TimelineModel` uses too this model - many fixes and refactoring - `mapToSipAddress` moved from `ContactsListModel` to `SipAddressesModel` - ... --- tests/CMakeLists.txt | 8 +- tests/src/app/App.cpp | 10 ++ tests/src/components/chat/ChatProxyModel.cpp | 2 +- tests/src/components/contact/ContactModel.cpp | 4 - tests/src/components/contact/ContactModel.hpp | 12 +- tests/src/components/contact/VcardModel.hpp | 2 +- .../components/contacts/ContactsListModel.cpp | 11 -- .../components/contacts/ContactsListModel.hpp | 5 +- .../contacts/ContactsListProxyModel.cpp | 6 +- tests/src/components/core/CoreManager.hpp | 5 +- tests/src/components/notifier/Notifier.cpp | 5 +- tests/src/components/notifier/Notifier.hpp | 3 +- .../sip-addresses/SipAddressModel.cpp | 3 - .../sip-addresses/SipAddressModel.hpp | 14 -- .../sip-addresses/SipAddressesModel.cpp | 101 ++++++++++++++ .../sip-addresses/SipAddressesModel.hpp | 30 +++- .../UnregisteredSipAddressesModel.cpp | 14 ++ .../UnregisteredSipAddressesModel.hpp | 19 +++ .../smart-search-bar/SmartSearchBarModel.cpp | 1 - .../smart-search-bar/SmartSearchBarModel.hpp | 9 -- .../SmartSearchBarProxyModel.cpp | 1 - .../SmartSearchBarProxyModel.hpp | 9 -- .../src/components/timeline/TimelineModel.cpp | 130 ++---------------- .../src/components/timeline/TimelineModel.hpp | 20 +-- tests/ui/modules/Linphone/Chat/Chat.qml | 2 +- tests/ui/modules/Linphone/Contact/Contact.qml | 2 +- tests/ui/modules/Linphone/Timeline.qml | 14 +- .../views/App/Calls/AbstractStartingCall.qml | 2 +- tests/ui/views/App/Calls/Incall.qml | 2 +- tests/ui/views/App/MainWindow/ContactEdit.qml | 2 +- .../ui/views/App/MainWindow/Conversation.qml | 2 +- 31 files changed, 223 insertions(+), 227 deletions(-) delete mode 100644 tests/src/components/sip-addresses/SipAddressModel.cpp delete mode 100644 tests/src/components/sip-addresses/SipAddressModel.hpp create mode 100644 tests/src/components/sip-addresses/UnregisteredSipAddressesModel.cpp create mode 100644 tests/src/components/sip-addresses/UnregisteredSipAddressesModel.hpp delete mode 100644 tests/src/components/smart-search-bar/SmartSearchBarModel.cpp delete mode 100644 tests/src/components/smart-search-bar/SmartSearchBarModel.hpp delete mode 100644 tests/src/components/smart-search-bar/SmartSearchBarProxyModel.cpp delete mode 100644 tests/src/components/smart-search-bar/SmartSearchBarProxyModel.hpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ba26caaf0..7f553821a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -67,9 +67,7 @@ set(SOURCES src/components/settings/AccountSettingsModel.cpp src/components/settings/SettingsModel.cpp src/components/sip-addresses/SipAddressesModel.cpp - src/components/sip-addresses/SipAddressModel.cpp - src/components/smart-search-bar/SmartSearchBarModel.cpp - src/components/smart-search-bar/SmartSearchBarProxyModel.cpp + src/components/sip-addresses/UnregisteredSipAddressesModel.cpp src/components/timeline/TimelineModel.cpp src/main.cpp ) @@ -93,9 +91,7 @@ set(HEADERS src/components/settings/AccountSettingsModel.hpp src/components/settings/SettingsModel.hpp src/components/sip-addresses/SipAddressesModel.hpp - src/components/sip-addresses/SipAddressModel.hpp - src/components/smart-search-bar/SmartSearchBarModel.hpp - src/components/smart-search-bar/SmartSearchBarProxyModel.hpp + src/components/sip-addresses/UnregisteredSipAddressesModel.hpp src/components/timeline/TimelineModel.hpp src/utils.hpp ) diff --git a/tests/src/app/App.cpp b/tests/src/app/App.cpp index f3a5ecffa..d7c1edafd 100644 --- a/tests/src/app/App.cpp +++ b/tests/src/app/App.cpp @@ -11,6 +11,7 @@ #include "../components/core/CoreManager.hpp" #include "../components/notifier/Notifier.hpp" #include "../components/settings/AccountSettingsModel.hpp" +#include "../components/sip-addresses/SipAddressesModel.hpp" #include "../components/timeline/TimelineModel.hpp" #include "App.hpp" @@ -66,6 +67,7 @@ void App::initContentApp () { // Init core & contacts. CoreManager::init(); ContactsListModel::init(); + SipAddressesModel::init(); // Register types and load context properties. registerTypes(); @@ -120,6 +122,13 @@ void App::registerTypes () { } ); + qmlRegisterSingletonType( + "Linphone", 1, 0, "SipAddressesModel", + [](QQmlEngine *, QJSEngine *) -> QObject *{ + return SipAddressesModel::getInstance(); + } + ); + qmlRegisterSingletonType( "Linphone", 1, 0, "AccountSettingsModel", [](QQmlEngine *, QJSEngine *) -> QObject *{ @@ -144,6 +153,7 @@ void App::addContextProperties () { qInfo() << "Adding context properties..."; QQmlContext *context = m_engine.rootContext(); + // TODO: Avoid context properties. Use qmlRegister... QQmlComponent component(&m_engine, QUrl(QML_VIEW_CALL_WINDOW)); if (component.isError()) { qWarning() << component.errors(); diff --git a/tests/src/components/chat/ChatProxyModel.cpp b/tests/src/components/chat/ChatProxyModel.cpp index a2007d2a7..7fc845e80 100644 --- a/tests/src/components/chat/ChatProxyModel.cpp +++ b/tests/src/components/chat/ChatProxyModel.cpp @@ -11,7 +11,7 @@ bool ChatModelFilter::filterAcceptsRow (int source_row, const QModelIndex &) con return true; QModelIndex index = sourceModel()->index(source_row, 0, QModelIndex()); - const QVariantMap &data = qvariant_cast(index.data()); + const QVariantMap &data = index.data().toMap(); return data["type"].toInt() == m_entry_type_filter; } diff --git a/tests/src/components/contact/ContactModel.cpp b/tests/src/components/contact/ContactModel.cpp index 08c55c0ad..5e8641cee 100644 --- a/tests/src/components/contact/ContactModel.cpp +++ b/tests/src/components/contact/ContactModel.cpp @@ -6,11 +6,8 @@ using namespace std; // ============================================================================= -const char *ContactModel::NAME = "contact-model"; - ContactModel::ContactModel (shared_ptr linphone_friend) { m_linphone_friend = linphone_friend; - m_linphone_friend->setData(NAME, *this); m_vcard = make_shared(linphone_friend->getVcard()); App::getInstance()->getEngine()->setObjectOwnership(m_vcard.get(), QQmlEngine::CppOwnership); @@ -23,7 +20,6 @@ ContactModel::ContactModel (VcardModel *vcard) { throw std::invalid_argument("A contact is already linked to this vcard."); m_linphone_friend = linphone::Friend::newFromVcard(vcard->m_vcard); - m_linphone_friend->setData(NAME, *this); m_vcard.reset(vcard); engine->setObjectOwnership(vcard, QQmlEngine::CppOwnership); diff --git a/tests/src/components/contact/ContactModel.hpp b/tests/src/components/contact/ContactModel.hpp index 2bc787cc9..52e93ade0 100644 --- a/tests/src/components/contact/ContactModel.hpp +++ b/tests/src/components/contact/ContactModel.hpp @@ -1,11 +1,7 @@ #ifndef CONTACT_MODEL_H_ #define CONTACT_MODEL_H_ -#include -#include - #include "../presence/Presence.hpp" - #include "VcardModel.hpp" // ============================================================================= @@ -25,7 +21,9 @@ public: ContactModel (VcardModel *vcard); ~ContactModel () = default; - static const char *NAME; + std::shared_ptr getVcardModel () const { + return m_vcard; + } public slots: void startEdit () { @@ -48,10 +46,6 @@ private: Presence::PresenceStatus getPresenceStatus () const; Presence::PresenceLevel getPresenceLevel () const; - std::shared_ptr getVcardModel () const { - return m_vcard; - } - VcardModel *getVcardModelPtr () const { return m_vcard.get(); } diff --git a/tests/src/components/contact/VcardModel.hpp b/tests/src/components/contact/VcardModel.hpp index 2b1b08955..9ce5240e1 100644 --- a/tests/src/components/contact/VcardModel.hpp +++ b/tests/src/components/contact/VcardModel.hpp @@ -25,6 +25,7 @@ public: ~VcardModel (); QString getUsername () const; + QVariantList getSipAddresses () const; public slots: bool addSipAddress (const QString &sip_address); @@ -58,7 +59,6 @@ private: bool setAvatar (const QString &path); QVariantMap getAddress () const; - QVariantList getSipAddresses () const; QVariantList getCompanies () const; QVariantList getEmails () const; QVariantList getUrls () const; diff --git a/tests/src/components/contacts/ContactsListModel.cpp b/tests/src/components/contacts/ContactsListModel.cpp index 28b528d9b..f349e054a 100644 --- a/tests/src/components/contacts/ContactsListModel.cpp +++ b/tests/src/components/contacts/ContactsListModel.cpp @@ -77,17 +77,6 @@ bool ContactsListModel::removeRows (int row, int count, const QModelIndex &paren // ----------------------------------------------------------------------------- -ContactModel *ContactsListModel::mapSipAddressToContact (const QString &sipAddress) const { - shared_ptr friend_ = m_linphone_friends->findFriendByUri( - ::Utils::qStringToLinphoneString(sipAddress) - ); - - if (!friend_) - return nullptr; - - return &friend_->getData(ContactModel::NAME); -} - ContactModel *ContactsListModel::addContact (VcardModel *vcard) { ContactModel *contact = new ContactModel(vcard); App::getInstance()->getEngine()->setObjectOwnership(contact, QQmlEngine::CppOwnership); diff --git a/tests/src/components/contacts/ContactsListModel.hpp b/tests/src/components/contacts/ContactsListModel.hpp index 6c0b017b9..f90fb1411 100644 --- a/tests/src/components/contacts/ContactsListModel.hpp +++ b/tests/src/components/contacts/ContactsListModel.hpp @@ -12,6 +12,7 @@ class ContactsListModel : public QAbstractListModel { Q_OBJECT; friend class ContactsListProxyModel; + friend class SipAddressesModel; public: ~ContactsListModel () = default; @@ -25,7 +26,7 @@ public: bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override; static void init () { - if (!ContactsListModel::m_instance) { + if (!m_instance) { m_instance = new ContactsListModel(); } } @@ -35,8 +36,6 @@ public: } public slots: - ContactModel *mapSipAddressToContact (const QString &sipAddress) const; - ContactModel *addContact (VcardModel *vcard); void removeContact (ContactModel *contact); diff --git a/tests/src/components/contacts/ContactsListProxyModel.cpp b/tests/src/components/contacts/ContactsListProxyModel.cpp index a1048d3cc..60eea9722 100644 --- a/tests/src/components/contacts/ContactsListProxyModel.cpp +++ b/tests/src/components/contacts/ContactsListProxyModel.cpp @@ -49,7 +49,7 @@ bool ContactsListProxyModel::filterAcceptsRow ( const QModelIndex &source_parent ) const { QModelIndex index = sourceModel()->index(source_row, 0, source_parent); - const ContactModel *contact = qvariant_cast(index.data()); + const ContactModel *contact = index.data().value(); m_weights[contact] = static_cast(computeContactWeight(*contact)); @@ -60,8 +60,8 @@ bool ContactsListProxyModel::filterAcceptsRow ( } bool ContactsListProxyModel::lessThan (const QModelIndex &left, const QModelIndex &right) const { - const ContactModel *contact_a = qvariant_cast(sourceModel()->data(left)); - const ContactModel *contact_b = qvariant_cast(sourceModel()->data(right)); + const ContactModel *contact_a = sourceModel()->data(left).value(); + const ContactModel *contact_b = sourceModel()->data(right).value(); unsigned int weight_a = m_weights[contact_a]; unsigned int weight_b = m_weights[contact_b]; diff --git a/tests/src/components/core/CoreManager.hpp b/tests/src/components/core/CoreManager.hpp index bd4723f45..d7f6dca9f 100644 --- a/tests/src/components/core/CoreManager.hpp +++ b/tests/src/components/core/CoreManager.hpp @@ -1,9 +1,6 @@ #ifndef CORE_MANAGER_H_ #define CORE_MANAGER_H_ -#include -#include - #include "../contact/VcardModel.hpp" // ============================================================================= @@ -30,7 +27,7 @@ public: public slots: // Must be used in a qml scene. - // The ownership of `VcardModel` is `QQmlEngine::JavaScriptOwnership` by default. + // Warning: The ownership of `VcardModel` is `QQmlEngine::JavaScriptOwnership` by default. VcardModel *createDetachedVcardModel (); private: diff --git a/tests/src/components/notifier/Notifier.cpp b/tests/src/components/notifier/Notifier.cpp index dc78964a2..e55bcfc4e 100644 --- a/tests/src/components/notifier/Notifier.cpp +++ b/tests/src/components/notifier/Notifier.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -22,7 +23,7 @@ // ============================================================================= inline int getNotificationSize (const QObject &object, const char *property) { - QVariant variant(object.property(property)); + QVariant variant = object.property(property); bool so_far_so_good; int size = variant.toInt(&so_far_so_good); @@ -56,7 +57,7 @@ Notifier::Notifier (QObject *parent) : m_components[Notifier::Call] = new QQmlComponent(engine, QUrl(QML_NOTIFICATION_PATH)); // Check errors. - for (int i = 0; i < Notifier::MaxNbTypes; i++) { + for (int i = 0; i < Notifier::MaxNbTypes; ++i) { QQmlComponent *component = m_components[i]; if (component->isError()) { qWarning() << QStringLiteral("Errors found in `Notification` component %1:").arg(i) << diff --git a/tests/src/components/notifier/Notifier.hpp b/tests/src/components/notifier/Notifier.hpp index 5535322ec..32c99f060 100644 --- a/tests/src/components/notifier/Notifier.hpp +++ b/tests/src/components/notifier/Notifier.hpp @@ -3,10 +3,11 @@ #include #include -#include // ============================================================================= +class QQmlComponent; + class Notifier : public QObject { Q_OBJECT; diff --git a/tests/src/components/sip-addresses/SipAddressModel.cpp b/tests/src/components/sip-addresses/SipAddressModel.cpp deleted file mode 100644 index b267f0ce3..000000000 --- a/tests/src/components/sip-addresses/SipAddressModel.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "SipAddressModel.hpp" - -// ============================================================================= diff --git a/tests/src/components/sip-addresses/SipAddressModel.hpp b/tests/src/components/sip-addresses/SipAddressModel.hpp deleted file mode 100644 index 67270fbd2..000000000 --- a/tests/src/components/sip-addresses/SipAddressModel.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef SIP_ADDRESS_MODEL_H_ -#define SIP_ADDRESS_MODEL_H_ - -#include - -// ============================================================================= - -class SipAddressModel : public QObject { - Q_OBJECT; - -public: -}; - -#endif // SIP_ADDRESS_H_ diff --git a/tests/src/components/sip-addresses/SipAddressesModel.cpp b/tests/src/components/sip-addresses/SipAddressesModel.cpp index 528aabc05..adaba93fd 100644 --- a/tests/src/components/sip-addresses/SipAddressesModel.cpp +++ b/tests/src/components/sip-addresses/SipAddressesModel.cpp @@ -1,3 +1,104 @@ +#include +#include + +#include "../../utils.hpp" +#include "../contacts/ContactsListModel.hpp" +#include "../core/CoreManager.hpp" + #include "SipAddressesModel.hpp" // ============================================================================= + +SipAddressesModel *SipAddressesModel::m_instance = nullptr; + +SipAddressesModel::SipAddressesModel (QObject *parent) : QAbstractListModel(parent) { + shared_ptr core = CoreManager::getInstance()->getCore(); + + // Get sip addresses from chatrooms. + for (const auto &chat_room : core->getChatRooms()) { + list > history = chat_room->getHistory(0); + + if (history.size() == 0) + continue; + + QString sip_address = ::Utils::linphoneStringToQString(chat_room->getPeerAddress()->asString()); + + QVariantMap map; + map["sipAddress"] = sip_address; + map["timestamp"] = QDateTime::fromMSecsSinceEpoch(static_cast(history.back()->getTime()) * 1000); + + m_sip_addresses[sip_address] = map; + } + + // Get sip addresses from calls. + QSet address_done; + for (const auto &call_log : core->getCallLogs()) { + QString sip_address = ::Utils::linphoneStringToQString(call_log->getRemoteAddress()->asString()); + + if (address_done.contains(sip_address)) + continue; // Already used. + address_done << sip_address; + + QVariantMap map; + map["sipAddress"] = sip_address; + map["timestamp"] = QDateTime::fromMSecsSinceEpoch( + static_cast(call_log->getStartDate() + call_log->getDuration()) * 1000 + ); + + auto it = m_sip_addresses.find(sip_address); + if (it == m_sip_addresses.end() || map["timestamp"] > (*it)["timestamp"]) + m_sip_addresses[sip_address] = map; + } + + // Get sip addresses from contacts. + for (auto &contact : ContactsListModel::getInstance()->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 (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(); +} diff --git a/tests/src/components/sip-addresses/SipAddressesModel.hpp b/tests/src/components/sip-addresses/SipAddressesModel.hpp index 3c12c7f7d..22b8acea0 100644 --- a/tests/src/components/sip-addresses/SipAddressesModel.hpp +++ b/tests/src/components/sip-addresses/SipAddressesModel.hpp @@ -3,12 +3,40 @@ #include +#include "../contact/ContactModel.hpp" + // ============================================================================= -class SipAddresses : public QAbstractListModel { +class SipAddressesModel : public QAbstractListModel { Q_OBJECT; public: + ~SipAddressesModel () = default; + + int rowCount (const QModelIndex &index = QModelIndex()) const override; + + QHash roleNames () const override; + QVariant data (const QModelIndex &index, int role) const override; + + static void init () { + if (!m_instance) + m_instance = new SipAddressesModel(); + } + + static SipAddressesModel *getInstance () { + return m_instance; + } + +public slots: + ContactModel *mapSipAddressToContact (const QString &sip_address) const; + +private: + SipAddressesModel (QObject *parent = Q_NULLPTR); + + QHash m_sip_addresses; + QList m_refs; + + static SipAddressesModel *m_instance; }; #endif // SIP_ADDRESSES_MODEL_H_ diff --git a/tests/src/components/sip-addresses/UnregisteredSipAddressesModel.cpp b/tests/src/components/sip-addresses/UnregisteredSipAddressesModel.cpp new file mode 100644 index 000000000..e8716a67f --- /dev/null +++ b/tests/src/components/sip-addresses/UnregisteredSipAddressesModel.cpp @@ -0,0 +1,14 @@ +#include "../sip-addresses/SipAddressesModel.hpp" + +#include "UnregisteredSipAddressesModel.hpp" + +// ============================================================================= + +UnregisteredSipAddressesModel::UnregisteredSipAddressesModel (QObject *parent) : QSortFilterProxyModel(parent) { + setSourceModel(SipAddressesModel::getInstance()); +} + +bool UnregisteredSipAddressesModel::filterAcceptsRow (int source_row, const QModelIndex &source_parent) const { + QModelIndex index = sourceModel()->index(source_row, 0, source_parent); + return index.data().toMap().contains("contact"); +} diff --git a/tests/src/components/sip-addresses/UnregisteredSipAddressesModel.hpp b/tests/src/components/sip-addresses/UnregisteredSipAddressesModel.hpp new file mode 100644 index 000000000..ffc8f6aa5 --- /dev/null +++ b/tests/src/components/sip-addresses/UnregisteredSipAddressesModel.hpp @@ -0,0 +1,19 @@ +#ifndef UNREGISTERED_SIP_ADDRESSES_MODEL_H_ +#define UNREGISTERED_SIP_ADDRESSES_MODEL_H_ + +#include + +// ============================================================================= + +class UnregisteredSipAddressesModel : public QSortFilterProxyModel { + Q_OBJECT; + +public: + UnregisteredSipAddressesModel (QObject *parent = Q_NULLPTR); + ~UnregisteredSipAddressesModel () = default; + +protected: + bool filterAcceptsRow (int source_row, const QModelIndex &source_parent) const override; +}; + + #endif // UNREGISTERED_SIP_ADDRESSES_MODEL_H_ diff --git a/tests/src/components/smart-search-bar/SmartSearchBarModel.cpp b/tests/src/components/smart-search-bar/SmartSearchBarModel.cpp deleted file mode 100644 index 5c486c816..000000000 --- a/tests/src/components/smart-search-bar/SmartSearchBarModel.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "SmartSearchBarModel.hpp" diff --git a/tests/src/components/smart-search-bar/SmartSearchBarModel.hpp b/tests/src/components/smart-search-bar/SmartSearchBarModel.hpp deleted file mode 100644 index 166d8dce3..000000000 --- a/tests/src/components/smart-search-bar/SmartSearchBarModel.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef SMART_SEARCH_BAR_MODEL_H_ -#define SMART_SEARCH_BAR_MODEL_H_ - -class SmartSearchBarModel { - - -}; - -#endif // SMART_SEARCH_BAR_MODEL_H_ diff --git a/tests/src/components/smart-search-bar/SmartSearchBarProxyModel.cpp b/tests/src/components/smart-search-bar/SmartSearchBarProxyModel.cpp deleted file mode 100644 index e6e04783c..000000000 --- a/tests/src/components/smart-search-bar/SmartSearchBarProxyModel.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "SmartSearchBarProxyModel.hpp" diff --git a/tests/src/components/smart-search-bar/SmartSearchBarProxyModel.hpp b/tests/src/components/smart-search-bar/SmartSearchBarProxyModel.hpp deleted file mode 100644 index 7057fc024..000000000 --- a/tests/src/components/smart-search-bar/SmartSearchBarProxyModel.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef SMART_SEARCH_BAR_PROXY_MODEL_H_ -#define SMART_SEARCH_BAR_PROXY_MODEL_H_ - -class SmartSearchBarProxyModel { - - -}; - -#endif // SMART_SEARCH_BAR_PROXY_MODEL_H_ diff --git a/tests/src/components/timeline/TimelineModel.cpp b/tests/src/components/timeline/TimelineModel.cpp index 9e9179ef1..88ae7f234 100644 --- a/tests/src/components/timeline/TimelineModel.cpp +++ b/tests/src/components/timeline/TimelineModel.cpp @@ -1,36 +1,12 @@ -#include - -#include -#include -#include - -#include "../../utils.hpp" -#include "../contacts/ContactsListModel.hpp" -#include "../core/CoreManager.hpp" +#include "../sip-addresses/SipAddressesModel.hpp" #include "TimelineModel.hpp" -using namespace std; +// ============================================================================= -// =================================================================== - -TimelineModel::TimelineModel (QObject *parent) : QAbstractListModel(parent) { - init_entries(); - - // Invalidate model if a contact is removed. - // Better than compare each sip address. - connect( - ContactsListModel::getInstance(), &ContactsListModel::rowsRemoved, this, - [this](const QModelIndex &, int, int) { - beginResetModel(); - // Nothing. - endResetModel(); - } - ); -} - -int TimelineModel::rowCount (const QModelIndex &) const { - return m_entries.count(); +TimelineModel::TimelineModel (QObject *parent) : QSortFilterProxyModel(parent) { + setSourceModel(SipAddressesModel::getInstance()); + sort(0); } QHash TimelineModel::roleNames () const { @@ -39,96 +15,16 @@ QHash TimelineModel::roleNames () const { return roles; } -QVariant TimelineModel::data (const QModelIndex &index, int role) const { - int row = index.row(); +// ----------------------------------------------------------------------------- - if (row < 0 || row >= m_entries.count()) - return QVariant(); - - if (role == Qt::DisplayRole) - return m_entries[row]; - - return QVariant(); +bool TimelineModel::filterAcceptsRow (int source_row, const QModelIndex &source_parent) const { + QModelIndex index = sourceModel()->index(source_row, 0, source_parent); + return index.data().toMap().contains("timestamp"); } -// ------------------------------------------------------------------- +bool TimelineModel::lessThan (const QModelIndex &left, const QModelIndex &right) const { + const QVariantMap &sip_address_a = sourceModel()->data(left).toMap(); + const QVariantMap &sip_address_b = sourceModel()->data(right).toMap(); -void TimelineModel::init_entries () { - // Returns an iterator entry position to insert a new entry. - auto search_entry = [this]( - const QVariantMap &map, - const QList >::iterator *start = NULL - ) { - return lower_bound( - start ? *start : m_entries.begin(), m_entries.end(), map, - [](const QVariantMap &a, const QVariantMap &b) { - return a["timestamp"] > b["timestamp"]; - } - ); - }; - - shared_ptr core(CoreManager::getInstance()->getCore()); - - // Insert chat rooms events. - for (const auto &chat_room : core->getChatRooms()) { - list > history = chat_room->getHistory(0); - - if (history.size() == 0) - continue; - - // Last message must be at the end of history. - shared_ptr message = history.back(); - - // Insert event message in timeline entries. - QVariantMap map; - map["timestamp"] = QDateTime::fromMSecsSinceEpoch( - static_cast(message->getTime()) * 1000 - ); - map["sipAddresses"] = ::Utils::linphoneStringToQString( - chat_room->getPeerAddress()->asString() - ); - - m_entries.insert(search_entry(map), map); - } - - // Insert calls events. - QSet address_done; - for (const auto &call_log : core->getCallLogs()) { - // Get a sip uri to check. - QString address = ::Utils::linphoneStringToQString( - call_log->getRemoteAddress()->asString() - ); - - if (address_done.contains(address)) - continue; // Already used. - - address_done << address; - - // Make a new map. - QVariantMap map; - map["timestamp"] = QDateTime::fromMSecsSinceEpoch( - static_cast(call_log->getStartDate() + call_log->getDuration()) * 1000 - ); - map["sipAddresses"] = address; - - // Search existing entry. - auto it = find_if( - m_entries.begin(), m_entries.end(), [&address](const QVariantMap &map) { - return address == map["sipAddresses"].toString(); - } - ); - - // Is it a new entry? - if (it == m_entries.cend()) - m_entries.insert(search_entry(map), map); - else if (map["timestamp"] > (*it)["timestamp"]) { - // Remove old entry and insert. - it = m_entries.erase(it); - - if (it != m_entries.cbegin()) - it--; - - m_entries.insert(search_entry(map, &it), map); - } - } + return sip_address_a["timestamp"] > sip_address_b["timestamp"]; } diff --git a/tests/src/components/timeline/TimelineModel.hpp b/tests/src/components/timeline/TimelineModel.hpp index c8420d3fd..43e019e29 100644 --- a/tests/src/components/timeline/TimelineModel.hpp +++ b/tests/src/components/timeline/TimelineModel.hpp @@ -1,30 +1,22 @@ #ifndef TIMELINE_MODEL_H_ #define TIMELINE_MODEL_H_ -#include - -class ContactsListModel; +#include // ============================================================================= -class TimelineModel : public QAbstractListModel { +class TimelineModel : public QSortFilterProxyModel { Q_OBJECT; public: TimelineModel (QObject *parent = Q_NULLPTR); + ~TimelineModel () = default; - int rowCount (const QModelIndex &) const override; QHash roleNames () const override; - QVariant data (const QModelIndex &index, int role) const override; -private: - void init_entries (); - - // A timeline enty is a object that contains: - // - A QDateTime `timestamp`. - // - A `sipAddresses` value, if it exists only one address, it's - // a string, otherwise it's a string array. - QList m_entries; +protected: + bool filterAcceptsRow (int source_row, const QModelIndex &source_parent) const override; + bool lessThan (const QModelIndex &left, const QModelIndex &right) const override; }; #endif // TIMELINE_MODEL_H_ diff --git a/tests/ui/modules/Linphone/Chat/Chat.qml b/tests/ui/modules/Linphone/Chat/Chat.qml index 1ed024cc7..ab381dd82 100644 --- a/tests/ui/modules/Linphone/Chat/Chat.qml +++ b/tests/ui/modules/Linphone/Chat/Chat.qml @@ -11,7 +11,7 @@ import Linphone.Styles 1.0 ColumnLayout { property alias proxyModel: chat.model - property var _contact: ContactsListModel.mapSipAddressToContact( + property var _contact: SipAddressesModel.mapSipAddressToContact( proxyModel.sipAddress ) || proxyModel.sipAddress diff --git a/tests/ui/modules/Linphone/Contact/Contact.qml b/tests/ui/modules/Linphone/Contact/Contact.qml index 875140b14..dd729d317 100644 --- a/tests/ui/modules/Linphone/Contact/Contact.qml +++ b/tests/ui/modules/Linphone/Contact/Contact.qml @@ -15,7 +15,7 @@ Rectangle { property alias sipAddressColor: description.sipAddressColor property alias usernameColor: description.usernameColor property string sipAddress - property var _contact: ContactsListModel.mapSipAddressToContact(sipAddress) + property var _contact: SipAddressesModel.mapSipAddressToContact(sipAddress) color: 'transparent' // No color by default. height: ContactStyle.height diff --git a/tests/ui/modules/Linphone/Timeline.qml b/tests/ui/modules/Linphone/Timeline.qml index 75e4423a3..54b7f85f0 100644 --- a/tests/ui/modules/Linphone/Timeline.qml +++ b/tests/ui/modules/Linphone/Timeline.qml @@ -66,17 +66,17 @@ ColumnLayout { delegate: Item { property var contact: { Utils.assert( - !Utils.isArray($timelineEntry.sipAddresses), + !Utils.isArray($timelineEntry.sipAddress), 'Conferences are not supported at this moment.' ) - return ContactsListModel.mapSipAddressToContact( - $timelineEntry.sipAddresses - ) || $timelineEntry.sipAddresses + return SipAddressesModel.mapSipAddressToContact( + $timelineEntry.sipAddress + ) || $timelineEntry.sipAddress } height: TimelineStyle.contact.height - width: parent.width + width: parent ? parent.width : 0 Contact { anchors.fill: parent @@ -87,7 +87,7 @@ ColumnLayout { ? TimelineStyle.contact.backgroundColor.a : TimelineStyle.contact.backgroundColor.b ) - sipAddress: $timelineEntry.sipAddresses + sipAddress: $timelineEntry.sipAddress sipAddressColor: view.currentIndex === index ? TimelineStyle.contact.sipAddress.color.selected : TimelineStyle.contact.sipAddress.color.normal @@ -110,7 +110,7 @@ ColumnLayout { anchors.fill: parent onClicked: { view.currentIndex = index - timeline.entrySelected($timelineEntry.sipAddresses) + timeline.entrySelected($timelineEntry.sipAddress) } } } diff --git a/tests/ui/views/App/Calls/AbstractStartingCall.qml b/tests/ui/views/App/Calls/AbstractStartingCall.qml index 56cdd6a1f..86f4a9dab 100644 --- a/tests/ui/views/App/Calls/AbstractStartingCall.qml +++ b/tests/ui/views/App/Calls/AbstractStartingCall.qml @@ -18,7 +18,7 @@ Rectangle { property bool isVideoCall: false property string sipAddress - property var _contact: ContactsListModel.mapSipAddressToContact( + property var _contact: SipAddressesModel.mapSipAddressToContact( sipAddress ) || sipAddress diff --git a/tests/ui/views/App/Calls/Incall.qml b/tests/ui/views/App/Calls/Incall.qml index 32928ac54..7580b0216 100644 --- a/tests/ui/views/App/Calls/Incall.qml +++ b/tests/ui/views/App/Calls/Incall.qml @@ -16,7 +16,7 @@ Rectangle { property bool isVideoCall: false property string sipAddress - property var _contact: ContactsListModel.mapSipAddressToContact( + property var _contact: SipAddressesModel.mapSipAddressToContact( sipAddress ) || sipAddress diff --git a/tests/ui/views/App/MainWindow/ContactEdit.qml b/tests/ui/views/App/MainWindow/ContactEdit.qml index 8345aa15c..3b63cb3fa 100644 --- a/tests/ui/views/App/MainWindow/ContactEdit.qml +++ b/tests/ui/views/App/MainWindow/ContactEdit.qml @@ -75,7 +75,7 @@ ColumnLayout { spacing: 0 Component.onCompleted: { - _contact = ContactsListModel.mapSipAddressToContact(sipAddress) + _contact = SipAddressesModel.mapSipAddressToContact(sipAddress) if (!_contact) { _vcard = CoreManager.createDetachedVcardModel() diff --git a/tests/ui/views/App/MainWindow/Conversation.qml b/tests/ui/views/App/MainWindow/Conversation.qml index 7f33f3a71..80ef4f427 100644 --- a/tests/ui/views/App/MainWindow/Conversation.qml +++ b/tests/ui/views/App/MainWindow/Conversation.qml @@ -15,7 +15,7 @@ ColumnLayout { property string sipAddress - property var _contact: ContactsListModel.mapSipAddressToContact( + property var _contact: SipAddressesModel.mapSipAddressToContact( sipAddress ) || sipAddress