Commit b9d8311e authored by Ronan Abhamon's avatar Ronan Abhamon

feat(ui/modules/Linphone/Chat/FileMessage): user friendly download \o/

parent b70b419c
......@@ -23,6 +23,7 @@
#include <algorithm>
#include <QDateTime>
#include <QDesktopServices>
#include <QFileDialog>
#include <QFileInfo>
#include <QImage>
......@@ -48,11 +49,24 @@ using namespace std;
// =============================================================================
inline QString getFileId (const shared_ptr<linphone::ChatMessage> &message) {
return ::Utils::coreStringToAppString(message->getAppdata()).section(':', 0, 0);
}
inline QString getDownloadPath (const shared_ptr<linphone::ChatMessage> &message) {
return ::Utils::coreStringToAppString(message->getAppdata()).section(':', 1);
}
inline bool fileWasDownloaded (const std::shared_ptr<linphone::ChatMessage> &message) {
const QString &path = getDownloadPath(message);
return !path.isEmpty() && QFileInfo(path).isFile();
}
inline void fillThumbnailProperty (QVariantMap &dest, const shared_ptr<linphone::ChatMessage> &message) {
string fileId = message->getAppdata();
if (!fileId.empty() && !dest.contains("thumbnail"))
QString fileId = getFileId(message);
if (!fileId.isEmpty() && !dest.contains("thumbnail"))
dest["thumbnail"] = QStringLiteral("image://%1/%2")
.arg(ThumbnailProvider::PROVIDER_ID).arg(::Utils::coreStringToAppString(fileId));
.arg(ThumbnailProvider::PROVIDER_ID).arg(fileId);
}
inline void createThumbnail (const shared_ptr<linphone::ChatMessage> &message) {
......@@ -156,6 +170,12 @@ private:
if (state == linphone::ChatMessageStateFileTransferDone && !message->isOutgoing()) {
createThumbnail(message);
fillThumbnailProperty((*it).first, message);
message->setAppdata(
::Utils::appStringToCoreString(getFileId(message)) + ':' + message->getFileTransferFilepath()
);
(*it).first["wasDownloaded"] = true;
App::getInstance()->getNotifier()->notifyReceivedFileMessage(message);
}
......@@ -310,6 +330,8 @@ void ChatModel::removeAllEntries () {
emit allEntriesRemoved();
}
// -----------------------------------------------------------------------------
void ChatModel::sendMessage (const QString &message) {
if (!mChatRoom)
return;
......@@ -388,26 +410,14 @@ void ChatModel::sendFileMessage (const QString &path) {
emit messageSent(message);
}
void ChatModel::downloadFile (int id) {
if (!mChatRoom)
return;
if (id < 0 || id > mEntries.count()) {
qWarning() << QStringLiteral("Entry %1 not exists.").arg(id);
return;
}
// -----------------------------------------------------------------------------
const ChatEntryData &entry = mEntries[id];
if (entry.first["type"] != EntryType::MessageEntry) {
qWarning() << QStringLiteral("Unable to download entry %1. It's not a message.").arg(id);
void ChatModel::downloadFile (int id) {
const ChatEntryData &entry = getFileMessageEntry(id);
if (!entry.second)
return;
}
shared_ptr<linphone::ChatMessage> message = static_pointer_cast<linphone::ChatMessage>(entry.second);
if (!message->getFileTransferInformation()) {
qWarning() << QStringLiteral("Entry %1 is not a file message.").arg(id);
return;
}
switch (message->getState()) {
case MessageStatusDelivered:
......@@ -441,6 +451,54 @@ void ChatModel::downloadFile (int id) {
qWarning() << QStringLiteral("Unable to download file of entry %1.").arg(id);
}
void ChatModel::openFile (int id, bool showDirectory) {
const ChatEntryData &entry = getFileMessageEntry(id);
if (!entry.second)
return;
shared_ptr<linphone::ChatMessage> message = static_pointer_cast<linphone::ChatMessage>(entry.second);
if (!::fileWasDownloaded(message)) {
downloadFile(id);
return;
}
QFileInfo info(getDownloadPath(message));
QDesktopServices::openUrl(
QUrl(QStringLiteral("file:///%1").arg(showDirectory ? info.absolutePath() : info.absoluteFilePath()))
);
}
bool ChatModel::fileWasDownloaded (int id) {
const ChatEntryData &entry = getFileMessageEntry(id);
return entry.second && ::fileWasDownloaded(static_pointer_cast<linphone::ChatMessage>(entry.second));
}
// -----------------------------------------------------------------------------
const ChatModel::ChatEntryData ChatModel::getFileMessageEntry (int id) {
if (!mChatRoom)
return ChatEntryData();
if (id < 0 || id > mEntries.count()) {
qWarning() << QStringLiteral("Entry %1 not exists.").arg(id);
return ChatEntryData();
}
const ChatEntryData &entry = mEntries[id];
if (entry.first["type"] != EntryType::MessageEntry) {
qWarning() << QStringLiteral("Unable to download entry %1. It's not a message.").arg(id);
return ChatEntryData();
}
shared_ptr<linphone::ChatMessage> message = static_pointer_cast<linphone::ChatMessage>(entry.second);
if (!message->getFileTransferInformation()) {
qWarning() << QStringLiteral("Entry %1 is not a file message.").arg(id);
return ChatEntryData();
}
return entry;
}
// -----------------------------------------------------------------------------
void ChatModel::fillMessageEntry (QVariantMap &dest, const shared_ptr<linphone::ChatMessage> &message) {
......@@ -454,6 +512,8 @@ void ChatModel::fillMessageEntry (QVariantMap &dest, const shared_ptr<linphone::
if (content) {
dest["fileSize"] = static_cast<quint64>(content->getSize());
dest["fileName"] = ::Utils::coreStringToAppString(content->getName());
dest["wasDownloaded"] = ::fileWasDownloaded(message);
fillThumbnailProperty(dest, message);
}
}
......
......@@ -98,6 +98,12 @@ public:
void sendFileMessage (const QString &path);
void downloadFile (int id);
void openFile (int id, bool showDirectory = false);
void openFileDirectory (int id) {
openFile(id, true);
}
bool fileWasDownloaded (int id);
signals:
void sipAddressChanged (const QString &sipAddress);
......@@ -111,6 +117,8 @@ signals:
private:
typedef QPair<QVariantMap, std::shared_ptr<void> > ChatEntryData;
const ChatEntryData getFileMessageEntry (int id);
void fillMessageEntry (QVariantMap &dest, const std::shared_ptr<linphone::ChatMessage> &message);
void fillCallStartEntry (QVariantMap &dest, const std::shared_ptr<linphone::CallLog> &callLog);
void fillCallEndEntry (QVariantMap &dest, const std::shared_ptr<linphone::CallLog> &callLog);
......
......@@ -78,6 +78,26 @@ ChatProxyModel::ChatProxyModel (QObject *parent) : QSortFilterProxyModel(parent)
});
}
// -----------------------------------------------------------------------------
#define CREATE_CALL_MODEL_FUNCTION_WITH_ID(METHOD) \
void ChatProxyModel::METHOD(int id) { \
QModelIndex sourceIndex = mapToSource(index(id, 0)); \
static_cast<ChatModel *>(mChatModelFilter->sourceModel())->METHOD( \
mChatModelFilter->mapToSource(sourceIndex).row() \
); \
}
CREATE_CALL_MODEL_FUNCTION_WITH_ID(downloadFile);
CREATE_CALL_MODEL_FUNCTION_WITH_ID(openFile);
CREATE_CALL_MODEL_FUNCTION_WITH_ID(openFileDirectory);
CREATE_CALL_MODEL_FUNCTION_WITH_ID(removeEntry);
CREATE_CALL_MODEL_FUNCTION_WITH_ID(resendMessage);
#undef CREATE_CALL_MODEL_FUNCTION_WITH_ID
// -----------------------------------------------------------------------------
void ChatProxyModel::loadMoreEntries () {
int count = rowCount();
int parentCount = mChatModelFilter->rowCount();
......@@ -103,13 +123,6 @@ void ChatProxyModel::setEntryTypeFilter (ChatModel::EntryType type) {
}
}
void ChatProxyModel::removeEntry (int id) {
QModelIndex sourceIndex = mapToSource(index(id, 0));
static_cast<ChatModel *>(mChatModelFilter->sourceModel())->removeEntry(
mChatModelFilter->mapToSource(sourceIndex).row()
);
}
void ChatProxyModel::removeAllEntries () {
static_cast<ChatModel *>(mChatModelFilter->sourceModel())->removeAllEntries();
}
......@@ -118,24 +131,10 @@ void ChatProxyModel::sendMessage (const QString &message) {
static_cast<ChatModel *>(mChatModelFilter->sourceModel())->sendMessage(message);
}
void ChatProxyModel::resendMessage (int id) {
QModelIndex sourceIndex = mapToSource(index(id, 0));
static_cast<ChatModel *>(mChatModelFilter->sourceModel())->resendMessage(
mChatModelFilter->mapToSource(sourceIndex).row()
);
}
void ChatProxyModel::sendFileMessage (const QString &path) {
static_cast<ChatModel *>(mChatModelFilter->sourceModel())->sendFileMessage(path);
}
void ChatProxyModel::downloadFile (int id) {
QModelIndex sourceIndex = mapToSource(index(id, 0));
static_cast<ChatModel *>(mChatModelFilter->sourceModel())->downloadFile(
mChatModelFilter->mapToSource(sourceIndex).row()
);
}
// -----------------------------------------------------------------------------
bool ChatProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex &) const {
......
......@@ -51,6 +51,8 @@ public:
Q_INVOKABLE void sendFileMessage (const QString &path);
Q_INVOKABLE void downloadFile (int id);
Q_INVOKABLE void openFile (int id);
Q_INVOKABLE void openFileDirectory (int id);
signals:
void sipAddressChanged (const QString &sipAddress);
......
......@@ -240,7 +240,7 @@ Row {
icon: 'download'
iconSize: ChatStyle.entry.message.file.iconSize
visible: !$chatEntry.isOutgoing
visible: !$chatEntry.isOutgoing && !$chatEntry.wasDownloaded
}
MouseArea {
......@@ -257,18 +257,19 @@ Row {
hoverEnabled: true
visible: !rectangle.isNotDelivered && !$chatEntry.isOutgoing
onMouseXChanged: handleMouseMove.call(this, mouse)
onMouseYChanged: handleMouseMove.call(this, mouse)
onExited: thumbnailProvider.state = ''
onClicked: {
// TODO: Handle open.
if (false && Utils.pointIsInItem(this, thumbnailProvider, mouse)) {
if (Utils.pointIsInItem(this, thumbnailProvider, mouse)) {
proxyModel.openFile(index)
} else {
} else if ($chatEntry.wasDownloaded) {
proxyModel.openFileDirectory(index)
} else {
proxyModel.downloadFile(index)
}
}
onExited: thumbnailProvider.state = ''
onMouseXChanged: handleMouseMove.call(this, mouse)
onMouseYChanged: handleMouseMove.call(this, mouse)
}
}
......
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