Add "open in external program" action

This commit is contained in:
Michele Guerini Rocco 2021-01-24 01:29:30 +01:00
parent 049278bc35
commit c569ab24bc
Signed by: rnhmjoj
GPG Key ID: BFBAF4C975F76450
3 changed files with 39 additions and 8 deletions

View File

@ -124,6 +124,12 @@ Page {
text: qsTr("Save as") text: qsTr("Save as")
onTriggered: TimelineManager.timeline.saveMedia(messageContextMenu.eventId) onTriggered: TimelineManager.timeline.saveMedia(messageContextMenu.eventId)
} }
MenuItem {
visible: messageContextMenu.eventType == MtxEvent.ImageMessage || messageContextMenu.eventType == MtxEvent.VideoMessage || messageContextMenu.eventType == MtxEvent.AudioMessage || messageContextMenu.eventType == MtxEvent.FileMessage || messageContextMenu.eventType == MtxEvent.Sticker
height: visible ? implicitHeight : 0
text: qsTr("Open in external program")
onTriggered: TimelineManager.timeline.openMedia(messageContextMenu.eventId)
}
} }

View File

@ -5,6 +5,7 @@
#include <type_traits> #include <type_traits>
#include <QCache> #include <QCache>
#include <QDesktopServices>
#include <QFileDialog> #include <QFileDialog>
#include <QMimeDatabase> #include <QMimeDatabase>
#include <QRegularExpression> #include <QRegularExpression>
@ -1073,6 +1074,14 @@ TimelineModel::addPendingMessage(mtx::events::collections::TimelineEvents event)
std::visit(SendMessageVisitor{this}, event); std::visit(SendMessageVisitor{this}, event);
} }
void
TimelineModel::openMedia(QString eventId)
{
cacheMedia(eventId, [](QString filename) {
QDesktopServices::openUrl(QUrl::fromLocalFile(filename));
});
}
bool bool
TimelineModel::saveMedia(QString eventId) const TimelineModel::saveMedia(QString eventId) const
{ {
@ -1149,7 +1158,7 @@ TimelineModel::saveMedia(QString eventId) const
} }
void void
TimelineModel::cacheMedia(QString eventId) TimelineModel::cacheMedia(QString eventId, std::function<void(const QString)> callback)
{ {
mtx::events::collections::TimelineEvents *event = events.get(eventId.toStdString(), ""); mtx::events::collections::TimelineEvents *event = events.get(eventId.toStdString(), "");
if (!event) if (!event)
@ -1169,12 +1178,13 @@ TimelineModel::cacheMedia(QString eventId)
QString suffix = QMimeDatabase().mimeTypeForName(mimeType).preferredSuffix(); QString suffix = QMimeDatabase().mimeTypeForName(mimeType).preferredSuffix();
const auto url = mxcUrl.toStdString(); const auto url = mxcUrl.toStdString();
const auto name = QString(mxcUrl).remove("mxc://");
QFileInfo filename(QString("%1/media_cache/%2.%3") QFileInfo filename(QString("%1/media_cache/%2.%3")
.arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)) .arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
.arg(QString(mxcUrl).remove("mxc://")) .arg(name)
.arg(suffix)); .arg(suffix));
if (QDir::cleanPath(filename.path()) != filename.path()) { if (QDir::cleanPath(name) != name) {
nhlog::net()->warn("mxcUrl '{}' is not safe, not downloading file", url); nhlog::net()->warn("mxcUrl '{}' is not safe, not downloading file", url);
return; return;
} }
@ -1183,15 +1193,18 @@ TimelineModel::cacheMedia(QString eventId)
if (filename.isReadable()) { if (filename.isReadable()) {
emit mediaCached(mxcUrl, filename.filePath()); emit mediaCached(mxcUrl, filename.filePath());
if (callback) {
callback(filename.filePath());
}
return; return;
} }
http::client()->download( http::client()->download(
url, url,
[this, mxcUrl, filename, url, encryptionInfo](const std::string &data, [this, callback, mxcUrl, filename, url, encryptionInfo](const std::string &data,
const std::string &, const std::string &,
const std::string &, const std::string &,
mtx::http::RequestErr err) { mtx::http::RequestErr err) {
if (err) { if (err) {
nhlog::net()->warn("failed to retrieve image {}: {} {}", nhlog::net()->warn("failed to retrieve image {}: {} {}",
url, url,
@ -1213,6 +1226,10 @@ TimelineModel::cacheMedia(QString eventId)
file.write(QByteArray(temp.data(), (int)temp.size())); file.write(QByteArray(temp.data(), (int)temp.size()));
file.close(); file.close();
if (callback) {
callback(filename.filePath());
}
} catch (const std::exception &e) { } catch (const std::exception &e) {
nhlog::ui()->warn("Error while saving file to: {}", e.what()); nhlog::ui()->warn("Error while saving file to: {}", e.what());
} }
@ -1221,6 +1238,12 @@ TimelineModel::cacheMedia(QString eventId)
}); });
} }
void
TimelineModel::cacheMedia(QString eventId)
{
cacheMedia(eventId, NULL);
}
QString QString
TimelineModel::formatTypingUsers(const std::vector<QString> &users, QColor bg) TimelineModel::formatTypingUsers(const std::vector<QString> &users, QColor bg)
{ {

View File

@ -218,8 +218,10 @@ public:
Q_INVOKABLE void redactEvent(QString id); Q_INVOKABLE void redactEvent(QString id);
Q_INVOKABLE int idToIndex(QString id) const; Q_INVOKABLE int idToIndex(QString id) const;
Q_INVOKABLE QString indexToId(int index) const; Q_INVOKABLE QString indexToId(int index) const;
Q_INVOKABLE void openMedia(QString eventId);
Q_INVOKABLE void cacheMedia(QString eventId); Q_INVOKABLE void cacheMedia(QString eventId);
Q_INVOKABLE bool saveMedia(QString eventId) const; Q_INVOKABLE bool saveMedia(QString eventId) const;
void cacheMedia(QString eventId, std::function<void(const QString filename)> callback);
std::vector<::Reaction> reactions(const std::string &event_id) std::vector<::Reaction> reactions(const std::string &event_id)
{ {