mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-05-01 00:16:23 +00:00
feat(ui/modules/Linphone/Chat/FileMessage): user friendly download \o/
This commit is contained in:
parent
b70b419c21
commit
b9d8311e91
5 changed files with 118 additions and 48 deletions
|
|
@ -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)
|
||||
const ChatEntryData &entry = getFileMessageEntry(id);
|
||||
if (!entry.second)
|
||||
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);
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue