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