From d706b4c7c99385a22983e4f4276eff43210b0600 Mon Sep 17 00:00:00 2001 From: Ronan Abhamon Date: Mon, 16 Jan 2017 15:36:24 +0100 Subject: [PATCH] feat(ui/modules/Linphone/Chat/FileMessage): file download is supported --- tests/assets/languages/en.ts | 7 ++ tests/assets/languages/fr.ts | 7 ++ tests/src/components/chat/ChatModel.cpp | 95 ++++++++++++++----- tests/src/components/chat/ChatModel.hpp | 2 + tests/src/components/chat/ChatProxyModel.cpp | 7 ++ tests/src/components/chat/ChatProxyModel.hpp | 2 + .../ui/modules/Linphone/Chat/FileMessage.qml | 29 +++++- 7 files changed, 123 insertions(+), 26 deletions(-) diff --git a/tests/assets/languages/en.ts b/tests/assets/languages/en.ts index 6755d2916..308fad2f1 100644 --- a/tests/assets/languages/en.ts +++ b/tests/assets/languages/en.ts @@ -311,6 +311,13 @@ Server url not configured. Missed outgoing call + + FileMessage + + downloadFileTitle + + + Home diff --git a/tests/assets/languages/fr.ts b/tests/assets/languages/fr.ts index 71f21dcf9..dcef4df81 100644 --- a/tests/assets/languages/fr.ts +++ b/tests/assets/languages/fr.ts @@ -299,6 +299,13 @@ Url du serveur non configurée. Appel sortant sans réponse + + FileMessage + + downloadFileTitle + + + Home diff --git a/tests/src/components/chat/ChatModel.cpp b/tests/src/components/chat/ChatModel.cpp index bf8ce2e4e..564d267fb 100644 --- a/tests/src/components/chat/ChatModel.cpp +++ b/tests/src/components/chat/ChatModel.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include #include @@ -22,10 +23,36 @@ using namespace std; // ============================================================================= inline void fillThumbnailProperty (QVariantMap &dest, const shared_ptr &message) { - string data = message->getAppdata(); - if (!data.empty()) + string file_id = message->getAppdata(); + if (!file_id.empty() && !dest.contains("thumbnail")) dest["thumbnail"] = QStringLiteral("image://%1/%2") - .arg(ThumbnailProvider::PROVIDER_ID).arg(::Utils::linphoneStringToQString(data)); + .arg(ThumbnailProvider::PROVIDER_ID).arg(::Utils::linphoneStringToQString(file_id)); +} + +inline void createThumbnail (const shared_ptr &message) { + if (!message->getAppdata().empty()) + return; + + QString thumbnail_path = ::Utils::linphoneStringToQString(message->getFileTransferFilepath()); + + QImage image(thumbnail_path); + if (image.isNull()) + return; + + QImage thumbnail = image.scaled( + THUMBNAIL_IMAGE_FILE_WIDTH, THUMBNAIL_IMAGE_FILE_HEIGHT, + Qt::KeepAspectRatio, Qt::SmoothTransformation + ); + + QString uuid = QUuid::createUuid().toString(); + QString file_id = QStringLiteral("%1.jpg").arg(uuid.mid(1, uuid.length() - 2)); + + if (!thumbnail.save(::Utils::linphoneStringToQString(Paths::getThumbnailsDirPath()) + file_id, "jpg", 100)) { + qWarning() << QStringLiteral("Unable to create thumbnail of: `%1`.").arg(thumbnail_path); + return; + } + + message->setAppdata(::Utils::qStringToLinphoneString(file_id)); } inline void removeFileMessageThumbnail (const shared_ptr &message) { @@ -112,24 +139,8 @@ private: if (state == linphone::ChatMessageStateFileTransferError) state = linphone::ChatMessageStateNotDelivered; else if (state == linphone::ChatMessageStateFileTransferDone) { - QString thumbnail_path = ::Utils::linphoneStringToQString(message->getFileTransferFilepath()); - - QImage image(thumbnail_path); - if (!image.isNull()) { - QImage thumbnail = image.scaled( - THUMBNAIL_IMAGE_FILE_WIDTH, THUMBNAIL_IMAGE_FILE_HEIGHT, - Qt::KeepAspectRatio, Qt::SmoothTransformation - ); - - QString uuid = QUuid::createUuid().toString(); - QString file_id = QStringLiteral("%1.jpg").arg(uuid.mid(1, uuid.length() - 2)); - - if (!thumbnail.save(::Utils::linphoneStringToQString(Paths::getThumbnailsDirPath()) + file_id, "jpg", 100)) { - qWarning() << QStringLiteral("Unable to create thumbnail of: `%1`.").arg(thumbnail_path); - return; - } - - message->setAppdata(::Utils::qStringToLinphoneString(file_id)); + if (!message->isOutgoing()) { + createThumbnail(message); fillThumbnailProperty((*it).first, message); } @@ -348,7 +359,8 @@ void ChatModel::resendMessage (int id) { } shared_ptr message = static_pointer_cast(entry.second); - if (message->getState() != linphone::ChatMessageStateNotDelivered) { + int state = message->getState(); + if (state != linphone::ChatMessageStateNotDelivered && state != linphone::ChatMessageStateFileTransferError) { qWarning() << QStringLiteral("Unable to resend message: %1. Bad state.").arg(id); return; } @@ -381,6 +393,45 @@ void ChatModel::sendFileMessage (const QString &path) { emit messageSent(message); } +void ChatModel::downloadFile (int id, const QString &download_path) { + if (!m_chat_room) + return; + + if (id < 0 || id > m_entries.count()) { + qWarning() << QStringLiteral("Entry %1 not exists.").arg(id); + return; + } + + const ChatEntryData &entry = m_entries[id]; + if (entry.first["type"] != EntryType::MessageEntry) { + qWarning() << QStringLiteral("Unable to download entry %1. It's not a message.").arg(id); + return; + } + + shared_ptr message = static_pointer_cast(entry.second); + if (!message->getFileTransferInformation()) { + qWarning() << QStringLiteral("Entry %1 is not a file message.").arg(id); + return; + } + + int state = message->getState(); + if (state != linphone::ChatMessageStateDelivered && state != linphone::ChatMessageStateFileTransferDone) { + qWarning() << QStringLiteral("Unable to download file of entry %1. It was not uploaded.").arg(id); + return; + } + + message->setFileTransferFilepath( + ::Utils::qStringToLinphoneString(download_path.startsWith("file://") + ? download_path.mid(sizeof("file://") - 1) + : download_path + ) + ); + message->setListener(m_message_handlers); + + if (message->downloadFile() < 0) + qWarning() << QStringLiteral("Unable to download file of entry %1.").arg(id); +} + // ----------------------------------------------------------------------------- void ChatModel::fillMessageEntry (QVariantMap &dest, const shared_ptr &message) { diff --git a/tests/src/components/chat/ChatModel.hpp b/tests/src/components/chat/ChatModel.hpp index 1a18af568..c640a82ec 100644 --- a/tests/src/components/chat/ChatModel.hpp +++ b/tests/src/components/chat/ChatModel.hpp @@ -70,6 +70,8 @@ public: void sendFileMessage (const QString &path); + void downloadFile (int id, const QString &download_path); + signals: void sipAddressChanged (const QString &sip_address); void allEntriesRemoved (); diff --git a/tests/src/components/chat/ChatProxyModel.cpp b/tests/src/components/chat/ChatProxyModel.cpp index 47e0cff3c..8b3998119 100644 --- a/tests/src/components/chat/ChatProxyModel.cpp +++ b/tests/src/components/chat/ChatProxyModel.cpp @@ -109,6 +109,13 @@ void ChatProxyModel::sendFileMessage (const QString &path) { static_cast(m_chat_model_filter->sourceModel())->sendFileMessage(path); } +void ChatProxyModel::downloadFile (int id, const QString &download_path) { + QModelIndex source_index = mapToSource(index(id, 0)); + static_cast(m_chat_model_filter->sourceModel())->downloadFile( + m_chat_model_filter->mapToSource(source_index).row(), download_path + ); +} + // ----------------------------------------------------------------------------- bool ChatProxyModel::filterAcceptsRow (int source_row, const QModelIndex &) const { diff --git a/tests/src/components/chat/ChatProxyModel.hpp b/tests/src/components/chat/ChatProxyModel.hpp index 88535566e..aba11b114 100644 --- a/tests/src/components/chat/ChatProxyModel.hpp +++ b/tests/src/components/chat/ChatProxyModel.hpp @@ -28,6 +28,8 @@ public: Q_INVOKABLE void sendFileMessage (const QString &path); + Q_INVOKABLE void downloadFile (int id, const QString &download_path); + signals: void sipAddressChanged (const QString &sip_address); void moreEntriesLoaded (int n); diff --git a/tests/ui/modules/Linphone/Chat/FileMessage.qml b/tests/ui/modules/Linphone/Chat/FileMessage.qml index 7829c57ab..7b7609b59 100644 --- a/tests/ui/modules/Linphone/Chat/FileMessage.qml +++ b/tests/ui/modules/Linphone/Chat/FileMessage.qml @@ -1,5 +1,6 @@ import QtQuick 2.7 import QtQuick.Controls 2.0 +import QtQuick.Dialogs 1.2 import QtQuick.Layouts 1.3 import Common 1.0 @@ -47,6 +48,8 @@ Row { Rectangle { id: rectangle + readonly property bool isNotDelivered: $chatEntry.status === ChatModel.MessageStatusNotDelivered + color: $chatEntry.isOutgoing ? ChatStyle.entry.message.outgoing.backgroundColor : ChatStyle.entry.message.incoming.backgroundColor @@ -169,6 +172,27 @@ Row { } } } + + MouseArea { + FileDialog { + id: fileDialog + + folder: shortcuts.home + title: qsTr('downloadFileTitle') + selectExisting: false + + onAccepted: proxyModel.downloadFile(index, fileUrl) + } + + anchors.fill: parent + cursorShape: containsMouse + ? Qt.PointingHandCursor + : Qt.ArrowCursor + hoverEnabled: true + + onClicked: fileDialog.open() + visible: !rectangle.isNotDelivered && !$chatEntry.isOutgoing + } } // ------------------------------------------------------------------------- @@ -182,10 +206,7 @@ Row { id: icon Icon { - readonly property bool isNotDelivered: - $chatEntry.status === ChatModel.MessageStatusNotDelivered - - icon: isNotDelivered ? 'chat_error' : 'chat_send' + icon: rectangle.isNotDelivered ? 'chat_error' : 'chat_send' iconSize: ChatStyle.entry.message.outgoing.sendIconSize MouseArea {