diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 00f123e32..6328be1b0 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -34,6 +34,7 @@ set(SOURCES
src/app/Database.cpp
src/app/Logger.cpp
src/components/chat/ChatModel.cpp
+ src/components/chat/ChatProxyModel.cpp
src/components/contacts/ContactModel.cpp
src/components/contacts/ContactsListModel.cpp
src/components/contacts/ContactsListProxyModel.cpp
@@ -52,6 +53,7 @@ set(HEADERS
src/app/Database.hpp
src/app/Logger.hpp
src/components/chat/ChatModel.hpp
+ src/components/chat/ChatProxyModel.hpp
src/components/contacts/ContactModel.hpp
src/components/contacts/ContactsListModel.hpp
src/components/contacts/ContactsListProxyModel.hpp
diff --git a/tests/assets/languages/en.ts b/tests/assets/languages/en.ts
index 8a6e05fdb..251a18aff 100644
--- a/tests/assets/languages/en.ts
+++ b/tests/assets/languages/en.ts
@@ -194,6 +194,10 @@
endCall
+
+ outgoingCall
+
+
Home
diff --git a/tests/assets/languages/fr.ts b/tests/assets/languages/fr.ts
index e6c13f001..945d1f9af 100644
--- a/tests/assets/languages/fr.ts
+++ b/tests/assets/languages/fr.ts
@@ -194,6 +194,10 @@
endCall
+
+ outgoingCall
+
+
Home
diff --git a/tests/src/app/App.cpp b/tests/src/app/App.cpp
index a060892aa..4362886a4 100644
--- a/tests/src/app/App.cpp
+++ b/tests/src/app/App.cpp
@@ -4,7 +4,7 @@
#include
#include
-#include "../components/chat/ChatModel.hpp"
+#include "../components/chat/ChatProxyModel.hpp"
#include "../components/contacts/ContactModel.hpp"
#include "../components/contacts/ContactsListModel.hpp"
#include "../components/contacts/ContactsListProxyModel.hpp"
@@ -99,6 +99,7 @@ void App::registerTypes () {
qmlRegisterType("Linphone", 1, 0, "ContactsListProxyModel");
qmlRegisterType("Linphone", 1, 0, "ChatModel");
+ qmlRegisterType("Linphone", 1, 0, "ChatProxyModel");
// Register singletons.
qmlRegisterSingletonType(
diff --git a/tests/src/components/chat/ChatModel.cpp b/tests/src/components/chat/ChatModel.cpp
index 97d2fe877..0671e7457 100644
--- a/tests/src/components/chat/ChatModel.cpp
+++ b/tests/src/components/chat/ChatModel.cpp
@@ -1,3 +1,5 @@
+#include
+
#include
#include
@@ -79,6 +81,38 @@ void ChatModel::removeAllEntries () {
// -------------------------------------------------------------------
+void ChatModel::fillMessageEntry (
+ QVariantMap &dest,
+ const shared_ptr &message
+) {
+ dest["type"] = EntryType::MessageEntry;
+ dest["timestamp"] = QDateTime::fromTime_t(message->getTime());
+ dest["content"] = Utils::linphoneStringToQString(
+ message->getText()
+ );
+ dest["isOutgoing"] = message->isOutgoing();
+}
+
+void ChatModel::fillCallStartEntry (
+ QVariantMap &dest,
+ const std::shared_ptr &call_log
+) {
+ QDateTime timestamp = QDateTime::fromTime_t(call_log->getStartDate());
+
+ dest["type"] = EntryType::CallEntry;
+ dest["timestamp"] = timestamp;
+ dest["isOutgoing"] = call_log->getDir() == linphone::CallDirOutgoing;
+ dest["status"] = call_log->getStatus();
+}
+
+void ChatModel::fillCallEndEntry (
+ QVariantMap &dest,
+ const std::shared_ptr &call_log
+) {
+
+
+}
+
void ChatModel::removeEntry (ChatEntryData &pair) {
int type = pair.first["type"].toInt();
@@ -89,7 +123,9 @@ void ChatModel::removeEntry (ChatEntryData &pair) {
);
break;
case ChatModel::CallEntry:
-
+ CoreManager::getInstance()->getCore()->removeCallLog(
+ static_pointer_cast(pair.second)
+ );
break;
default:
qWarning() << "Unknown chat entry type:" << type;
@@ -114,29 +150,42 @@ void ChatModel::setSipAddress (const QString &sip_address) {
// Invalid old sip address entries.
m_entries.clear();
- m_chat_room =
- CoreManager::getInstance()->getCore()->getChatRoomFromUri(
- Utils::qStringToLinphoneString(sip_address)
- );
+ shared_ptr core = CoreManager::getInstance()->getCore();
+ string std_sip_address = Utils::qStringToLinphoneString(sip_address);
+
+ m_chat_room = core->getChatRoomFromUri(std_sip_address);
// Get messages.
for (auto &message : m_chat_room->getHistory(0)) {
QVariantMap map;
- map["type"] = EntryType::MessageEntry;
- map["timestamp"] = QDateTime::fromTime_t(message->getTime());
- map["content"] = Utils::linphoneStringToQString(
- message->getText()
- );
- map["isOutgoing"] = message->isOutgoing();
-
+ fillMessageEntry(map, message);
m_entries << qMakePair(map, static_pointer_cast(message));
}
// Get calls.
- // TODO.
+ for (auto &call_log : core->getCallHistoryForAddress(m_chat_room->getPeerAddress())) {
+ QVariantMap start, end;
+ fillCallStartEntry(start, call_log);
+
+ ChatEntryData pair = qMakePair(start, static_pointer_cast(call_log));
+
+ auto it = lower_bound(
+ m_entries.begin(), m_entries.end(), pair,
+ [](const ChatEntryData &a, const ChatEntryData &b) {
+ return a.first["timestamp"] < b.first["timestamp"];
+ }
+ );
+
+ m_entries.insert(it, pair);
+ }
endResetModel();
emit sipAddressChanged(sip_address);
}
+
+ // QT_TR_NOOP('endCall'),
+ // QT_TR_NOOP('incomingCall'),
+ // QT_TR_NOOP('lostIncomingCall'),
+ // QT_TR_NOOP('lostOutgoingCall')
diff --git a/tests/src/components/chat/ChatModel.hpp b/tests/src/components/chat/ChatModel.hpp
index 398454684..4df253047 100644
--- a/tests/src/components/chat/ChatModel.hpp
+++ b/tests/src/components/chat/ChatModel.hpp
@@ -7,6 +7,8 @@
// ===================================================================
class ChatModel : public QAbstractListModel {
+ friend class ChatProxyModel;
+
Q_OBJECT;
Q_PROPERTY(
@@ -16,6 +18,9 @@ class ChatModel : public QAbstractListModel {
NOTIFY sipAddressChanged
);
+signals:
+ void sipAddressChanged (const QString &sipAddress);
+
public:
enum Roles {
ChatEntry = Qt::DisplayRole,
@@ -28,6 +33,13 @@ public:
};
Q_ENUM(EntryType);
+ enum CallStatus {
+ CallStatusDeclined = linphone::CallStatusDeclined,
+ CallStatusMissed = linphone::CallStatusMissed,
+ CallStatusSuccess = linphone::CallStatusSuccess
+ };
+ Q_ENUM(CallStatus);
+
ChatModel (QObject *parent = Q_NULLPTR) : QAbstractListModel(parent) {}
int rowCount (const QModelIndex &index = QModelIndex()) const {
@@ -44,12 +56,24 @@ public slots:
void removeEntry (int id);
void removeAllEntries ();
-signals:
- void sipAddressChanged (const QString &sipAddress);
-
private:
typedef QPair > ChatEntryData;
+ void fillMessageEntry (
+ QVariantMap &dest,
+ const std::shared_ptr &message
+ );
+
+ void fillCallStartEntry (
+ QVariantMap &dest,
+ const std::shared_ptr &call_log
+ );
+
+ void fillCallEndEntry (
+ QVariantMap &dest,
+ const std::shared_ptr &call_log
+ );
+
void removeEntry (ChatEntryData &pair);
QString getSipAddress () const;
diff --git a/tests/src/components/chat/ChatProxyModel.cpp b/tests/src/components/chat/ChatProxyModel.cpp
new file mode 100644
index 000000000..80173afa3
--- /dev/null
+++ b/tests/src/components/chat/ChatProxyModel.cpp
@@ -0,0 +1,13 @@
+#include "ChatProxyModel.hpp"
+
+// ===================================================================
+
+ChatProxyModel::ChatProxyModel (QObject *parent) : QSortFilterProxyModel(parent) {
+ m_chat_model.setParent(this);
+ setSourceModel(&m_chat_model);
+ setFilterCaseSensitivity(Qt::CaseInsensitive);
+}
+
+bool ChatProxyModel::filterAcceptsRow (int source_row, const QModelIndex &source_parent) const {
+ return true; // TODO.
+}
diff --git a/tests/src/components/chat/ChatProxyModel.hpp b/tests/src/components/chat/ChatProxyModel.hpp
new file mode 100644
index 000000000..be3a0198d
--- /dev/null
+++ b/tests/src/components/chat/ChatProxyModel.hpp
@@ -0,0 +1,44 @@
+#ifndef CHAT_PROXY_MODEL_H_
+#define CHAT_PROXY_MODEL_H_
+
+#include
+
+#include "ChatModel.hpp"
+
+class ChatProxyModel : public QSortFilterProxyModel {
+ Q_OBJECT;
+
+ Q_PROPERTY(
+ QString sipAddress
+ READ getSipAddress
+ WRITE setSipAddress
+ NOTIFY sipAddressChanged
+ );
+
+signals:
+ void sipAddressChanged (const QString &sipAddress);
+
+public:
+ ChatProxyModel (QObject *parent = Q_NULLPTR);
+
+public slots:
+ ChatModel *getChatModel () {
+ return &m_chat_model;
+ }
+
+protected:
+ bool filterAcceptsRow (int source_row, const QModelIndex &source_parent) const;
+
+private:
+ QString getSipAddress () const {
+ return m_chat_model.getSipAddress();
+ }
+
+ void setSipAddress (const QString &sip_address) {
+ m_chat_model.setSipAddress(sip_address);
+ }
+
+ ChatModel m_chat_model;
+};
+
+#endif // CHAT_PROXY_MODEL_H_
diff --git a/tests/ui/modules/Linphone/Chat/Chat.qml b/tests/ui/modules/Linphone/Chat/Chat.qml
index 340fdc4e2..1a4aad23d 100644
--- a/tests/ui/modules/Linphone/Chat/Chat.qml
+++ b/tests/ui/modules/Linphone/Chat/Chat.qml
@@ -11,6 +11,7 @@ import Linphone.Styles 1.0
ColumnLayout {
property var contact
+ // Can be a model or a proxy chat model.
property alias model: chat.model
// -----------------------------------------------------------------
@@ -80,12 +81,18 @@ ColumnLayout {
delegate: Rectangle {
id: entry
+ // Chat supports model and proxy model.
+ function getModel () {
+ var model = chat.model
+ return model.getChatModel ? model.getChatModel() : model
+ }
+
function isHoverEntry () {
return mouseArea.containsMouse
}
function removeEntry () {
- chat.model.removeEntry(index)
+ getModel().removeEntry(index)
}
anchors {
diff --git a/tests/ui/modules/Linphone/Chat/Event.qml b/tests/ui/modules/Linphone/Chat/Event.qml
index 94eb696a4..06722836e 100644
--- a/tests/ui/modules/Linphone/Chat/Event.qml
+++ b/tests/ui/modules/Linphone/Chat/Event.qml
@@ -1,18 +1,27 @@
import QtQuick 2.7
import Common 1.0
+import Linphone 1.0
import Linphone.Styles 1.0
import Utils 1.0
// ===================================================================
Row {
+ property string _type: {
+ if ($chatEntry.status === ChatModel.CallStatusSuccess) {
+ return $chatEntry.isOutgoing ? 'outgoing_call' : 'incoming_call'
+ }
+
+ return ''
+ }
+
height: ChatStyle.entry.lineHeight
spacing: ChatStyle.entry.message.extraContent.spacing
Icon {
height: parent.height
- icon: $content
+ icon: _type
iconSize: ChatStyle.entry.event.iconSize
width: ChatStyle.entry.metaWidth
}
@@ -25,8 +34,7 @@ Row {
property var i18n: [
QT_TR_NOOP('endCall'),
QT_TR_NOOP('incomingCall'),
- QT_TR_NOOP('lostIncomingCall'),
- QT_TR_NOOP('lostOutgoingCall')
+ QT_TR_NOOP('outgoingCall')
]
}
}
@@ -37,7 +45,7 @@ Row {
pointSize: ChatStyle.entry.event.text.fontSize
}
height: parent.height
- text: qsTr(Utils.snakeToCamel($content))
+ text: qsTr(Utils.snakeToCamel(_type))
verticalAlignment: Text.AlignVCenter
}
diff --git a/tests/ui/views/App/MainWindow/Conversation.qml b/tests/ui/views/App/MainWindow/Conversation.qml
index 239dbcbaf..6cc25ecea 100644
--- a/tests/ui/views/App/MainWindow/Conversation.qml
+++ b/tests/ui/views/App/MainWindow/Conversation.qml
@@ -23,7 +23,7 @@ ColumnLayout {
descriptionText: qsTr('removeAllEntriesDescription'),
exitHandler: function (status) {
if (status) {
- chatModel.removeAllEntries()
+ chatProxyModel.removeAllEntries()
}
},
title: qsTr('removeAllEntriesTitle')
@@ -145,8 +145,8 @@ ColumnLayout {
Layout.fillHeight: true
Layout.fillWidth: true
contact: parent._contact
- model: ChatModel {
- id: chatModel
+ model: ChatProxyModel {
+ id: chatProxyModel
sipAddress: conversation.sipAddress
}