fix(Chat): Context menu for gif downloads/copies a png file

Detect the MIME type using `QMimeDatabase` from the actual content and
save it in that same format using `QSaveFile`, as `QImage` does NOT
support saving a GIF

Fixes #10747
This commit is contained in:
Lukáš Tinkl 2023-06-12 10:32:27 +02:00 committed by Lukáš Tinkl
parent 31f59a2e81
commit 6bfe79a7f3
4 changed files with 38 additions and 22 deletions

View File

@ -105,8 +105,7 @@ QtObject:
downloadImage(content, path) downloadImage(content, path)
proc downloadImageByUrl*(self: Utils, url: string, path: string) {.slot.} = proc downloadImageByUrl*(self: Utils, url: string, path: string) {.slot.} =
let pathFormatted = self.formatImagePath(path) downloadImageByUrl(url, path)
downloadImageByUrl(url, pathFormatted)
proc generateQRCodeSVG*(self: Utils, text: string, border: int = 0): string = proc generateQRCodeSVG*(self: Utils, text: string, border: int = 0): string =
var qr0: array[0..qrcodegen_BUFFER_LEN_MAX, uint8] var qr0: array[0..qrcodegen_BUFFER_LEN_MAX, uint8]

View File

@ -224,7 +224,6 @@ QtObject {
function openDownloadImageDialog(imageSource) { function openDownloadImageDialog(imageSource) {
// We don't use `openPopup`, because there's no `FileDialog::closed` signal. // We don't use `openPopup`, because there's no `FileDialog::closed` signal.
// And multiple file dialogs are (almost) ok
const popup = downloadImageDialogComponent.createObject(popupParent, { imageSource }) const popup = downloadImageDialogComponent.createObject(popupParent, { imageSource })
popup.open() popup.open()
} }
@ -498,11 +497,7 @@ QtObject {
onRejected: { onRejected: {
destroy() destroy()
} }
Component.onCompleted: {
open()
}
} }
} }
] ]
} }

View File

@ -7,9 +7,10 @@ StatusMenu {
property string imageSource property string imageSource
readonly property bool isGif: root.imageSource.toLowerCase().endsWith(".gif")
StatusAction { StatusAction {
text: root.imageSource.endsWith(".gif") ? qsTr("Copy GIF") text: root.isGif ? qsTr("Copy GIF") : qsTr("Copy image")
: qsTr("Copy image")
icon.name: "copy" icon.name: "copy"
enabled: !!root.imageSource enabled: !!root.imageSource
onTriggered: { onTriggered: {
@ -18,8 +19,7 @@ StatusMenu {
} }
StatusAction { StatusAction {
text: root.imageSource.endsWith(".gif") ? qsTr("Download GIF") text: root.isGif ? qsTr("Download GIF") : qsTr("Download image")
: qsTr("Download image")
icon.name: "download" icon.name: "download"
enabled: !!root.imageSource enabled: !!root.imageSource
onTriggered: { onTriggered: {

View File

@ -51,6 +51,8 @@
#include <QSettings> #include <QSettings>
#include <QTimer> #include <QTimer>
#include <QSysInfo> #include <QSysInfo>
#include <QMimeDatabase>
#include <QSaveFile>
#ifdef QT_QUICKCONTROLS2_LIB #ifdef QT_QUICKCONTROLS2_LIB
#include <QtQuickControls2/QQuickStyle> #include <QtQuickControls2/QQuickStyle>
#endif #endif
@ -304,22 +306,42 @@ void dos_qguiapplication_download_imageByUrl(const char *url, const char *filePa
manager.setAutoDeleteReplies(true); manager.setAutoDeleteReplies(true);
QNetworkReply *reply = manager.get(QNetworkRequest(QUrl(url))); QNetworkReply *reply = manager.get(QNetworkRequest(QUrl(url)));
const auto path = QFile::decodeName(filePath); auto targetDir = QUrl::fromUserInput(filePath).toLocalFile(); // accept both "file:/foo/bar" and "/foo/bar"
if (targetDir.isEmpty())
targetDir = QDir::homePath();
QObject::connect(reply, &QNetworkReply::finished, [reply, path] { QObject::connect(reply, &QNetworkReply::finished, [reply, targetDir] {
if(reply->error() == QNetworkReply::NoError) { if(reply->error() == QNetworkReply::NoError) {
// Get current Date/Time information to use in naming of the image file // Extract the image data to be able to load and save it
const QString dateTimeString = QDateTime::currentDateTime().toString("dd-MM-yyyy_hh-mm-ss"); const auto btArray = reply->readAll();
Q_ASSERT(!btArray.isEmpty());
// Extract the image data to be able to load and save into a QImage // Get current Date/Time information to use in naming of the image file
QByteArray btArray = reply->readAll(); const auto dateTimeString = QDateTime::currentDateTime().toString(QStringLiteral("dd-MM-yyyy_hh-mm-ss"));
QImage image;
image.loadFromData(btArray); // Get the preferred extension
Q_ASSERT(!image.isNull()); QMimeDatabase mimeDb;
image.save(path + "/image_" + dateTimeString + ".png"); auto ext = mimeDb.mimeTypeForData(btArray).preferredSuffix();
if (ext.isEmpty())
ext = QStringLiteral("jpg");
// Construct the target path
const auto targetFile = QStringLiteral("%1/image_%2.%3").arg(targetDir, dateTimeString, ext);
// Save the image in a safe way
QSaveFile image(targetFile);
if (!image.open(QIODevice::WriteOnly)) {
qWarning() << "dos_qguiapplication_download_imageByUrl: Downloading image failed while opening the save file:" << targetFile;
return;
}
if (image.write(btArray) != -1)
image.commit();
else
qWarning() << "dos_qguiapplication_download_imageByUrl: Downloading image failed while saving to file:" << targetFile;
} }
else { else {
qWarning() << "dos_qguiapplication_download_imageByUrl: Downloading image failed!"; qWarning() << "dos_qguiapplication_download_imageByUrl: Downloading image" << reply->request().url() << "failed!";
} }
}); });
} }