Commit 519e8515 authored by Ronan Abhamon's avatar Ronan Abhamon

feat(app): download directly file chat message (without dialogs)

parent 64f0ab73
......@@ -760,13 +760,6 @@ Server url not configured.</translation>
<translation>It&apos;s necessary to restart the application. Do you want to restart now?</translation>
</message>
</context>
<context>
<name>FileMessage</name>
<message>
<source>downloadFileTitle</source>
<translation>Download file</translation>
</message>
</context>
<context>
<name>Home</name>
<message>
......@@ -1292,6 +1285,10 @@ your friend&apos;s SIP address or username.</translation>
<source>cleanAvatarsDescription</source>
<translation>Are you sure you want to clean all avatars?</translation>
</message>
<message>
<source>downloadLabel</source>
<translation>Download folder</translation>
</message>
</context>
<context>
<name>SettingsVideo</name>
......
......@@ -760,13 +760,6 @@ Url du serveur non configurée.</translation>
<translation>Voulez-vous redémarrer maintenant pour prendre en compte ces modifications ?</translation>
</message>
</context>
<context>
<name>FileMessage</name>
<message>
<source>downloadFileTitle</source>
<translation>Télécharger le fichier</translation>
</message>
</context>
<context>
<name>Home</name>
<message>
......@@ -1291,6 +1284,10 @@ un chat ou ajouter un contact.</translation>
<source>cleanAvatarsDescription</source>
<translation>Voulez-vous vraiment supprimer tous les avatars ?</translation>
</message>
<message>
<source>downloadLabel</source>
<translation>Dossier des téléchargements</translation>
</message>
</context>
<context>
<name>SettingsVideo</name>
......
......@@ -28,6 +28,7 @@
#include <QtDebug>
#include "../../utils/Utils.hpp"
#include "config.h"
#include "Paths.hpp"
......@@ -167,7 +168,7 @@ string Paths::getAvatarsDirPath () {
}
string Paths::getCallHistoryFilePath () {
return getWritableFilePath(getAppCallHistoryFilePath());
return getWritableFilePath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + PATH_AVATARS);
}
string Paths::getCapturesDirPath () {
......@@ -189,6 +190,10 @@ string Paths::getFriendsListFilePath () {
return getWritableFilePath(getAppFriendsFilePath());
}
std::string Paths::getDownloadDirPath () {
return getWritableDirPath(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation));
}
string Paths::getLogsDirPath () {
return getWritableDirPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + PATH_LOGS);
}
......
......@@ -39,6 +39,7 @@ namespace Paths {
std::string getConfigFilePath (const QString &configPath = QString());
std::string getFactoryConfigFilePath ();
std::string getFriendsListFilePath ();
std::string getDownloadDirPath ();
std::string getLogsDirPath ();
std::string getMessageHistoryFilePath ();
std::string getPackageDataDirPath ();
......
......@@ -106,11 +106,9 @@ public:
private:
QList<ChatEntryData>::iterator findMessageEntry (const shared_ptr<linphone::ChatMessage> &message) {
return find_if(
mChatModel->mEntries.begin(), mChatModel->mEntries.end(), [&message](const ChatEntryData &pair) {
return find_if(mChatModel->mEntries.begin(), mChatModel->mEntries.end(), [&message](const ChatEntryData &pair) {
return pair.second == message;
}
);
});
}
void signalDataChanged (const QList<ChatEntryData>::iterator &it) {
......@@ -390,7 +388,7 @@ void ChatModel::sendFileMessage (const QString &path) {
emit messageSent(message);
}
void ChatModel::downloadFile (int id, const QString &downloadPath) {
void ChatModel::downloadFile (int id) {
if (!mChatRoom)
return;
......@@ -423,7 +421,20 @@ void ChatModel::downloadFile (int id, const QString &downloadPath) {
return;
}
message->setFileTransferFilepath(::Utils::appStringToCoreString(downloadPath));
bool soFarSoGood;
const QString &safeFilePath = ::Utils::getSafeFilePath(
QStringLiteral("%1%2")
.arg(CoreManager::getInstance()->getSettingsModel()->getDownloadFolder())
.arg(entry.first["fileName"].toString()),
&soFarSoGood
);
if (!soFarSoGood) {
qWarning() << QStringLiteral("Unable to create safe file path for: %1.").arg(id);
return;
}
message->setFileTransferFilepath(::Utils::appStringToCoreString(safeFilePath));
message->setListener(mMessageHandlers);
if (message->downloadFile() < 0)
......@@ -486,16 +497,14 @@ void ChatModel::removeEntry (ChatEntryData &pair) {
// We are between `beginRemoveRows` and `endRemoveRows`.
// A solution is to schedule a `removeEntry` call in the Qt main loop.
shared_ptr<void> linphonePtr = pair.second;
QTimer::singleShot(
0, this, [this, linphonePtr]() {
QTimer::singleShot(0, this, [this, linphonePtr]() {
auto it = find_if(mEntries.begin(), mEntries.end(), [linphonePtr](const ChatEntryData &pair) {
return pair.second == linphonePtr;
});
if (it != mEntries.end())
removeEntry(static_cast<int>(distance(mEntries.begin(), it)));
}
);
});
}
CoreManager::getInstance()->getCore()->removeCallLog(static_pointer_cast<linphone::CallLog>(pair.second));
......@@ -525,12 +534,9 @@ void ChatModel::insertCall (const shared_ptr<linphone::CallLog> &callLog) {
const ChatEntryData &pair,
const QList<ChatEntryData>::iterator *start = NULL
) {
auto it = lower_bound(
start ? *start : mEntries.begin(), mEntries.end(), pair,
[](const ChatEntryData &a, const ChatEntryData &b) {
auto it = lower_bound(start ? *start : mEntries.begin(), mEntries.end(), pair, [](const ChatEntryData &a, const ChatEntryData &b) {
return a.first["timestamp"] < b.first["timestamp"];
}
);
});
int row = static_cast<int>(distance(mEntries.begin(), it));
......
......@@ -97,7 +97,7 @@ public:
void sendFileMessage (const QString &path);
void downloadFile (int id, const QString &downloadPath);
void downloadFile (int id);
signals:
void sipAddressChanged (const QString &sipAddress);
......
......@@ -69,17 +69,13 @@ ChatProxyModel::ChatProxyModel (QObject *parent) : QSortFilterProxyModel(parent)
ChatModel *chat = static_cast<ChatModel *>(mChatModelFilter->sourceModel());
QObject::connect(
chat, &ChatModel::messageReceived, this, [this](const shared_ptr<linphone::ChatMessage> &) {
QObject::connect(chat, &ChatModel::messageReceived, this, [this](const shared_ptr<linphone::ChatMessage> &) {
mMaxDisplayedEntries++;
}
);
});
QObject::connect(
chat, &ChatModel::messageSent, this, [this](const shared_ptr<linphone::ChatMessage> &) {
QObject::connect(chat, &ChatModel::messageSent, this, [this](const shared_ptr<linphone::ChatMessage> &) {
mMaxDisplayedEntries++;
}
);
});
}
void ChatProxyModel::loadMoreEntries () {
......@@ -133,10 +129,10 @@ void ChatProxyModel::sendFileMessage (const QString &path) {
static_cast<ChatModel *>(mChatModelFilter->sourceModel())->sendFileMessage(path);
}
void ChatProxyModel::downloadFile (int id, const QString &downloadPath) {
void ChatProxyModel::downloadFile (int id) {
QModelIndex sourceIndex = mapToSource(index(id, 0));
static_cast<ChatModel *>(mChatModelFilter->sourceModel())->downloadFile(
mChatModelFilter->mapToSource(sourceIndex).row(), downloadPath
mChatModelFilter->mapToSource(sourceIndex).row()
);
}
......
......@@ -50,7 +50,7 @@ public:
Q_INVOKABLE void sendFileMessage (const QString &path);
Q_INVOKABLE void downloadFile (int id, const QString &downloadPath);
Q_INVOKABLE void downloadFile (int id);
signals:
void sipAddressChanged (const QString &sipAddress);
......
......@@ -640,10 +640,27 @@ QString SettingsModel::getSavedVideosFolder () const {
}
void SettingsModel::setSavedVideosFolder (const QString &folder) {
QString _folder = QDir::cleanPath(folder) + QDir::separator();
QString cleanedFolder = QDir::cleanPath(folder) + QDir::separator();
mConfig->setString(UI_SECTION, "saved_videos_folder", ::Utils::appStringToCoreString(cleanedFolder));
emit savedVideosFolderChanged(cleanedFolder);
}
// -----------------------------------------------------------------------------
QString SettingsModel::getDownloadFolder () const {
return QDir::cleanPath(
::Utils::coreStringToAppString(
mConfig->getString(UI_SECTION, "download_folder", Paths::getDownloadDirPath())
)
) + QDir::separator();
}
void SettingsModel::setDownloadFolder (const QString &folder) {
QString cleanedFolder = QDir::cleanPath(folder) + QDir::separator();
mConfig->setString(UI_SECTION, "saved_videos_folder", ::Utils::appStringToCoreString(_folder));
emit savedVideosFolderChanged(_folder);
mConfig->setString(UI_SECTION, "download_folder", ::Utils::appStringToCoreString(cleanedFolder));
emit downloadFolderChanged(cleanedFolder);
}
// -----------------------------------------------------------------------------
......
......@@ -115,6 +115,7 @@ class SettingsModel : public QObject {
Q_PROPERTY(QString savedScreenshotsFolder READ getSavedScreenshotsFolder WRITE setSavedScreenshotsFolder NOTIFY savedScreenshotsFolderChanged);
Q_PROPERTY(QString savedVideosFolder READ getSavedVideosFolder WRITE setSavedVideosFolder NOTIFY savedVideosFolderChanged);
Q_PROPERTY(QString downloadFolder READ getDownloadFolder WRITE setDownloadFolder NOTIFY downloadFolderChanged);
public:
enum MediaEncryption {
......@@ -264,6 +265,9 @@ public:
QString getSavedVideosFolder () const;
void setSavedVideosFolder (const QString &folder);
QString getDownloadFolder () const;
void setDownloadFolder (const QString &folder);
QString getRemoteProvisioning () const;
void setRemoteProvisioning (const QString &remoteProvisioning);
......@@ -339,6 +343,7 @@ signals:
void savedScreenshotsFolderChanged (const QString &folder);
void savedVideosFolderChanged (const QString &folder);
void downloadFolderChanged (const QString &folder);
void remoteProvisioningChanged (const QString &remoteProvisioning);
void remoteProvisioningNotChanged (const QString &remoteProvisioning);
......
......@@ -20,6 +20,8 @@
* Author: Ronan Abhamon
*/
#include <QFileInfo>
#include "Utils.hpp"
// =============================================================================
......@@ -38,3 +40,32 @@ char *Utils::rstrstr (const char *a, const char *b) {
return nullptr;
}
// -----------------------------------------------------------------------------
#define SAFE_FILE_PATH_LIMIT 100
QString Utils::getSafeFilePath (const QString &filePath, bool *soFarSoGood) {
if (soFarSoGood)
*soFarSoGood = true;
QFileInfo info(filePath);
if (!info.exists())
return filePath;
const QString &prefix = QStringLiteral("%1/%2").arg(info.absolutePath()).arg(info.baseName());
const QString &ext = info.completeSuffix();
for (int i = 1; i < SAFE_FILE_PATH_LIMIT; ++i) {
QString safePath = QStringLiteral("%1 (%3).%4").arg(prefix).arg(i).arg(ext);
if (!QFileInfo::exists(safePath))
return safePath;
}
if (soFarSoGood)
*soFarSoGood = false;
return QStringLiteral("");
}
#undef SAFE_FILE_PATH_LIMIT
......@@ -50,6 +50,10 @@ namespace Utils {
// Reverse function of strstr.
char *rstrstr (const char *a, const char *b);
// Returns the same path given in parameter if `filePath` exists.
// Otherwise returns a safe path with a unique number before the extension.
QString getSafeFilePath (const QString &filePath, bool *soFarSoGood = nullptr);
}
#endif // UTILS_H_
import QtQuick 2.7
import QtQuick.Controls 2.1
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.3
import Common 1.0
......@@ -179,23 +178,13 @@ Row {
}
MouseArea {
FileDialog {
id: fileDialog
folder: shortcuts.home
selectExisting: false
title: qsTr('downloadFileTitle')
onAccepted: proxyModel.downloadFile(index, App.convertUrlToLocalPath(fileUrl))
}
anchors.fill: parent
cursorShape: containsMouse
? Qt.PointingHandCursor
: Qt.ArrowCursor
hoverEnabled: true
onClicked: fileDialog.open()
onClicked: proxyModel.downloadFile(index)
visible: !rectangle.isNotDelivered && !$chatEntry.isOutgoing
}
}
......
......@@ -96,7 +96,9 @@ TabContainer {
onAccepted: SettingsModel.savedScreenshotsFolder = selectedFile
}
}
}
FormLine {
FormGroup {
label: qsTr('savedVideosLabel')
......@@ -109,6 +111,19 @@ TabContainer {
}
}
FormLine {
FormGroup {
label: qsTr('downloadLabel')
FileChooserButton {
selectedFile: SettingsModel.downloadFolder
selectFolder: true
onAccepted: SettingsModel.downloadFolder = selectedFile
}
}
}
FormEmptyLine {}
}
......
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