mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-24 07:08:07 +00:00
feat(src/components/chat/ChatModel): can send messages (but crash with wrapper/listener)
This commit is contained in:
parent
41aa40e1e2
commit
735554d421
6 changed files with 113 additions and 27 deletions
|
|
@ -1,5 +1,4 @@
|
|||
#include <bctoolbox/logging.h>
|
||||
#include <bctoolbox/port.h>
|
||||
#include <linphone/linphonecore.h>
|
||||
#include <QDateTime>
|
||||
|
||||
|
|
|
|||
|
|
@ -13,30 +13,66 @@ using namespace std;
|
|||
|
||||
// =============================================================================
|
||||
|
||||
class ChatModel::MessageHandlers : public linphone::ChatMessageListener {
|
||||
void onFileTransferRecv (
|
||||
const shared_ptr<linphone::ChatMessage> &message,
|
||||
const shared_ptr<linphone::Content> &content,
|
||||
const shared_ptr<linphone::Buffer> &buffer
|
||||
) override {
|
||||
qDebug() << "Not yet implemented";
|
||||
}
|
||||
|
||||
shared_ptr<linphone::Buffer> onFileTransferSend (
|
||||
const shared_ptr<linphone::ChatMessage> &message,
|
||||
const shared_ptr<linphone::Content> &content,
|
||||
size_t offset,
|
||||
size_t size
|
||||
) override {
|
||||
qDebug() << "Not yet implemented";
|
||||
}
|
||||
|
||||
void onFileTransferProgressIndication (
|
||||
const shared_ptr<linphone::ChatMessage> &message,
|
||||
const shared_ptr<linphone::Content> &content,
|
||||
size_t offset,
|
||||
size_t total
|
||||
) override {
|
||||
qDebug() << "Not yet implemented";
|
||||
}
|
||||
|
||||
void onMsgStateChanged (const shared_ptr<linphone::ChatMessage> &message, linphone::ChatMessageState state) override {
|
||||
ChatModel *chat = static_cast<ChatModel *>(message->getUserData());
|
||||
|
||||
auto it = find_if(chat->m_entries.begin(), chat->m_entries.end(), [&message](const ChatEntryData &pair) {
|
||||
return pair.second == message;
|
||||
});
|
||||
if (it == chat->m_entries.end())
|
||||
return;
|
||||
|
||||
(*it).first["state"] = state;
|
||||
int row = distance(chat->m_entries.begin(), it);
|
||||
|
||||
emit chat->dataChanged(chat->index(row, 0), chat->index(row, 0));
|
||||
}
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
ChatModel::ChatModel (QObject *parent) : QAbstractListModel(parent) {
|
||||
QObject::connect(
|
||||
this, &ChatModel::allEntriesRemoved,
|
||||
CoreManager::getInstance()->getSipAddressesModel(), &SipAddressesModel::handleAllHistoryEntriesRemoved
|
||||
);
|
||||
|
||||
m_handlers = CoreManager::getInstance()->getHandlers();
|
||||
m_core_handlers = CoreManager::getInstance()->getHandlers();
|
||||
QObject::connect(
|
||||
&(*m_handlers), &CoreHandlers::receivedMessage,
|
||||
&(*m_core_handlers), &CoreHandlers::receivedMessage,
|
||||
this, [this](
|
||||
const std::shared_ptr<linphone::ChatRoom> &room,
|
||||
const std::shared_ptr<linphone::ChatMessage> &message
|
||||
const shared_ptr<linphone::ChatRoom> &room,
|
||||
const shared_ptr<linphone::ChatMessage> &message
|
||||
) {
|
||||
if (m_chat_room == room) {
|
||||
int row = rowCount();
|
||||
|
||||
beginInsertRows(QModelIndex(), row, row);
|
||||
|
||||
QVariantMap map;
|
||||
fillMessageEntry(map, message);
|
||||
m_entries << qMakePair(map, static_pointer_cast<void>(message));
|
||||
|
||||
endInsertRows();
|
||||
}
|
||||
if (m_chat_room == room)
|
||||
insertMessageAtEnd(message);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
@ -189,6 +225,14 @@ void ChatModel::removeAllEntries () {
|
|||
emit allEntriesRemoved();
|
||||
}
|
||||
|
||||
void ChatModel::sendMessage (const QString &message) {
|
||||
shared_ptr<linphone::ChatMessage> _message = m_chat_room->createMessage(::Utils::qStringToLinphoneString(message));
|
||||
_message->setUserData(this);
|
||||
_message->setListener(m_message_handlers);
|
||||
m_chat_room->sendChatMessage(_message);
|
||||
insertMessageAtEnd(_message);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void ChatModel::fillMessageEntry (
|
||||
|
|
@ -246,11 +290,9 @@ void ChatModel::removeEntry (ChatEntryData &pair) {
|
|||
shared_ptr<void> linphone_ptr = pair.second;
|
||||
QTimer::singleShot(
|
||||
0, this, [this, linphone_ptr]() {
|
||||
auto it = find_if(
|
||||
m_entries.begin(), m_entries.end(), [linphone_ptr](const ChatEntryData &pair) {
|
||||
auto it = find_if(m_entries.begin(), m_entries.end(), [linphone_ptr](const ChatEntryData &pair) {
|
||||
return pair.second == linphone_ptr;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
if (it != m_entries.end())
|
||||
removeEntry(static_cast<int>(distance(m_entries.begin(), it)));
|
||||
|
|
@ -264,3 +306,15 @@ void ChatModel::removeEntry (ChatEntryData &pair) {
|
|||
qWarning() << QStringLiteral("Unknown chat entry type: %1.").arg(type);
|
||||
}
|
||||
}
|
||||
|
||||
void ChatModel::insertMessageAtEnd (const shared_ptr<linphone::ChatMessage> &message) {
|
||||
int row = rowCount();
|
||||
|
||||
beginInsertRows(QModelIndex(), row, row);
|
||||
|
||||
QVariantMap map;
|
||||
fillMessageEntry(map, message);
|
||||
m_entries << qMakePair(map, static_pointer_cast<void>(message));
|
||||
|
||||
endInsertRows();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
class CoreHandlers;
|
||||
|
||||
class ChatModel : public QAbstractListModel {
|
||||
class MessageHandlers;
|
||||
|
||||
Q_OBJECT;
|
||||
|
||||
Q_PROPERTY(QString sipAddress READ getSipAddress WRITE setSipAddress NOTIFY sipAddressChanged);
|
||||
|
|
@ -39,6 +41,14 @@ public:
|
|||
|
||||
Q_ENUM(CallStatus);
|
||||
|
||||
enum MessageState {
|
||||
MessageStateDelivered = linphone::ChatMessageStateDelivered,
|
||||
MessageStateInProgress = linphone::ChatMessageStateInProgress,
|
||||
MessageStateNotDelivered = linphone::ChatMessageStateNotDelivered
|
||||
};
|
||||
|
||||
Q_ENUM(MessageState);
|
||||
|
||||
ChatModel (QObject *parent = Q_NULLPTR);
|
||||
~ChatModel () = default;
|
||||
|
||||
|
|
@ -53,8 +63,10 @@ public:
|
|||
QString getSipAddress () const;
|
||||
void setSipAddress (const QString &sip_address);
|
||||
|
||||
Q_INVOKABLE void removeEntry (int id);
|
||||
Q_INVOKABLE void removeAllEntries ();
|
||||
void removeEntry (int id);
|
||||
void removeAllEntries ();
|
||||
|
||||
void sendMessage (const QString &message);
|
||||
|
||||
signals:
|
||||
void sipAddressChanged (const QString &sip_address);
|
||||
|
|
@ -78,10 +90,13 @@ private:
|
|||
|
||||
void removeEntry (ChatEntryData &pair);
|
||||
|
||||
void insertMessageAtEnd (const std::shared_ptr<linphone::ChatMessage> &message);
|
||||
|
||||
QList<ChatEntryData> m_entries;
|
||||
std::shared_ptr<linphone::ChatRoom> m_chat_room;
|
||||
|
||||
std::shared_ptr<CoreHandlers> m_handlers;
|
||||
std::shared_ptr<CoreHandlers> m_core_handlers;
|
||||
std::shared_ptr<MessageHandlers> m_message_handlers;
|
||||
};
|
||||
|
||||
#endif // CHAT_MODEL_H_
|
||||
|
|
|
|||
|
|
@ -51,6 +51,10 @@ public:
|
|||
static_cast<ChatModel *>(m_chat_model_filter.sourceModel())->removeAllEntries();
|
||||
}
|
||||
|
||||
Q_INVOKABLE void sendMessage (const QString &message) {
|
||||
static_cast<ChatModel *>(m_chat_model_filter.sourceModel())->sendMessage(message);
|
||||
}
|
||||
|
||||
signals:
|
||||
void sipAddressChanged (const QString &sipAddress);
|
||||
void moreEntriesLoaded (int n);
|
||||
|
|
|
|||
|
|
@ -8,10 +8,12 @@ import Common.Styles 1.0
|
|||
|
||||
Item {
|
||||
property alias placeholderText: textArea.placeholderText
|
||||
property alias text: textArea.text
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
signal dropped (var files)
|
||||
signal validText (string text)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -36,9 +38,13 @@ Item {
|
|||
|
||||
// Text area.
|
||||
Flickable {
|
||||
anchors.fill: parent
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
|
||||
ScrollBar.vertical: ForceScrollBar {
|
||||
id: scrollBar
|
||||
}
|
||||
|
||||
TextArea.flickable: TextArea {
|
||||
id: textArea
|
||||
|
||||
|
|
@ -49,12 +55,11 @@ Item {
|
|||
rightPadding: fileChooserButton.width +
|
||||
fileChooserButton.anchors.rightMargin +
|
||||
DroppableTextAreaStyle.fileChooserButton.margins
|
||||
selectByMouse: true
|
||||
wrapMode: TextArea.Wrap
|
||||
}
|
||||
anchors.fill: parent
|
||||
|
||||
// Necessary, else `placeHolderText` can get out of the component.
|
||||
clip: true
|
||||
Keys.onReturnPressed: text.length !== 0 && validText(text)
|
||||
}
|
||||
}
|
||||
|
||||
// Handle click to select files.
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@ ColumnLayout {
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
signal messageToSend (string text)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
spacing: 0
|
||||
|
||||
ScrollableListView {
|
||||
|
|
@ -212,6 +216,11 @@ ColumnLayout {
|
|||
DroppableTextArea {
|
||||
anchors.fill: parent
|
||||
placeholderText: qsTr('newMessagePlaceholder')
|
||||
|
||||
onValidText: {
|
||||
this.text = ''
|
||||
proxyModel.sendMessage(text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue