diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e640e4ed9..49bc8c02f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -35,6 +35,7 @@ set(SOURCES src/app/DefaultTranslator.cpp src/app/Logger.cpp src/components/chat/ChatModel.cpp + src/components/chat/ChatModelFilter.cpp src/components/chat/ChatProxyModel.cpp src/components/contacts/ContactModel.cpp src/components/contacts/ContactsListModel.cpp @@ -55,6 +56,7 @@ set(HEADERS src/app/DefaultTranslator.hpp src/app/Logger.hpp src/components/chat/ChatModel.hpp + src/components/chat/ChatModelFilter.hpp src/components/chat/ChatProxyModel.hpp src/components/contacts/ContactModel.hpp src/components/contacts/ContactsListModel.hpp diff --git a/tests/assets/languages/fr.ts b/tests/assets/languages/fr.ts index ef856f80c..e6dd29cbd 100644 --- a/tests/assets/languages/fr.ts +++ b/tests/assets/languages/fr.ts @@ -139,7 +139,7 @@ removeAllEntriesTitle - Suppression de l'historique + Suppression de l'historique @@ -184,7 +184,7 @@ endedCall - Fin d'appel + Fin d'appel missedIncomingCall diff --git a/tests/src/components/chat/ChatModelFilter.cpp b/tests/src/components/chat/ChatModelFilter.cpp new file mode 100644 index 000000000..5dcb45e17 --- /dev/null +++ b/tests/src/components/chat/ChatModelFilter.cpp @@ -0,0 +1,19 @@ +#include "ChatProxyModel.hpp" + +// =================================================================== + +ChatModelFilter::ChatModelFilter (QObject *parent) : QSortFilterProxyModel(parent) { + setSourceModel(&m_chat_model); +} + +bool ChatModelFilter::filterAcceptsRow (int source_row, const QModelIndex &source_parent) const { + if (m_entry_type_filter == ChatModel::EntryType::GenericEntry) + return true; + + QModelIndex index = sourceModel()->index(source_row, 0, QModelIndex()); + const QVariantMap &data = qvariant_cast( + index.data() + ); + + return data["type"].toInt() == m_entry_type_filter; +} diff --git a/tests/src/components/chat/ChatModelFilter.hpp b/tests/src/components/chat/ChatModelFilter.hpp new file mode 100644 index 000000000..9dc79acb9 --- /dev/null +++ b/tests/src/components/chat/ChatModelFilter.hpp @@ -0,0 +1,35 @@ +#ifndef CHAT_MODEL_FILTER_H_ +#define CHAT_MODEL_FILTER_H_ + +#include + +#include "ChatModel.hpp" +#include + +// =================================================================== +// Fetch K filtered chat entries. +// =================================================================== + +class ChatModelFilter : public QSortFilterProxyModel { + friend class ChatProxyModel; + + Q_OBJECT; + +public: + ChatModelFilter (QObject *parent = Q_NULLPTR); + +protected: + bool filterAcceptsRow (int source_row, const QModelIndex &source_parent) const; + +private: + void setEntryTypeFilter (ChatModel::EntryType type) { + m_entry_type_filter = type; + invalidateFilter(); + } + + ChatModel m_chat_model; + + ChatModel::EntryType m_entry_type_filter = ChatModel::EntryType::GenericEntry; +}; + +#endif // CHAT_MODEL_FILTER_H_ diff --git a/tests/src/components/chat/ChatProxyModel.cpp b/tests/src/components/chat/ChatProxyModel.cpp index 6d4e77777..5f81db84f 100644 --- a/tests/src/components/chat/ChatProxyModel.cpp +++ b/tests/src/components/chat/ChatProxyModel.cpp @@ -2,25 +2,37 @@ // =================================================================== +const unsigned int ChatProxyModel::ENTRIES_CHUNK_SIZE = 25; + ChatProxyModel::ChatProxyModel (QObject *parent) : QSortFilterProxyModel(parent) { - m_chat_model.setParent(this); - setSourceModel(&m_chat_model); + setSourceModel(&m_chat_model_filter); +} + +int ChatProxyModel::rowCount (const QModelIndex &parent) const { + int size = QSortFilterProxyModel::rowCount(parent); + return size < m_n_max_displayed_entries ? size : m_n_max_displayed_entries; +} + +QVariant ChatProxyModel::data (const QModelIndex &index, int role) const { + QAbstractItemModel *model = sourceModel(); + + return model->data( + model->index( + mapToSource(index).row() + (model->rowCount() - rowCount()), + 0 + ), + role + ); +} + +void ChatProxyModel::loadMoreEntries () { + // TODO. } void ChatProxyModel::removeEntry (int id) { - m_chat_model.removeEntry( - mapToSource(index(id, 0)).row() + QModelIndex source_index = mapToSource(index(id, 0)); + + static_cast(m_chat_model_filter.sourceModel())->removeEntry( + mapToSource(source_index).row() ); } - -bool ChatProxyModel::filterAcceptsRow (int source_row, const QModelIndex &source_parent) const { - if (m_entry_type_filter == ChatModel::EntryType::GenericEntry) - return true; - - QModelIndex index = sourceModel()->index(source_row, 0, source_parent); - const QVariantMap &data = qvariant_cast( - index.data() - ); - - return data["type"].toInt() == m_entry_type_filter; -} diff --git a/tests/src/components/chat/ChatProxyModel.hpp b/tests/src/components/chat/ChatProxyModel.hpp index 78f3a46f9..5a13dbf2c 100644 --- a/tests/src/components/chat/ChatProxyModel.hpp +++ b/tests/src/components/chat/ChatProxyModel.hpp @@ -1,10 +1,10 @@ #ifndef CHAT_PROXY_MODEL_H_ #define CHAT_PROXY_MODEL_H_ -#include - -#include "ChatModel.hpp" +#include "ChatModelFilter.hpp" +// =================================================================== +// Fetch the L last filtered chat entries. // =================================================================== class ChatProxyModel : public QSortFilterProxyModel { @@ -23,32 +23,38 @@ signals: public: ChatProxyModel (QObject *parent = Q_NULLPTR); + int rowCount (const QModelIndex &parent = QModelIndex()) const override; + QVariant data (const QModelIndex &index, int role) const override; + public slots: + void loadMoreEntries (); + + void setEntryTypeFilter (ChatModel::EntryType type) { + m_chat_model_filter.setEntryTypeFilter(type); + } + void removeEntry (int id); void removeAllEntries () { - m_chat_model.removeAllEntries(); + static_cast(m_chat_model_filter.sourceModel())->removeAllEntries(); } - void setEntryTypeFilter (ChatModel::EntryType type) { - m_entry_type_filter = type; - invalidateFilter(); - } - -protected: - bool filterAcceptsRow (int source_row, const QModelIndex &source_parent) const; - private: QString getSipAddress () const { - return m_chat_model.getSipAddress(); + static_cast(m_chat_model_filter.sourceModel())->getSipAddress(); } void setSipAddress (const QString &sip_address) { - m_chat_model.setSipAddress(sip_address); + static_cast(m_chat_model_filter.sourceModel())->setSipAddress( + sip_address + ); } - ChatModel m_chat_model; - ChatModel::EntryType m_entry_type_filter = ChatModel::EntryType::GenericEntry; + ChatModelFilter m_chat_model_filter; + + unsigned int m_n_max_displayed_entries = ENTRIES_CHUNK_SIZE; + + static const unsigned int ENTRIES_CHUNK_SIZE; }; #endif // CHAT_PROXY_MODEL_H_ diff --git a/tests/ui/modules/Linphone/Chat/Chat.qml b/tests/ui/modules/Linphone/Chat/Chat.qml index 8ce0e83da..b0a50e0cf 100644 --- a/tests/ui/modules/Linphone/Chat/Chat.qml +++ b/tests/ui/modules/Linphone/Chat/Chat.qml @@ -21,6 +21,18 @@ ColumnLayout { ScrollableListView { id: chat + property bool _tryToLoadMoreEntries: false + + function _loadMoreEntries () { + if (chat.contentY > 500 || _tryToLoadMoreEntries) { + return + } + + _tryToLoadMoreEntries = true + + proxyModel.loadMoreEntries() + } + Layout.fillHeight: true Layout.fillWidth: true @@ -164,6 +176,8 @@ ColumnLayout { } } } + + onContentYChanged: _loadMoreEntries() } // -----------------------------------------------------------------