diff --git a/tests/src/app/Logger.cpp b/tests/src/app/Logger.cpp index 9c26a948a..1d1a54173 100644 --- a/tests/src/app/Logger.cpp +++ b/tests/src/app/Logger.cpp @@ -1,5 +1,4 @@ #include -#include #include #include diff --git a/tests/src/components/chat/ChatModel.cpp b/tests/src/components/chat/ChatModel.cpp index f0fb8ac07..9ec55a843 100644 --- a/tests/src/components/chat/ChatModel.cpp +++ b/tests/src/components/chat/ChatModel.cpp @@ -13,30 +13,66 @@ using namespace std; // ============================================================================= +class ChatModel::MessageHandlers : public linphone::ChatMessageListener { + void onFileTransferRecv ( + const shared_ptr &message, + const shared_ptr &content, + const shared_ptr &buffer + ) override { + qDebug() << "Not yet implemented"; + } + + shared_ptr onFileTransferSend ( + const shared_ptr &message, + const shared_ptr &content, + size_t offset, + size_t size + ) override { + qDebug() << "Not yet implemented"; + } + + void onFileTransferProgressIndication ( + const shared_ptr &message, + const shared_ptr &content, + size_t offset, + size_t total + ) override { + qDebug() << "Not yet implemented"; + } + + void onMsgStateChanged (const shared_ptr &message, linphone::ChatMessageState state) override { + ChatModel *chat = static_cast(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 &room, - const std::shared_ptr &message + const shared_ptr &room, + const shared_ptr &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(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 _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 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(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 &message) { + int row = rowCount(); + + beginInsertRows(QModelIndex(), row, row); + + QVariantMap map; + fillMessageEntry(map, message); + m_entries << qMakePair(map, static_pointer_cast(message)); + + endInsertRows(); +} diff --git a/tests/src/components/chat/ChatModel.hpp b/tests/src/components/chat/ChatModel.hpp index ea9d2740b..6066f1b0e 100644 --- a/tests/src/components/chat/ChatModel.hpp +++ b/tests/src/components/chat/ChatModel.hpp @@ -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 &message); + QList m_entries; std::shared_ptr m_chat_room; - std::shared_ptr m_handlers; + std::shared_ptr m_core_handlers; + std::shared_ptr m_message_handlers; }; #endif // CHAT_MODEL_H_ diff --git a/tests/src/components/chat/ChatProxyModel.hpp b/tests/src/components/chat/ChatProxyModel.hpp index 5d20bb9b1..2fd0cc14a 100644 --- a/tests/src/components/chat/ChatProxyModel.hpp +++ b/tests/src/components/chat/ChatProxyModel.hpp @@ -51,6 +51,10 @@ public: static_cast(m_chat_model_filter.sourceModel())->removeAllEntries(); } + Q_INVOKABLE void sendMessage (const QString &message) { + static_cast(m_chat_model_filter.sourceModel())->sendMessage(message); + } + signals: void sipAddressChanged (const QString &sipAddress); void moreEntriesLoaded (int n); diff --git a/tests/ui/modules/Common/DroppableTextArea.qml b/tests/ui/modules/Common/DroppableTextArea.qml index c95cd93c7..5499e699d 100644 --- a/tests/ui/modules/Common/DroppableTextArea.qml +++ b/tests/ui/modules/Common/DroppableTextArea.qml @@ -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. diff --git a/tests/ui/modules/Linphone/Chat/Chat.qml b/tests/ui/modules/Linphone/Chat/Chat.qml index 511b089f1..e911d8a32 100644 --- a/tests/ui/modules/Linphone/Chat/Chat.qml +++ b/tests/ui/modules/Linphone/Chat/Chat.qml @@ -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) + } } } }