Commit bcee4d9d authored by Ronan Abhamon's avatar Ronan Abhamon

unstable, supports calls in chat

parent 74be0201
......@@ -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
......
......@@ -194,6 +194,10 @@
<source>endCall</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>outgoingCall</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Home</name>
......
......@@ -194,6 +194,10 @@
<source>endCall</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>outgoingCall</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Home</name>
......
......@@ -4,7 +4,7 @@
#include <QQuickView>
#include <QtDebug>
#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<ContactsListProxyModel>("Linphone", 1, 0, "ContactsListProxyModel");
qmlRegisterType<ChatModel>("Linphone", 1, 0, "ChatModel");
qmlRegisterType<ChatProxyModel>("Linphone", 1, 0, "ChatProxyModel");
// Register singletons.
qmlRegisterSingletonType<ContactsListModel>(
......
#include <algorithm>
#include <QDateTime>
#include <QtDebug>
......@@ -79,6 +81,38 @@ void ChatModel::removeAllEntries () {
// -------------------------------------------------------------------
void ChatModel::fillMessageEntry (
QVariantMap &dest,
const shared_ptr<linphone::ChatMessage> &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<linphone::CallLog> &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<linphone::CallLog> &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<linphone::CallLog>(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<linphone::Core> 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<void>(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<void>(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')
......@@ -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<QVariantMap, std::shared_ptr<void> > ChatEntryData;
void fillMessageEntry (
QVariantMap &dest,
const std::shared_ptr<linphone::ChatMessage> &message
);
void fillCallStartEntry (
QVariantMap &dest,
const std::shared_ptr<linphone::CallLog> &call_log
);
void fillCallEndEntry (
QVariantMap &dest,
const std::shared_ptr<linphone::CallLog> &call_log
);
void removeEntry (ChatEntryData &pair);
QString getSipAddress () const;
......
#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.
}
#ifndef CHAT_PROXY_MODEL_H_
#define CHAT_PROXY_MODEL_H_
#include <QSortFilterProxyModel>
#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_
......@@ -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 {
......
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
}
......
......@@ -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
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment