diff --git a/Telegram/SourceFiles/boxes/edit_caption_box.cpp b/Telegram/SourceFiles/boxes/edit_caption_box.cpp index 9e2982dd7..3a7413bc0 100644 --- a/Telegram/SourceFiles/boxes/edit_caption_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_caption_box.cpp @@ -78,14 +78,11 @@ auto ListFromMimeData(not_null data, bool premium) { : Ui::PreparedList(Error::EmptyFile, QString()); if (result.error == Error::None) { return result; - } else if (data->hasImage()) { - auto image = qvariant_cast(data->imageData()); - if (!image.isNull()) { - return Storage::PrepareMediaFromImage( - std::move(image), - QByteArray(), - st::sendMediaPreviewSize); - } + } else if (auto read = Core::ReadMimeImage(data)) { + return Storage::PrepareMediaFromImage( + std::move(read.image), + std::move(read.content), + st::sendMediaPreviewSize); } return result; } diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index 957b3560c..3a205d77a 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -976,14 +976,11 @@ bool SendFilesBox::addFiles(not_null data) { QString()); if (result.error == Ui::PreparedList::Error::None) { return result; - } else if (data->hasImage()) { - auto image = qvariant_cast(data->imageData()); - if (!image.isNull()) { - return Storage::PrepareMediaFromImage( - std::move(image), - QByteArray(), - st::sendMediaPreviewSize); - } + } else if (auto read = Core::ReadMimeImage(data)) { + return Storage::PrepareMediaFromImage( + std::move(read.image), + std::move(read.content), + st::sendMediaPreviewSize); } return result; }(); diff --git a/Telegram/SourceFiles/core/mime_type.cpp b/Telegram/SourceFiles/core/mime_type.cpp index c93ffb871..9fcace352 100644 --- a/Telegram/SourceFiles/core/mime_type.cpp +++ b/Telegram/SourceFiles/core/mime_type.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/mime_type.h" #include "core/utils.h" +#include "ui/image/image_prepare.h" #include #include @@ -164,10 +165,31 @@ std::shared_ptr ShareMimeMediaData( if (original->hasImage()) { result->setImageData(original->imageData()); } + if (original->hasFormat(u"application/x-td-use-jpeg"_q) + && original->hasFormat(u"image/jpeg"_q)) { + result->setData(u"application/x-td-use-jpeg"_q, "1"); + result->setData(u"image/jpeg"_q, original->data(u"image/jpeg"_q)); + } if (auto list = base::GetMimeUrls(original); !list.isEmpty()) { result->setUrls(std::move(list)); } return result; } +MimeImageData ReadMimeImage(not_null data) { + if (data->hasFormat(u"application/x-td-use-jpeg"_q)) { + auto bytes = data->data(u"image/jpeg"_q); + auto read = Images::Read({ .content = bytes }); + if (read.format == "jpeg" && !read.image.isNull()) { + return { + .image = std::move(read.image), + .content = std::move(bytes), + }; + } + } else if (data->hasImage()) { + return { .image = qvariant_cast(data->imageData()) }; + } + return {}; +} + } // namespace Core diff --git a/Telegram/SourceFiles/core/mime_type.h b/Telegram/SourceFiles/core/mime_type.h index bb83de41c..9406f57ba 100644 --- a/Telegram/SourceFiles/core/mime_type.h +++ b/Telegram/SourceFiles/core/mime_type.h @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include +#include class QMimeData; @@ -52,4 +53,17 @@ private: [[nodiscard]] std::shared_ptr ShareMimeMediaData( not_null original); +struct MimeImageData { + QImage image; + QByteArray content; + + [[nodiscard]] bool empty() const { + return image.isNull(); + } + explicit operator bool() const { + return !empty(); + } +}; +[[nodiscard]] MimeImageData ReadMimeImage(not_null data); + } // namespace Core diff --git a/Telegram/SourceFiles/data/data_photo_media.cpp b/Telegram/SourceFiles/data/data_photo_media.cpp index 312b672f5..7bbdcdd1e 100644 --- a/Telegram/SourceFiles/data/data_photo_media.cpp +++ b/Telegram/SourceFiles/data/data_photo_media.cpp @@ -18,6 +18,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "storage/file_download.h" #include "ui/image/image.h" +#include +#include + namespace Data { PhotoMedia::PhotoMedia(not_null owner) @@ -198,8 +201,7 @@ bool PhotoMedia::saveToFile(const QString &path) { QFile f(path); return f.open(QIODevice::WriteOnly) && (f.write(video) == video.size()); - } else if (const auto photo = imageBytes(large) - ; !photo.isEmpty()) { + } else if (const auto photo = imageBytes(large); !photo.isEmpty()) { QFile f(path); return f.open(QIODevice::WriteOnly) && (f.write(photo) == photo.size()); @@ -210,4 +212,24 @@ bool PhotoMedia::saveToFile(const QString &path) { return false; } +bool PhotoMedia::setToClipboard() { + constexpr auto large = PhotoSize::Large; + if (const auto video = videoContent(large); !video.isEmpty()) { + return false; + } + auto fallback = image(large)->original(); + if (fallback.isNull()) { + return false; + } + const auto bytes = imageBytes(large); + auto mime = std::make_unique(); + mime->setImageData(std::move(fallback)); + if (auto bytes = imageBytes(large); !bytes.isEmpty()) { + mime->setData(u"image/jpeg"_q, std::move(bytes)); + } + mime->setData(u"application/x-td-use-jpeg"_q, "1"); + QGuiApplication::clipboard()->setMimeData(mime.release()); + return true; +} + } // namespace Data diff --git a/Telegram/SourceFiles/data/data_photo_media.h b/Telegram/SourceFiles/data/data_photo_media.h index 4e97aa911..7c5c34bd4 100644 --- a/Telegram/SourceFiles/data/data_photo_media.h +++ b/Telegram/SourceFiles/data/data_photo_media.h @@ -48,6 +48,7 @@ public: void collectLocalData(not_null local); bool saveToFile(const QString &path); + bool setToClipboard(); private: struct PhotoImage { diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp index 2a171099e..6f9e27449 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp @@ -1362,9 +1362,7 @@ void InnerWidget::copyContextImage(not_null photo) { if (photo->isNull() || !media || !media->loaded()) { return; } - - const auto image = media->image(Data::PhotoSize::Large)->original(); - QGuiApplication::clipboard()->setImage(image); + media->setToClipboard(); } void InnerWidget::copySelectedText() { diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index c39c847aa..26ada37ac 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -2638,8 +2638,7 @@ void HistoryInner::copyContextImage( if (photo->isNull() || !media || !media->loaded()) { return; } else if (!showCopyMediaRestriction(item)) { - const auto image = media->image(Data::PhotoSize::Large)->original(); - QGuiApplication::clipboard()->setImage(image); + media->setToClipboard(); } } diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 7f671aa76..d18024d42 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/peers/edit_peer_permissions_box.h" // ShowAboutGigagroup. #include "boxes/peers/edit_peer_requests_box.h" #include "core/file_utilities.h" +#include "core/mime_type.h" #include "ui/toast/toast.h" #include "ui/toasts/common_toasts.h" #include "ui/emoji_config.h" @@ -5188,16 +5189,13 @@ bool HistoryWidget::confirmSendingFiles( } } - if (hasImage) { - auto image = qvariant_cast(data->imageData()); - if (!image.isNull()) { - confirmSendingFiles( - std::move(image), - QByteArray(), - overrideSendImagesAsPhotos, - insertTextOnCancel); - return true; - } + if (auto read = Core::ReadMimeImage(data)) { + confirmSendingFiles( + std::move(read.image), + std::move(read.content), + overrideSendImagesAsPhotos, + insertTextOnCancel); + return true; } return false; } diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index cea595a68..91387b7b0 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -124,9 +124,7 @@ void CopyImage(not_null photo) { if (photo->isNull() || !media || !media->loaded()) { return; } - - const auto image = media->image(Data::PhotoSize::Large)->original(); - QGuiApplication::clipboard()->setImage(image); + media->setToClipboard(); } void ShowStickerPackInfo( diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp index b78d045af..8daf4f8ee 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp @@ -62,6 +62,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/application.h" #include "core/shortcuts.h" #include "core/click_handler_types.h" +#include "core/mime_type.h" #include "main/main_session.h" #include "main/main_session_settings.h" #include "mainwidget.h" @@ -910,16 +911,13 @@ bool RepliesWidget::confirmSendingFiles( } } - if (hasImage) { - auto image = qvariant_cast(data->imageData()); - if (!image.isNull()) { - confirmSendingFiles( - std::move(image), - QByteArray(), - overrideSendImagesAsPhotos, - insertTextOnCancel); - return true; - } + if (auto read = Core::ReadMimeImage(data)) { + confirmSendingFiles( + std::move(read.image), + std::move(read.content), + overrideSendImagesAsPhotos, + insertTextOnCancel); + return true; } return false; } diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp index 5ad4fef7b..a0680c2db 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp @@ -44,6 +44,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/call_delayed.h" #include "base/qt/qt_key_modifiers.h" #include "core/file_utilities.h" +#include "core/mime_type.h" #include "chat_helpers/tabbed_selector.h" #include "main/main_session.h" #include "data/data_chat_participant_status.h" @@ -369,16 +370,13 @@ bool ScheduledWidget::confirmSendingFiles( } } - if (hasImage) { - auto image = qvariant_cast(data->imageData()); - if (!image.isNull()) { - confirmSendingFiles( - std::move(image), - QByteArray(), - overrideSendImagesAsPhotos, - insertTextOnCancel); - return true; - } + if (auto read = Core::ReadMimeImage(data)) { + confirmSendingFiles( + std::move(read.image), + std::move(read.content), + overrideSendImagesAsPhotos, + insertTextOnCancel); + return true; } return false; } diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index 5e0615179..a23592bba 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -1948,11 +1948,21 @@ void OverlayWidget::copyMedia() { } _dropdown->hideAnimated(Ui::DropdownMenu::HideOption::IgnoreShow); if (_document) { - QGuiApplication::clipboard()->setImage(transformedShownContent()); + const auto filepath = _document->filepath(true); + auto image = transformedShownContent(); + if (!image.isNull() || !filepath.isEmpty()) { + auto mime = std::make_unique(); + if (!image.isNull()) { + mime->setImageData(std::move(image)); + } + if (!filepath.isEmpty() && !videoShown()) { + mime->setUrls({ QUrl::fromLocalFile(filepath) }); + KUrlMimeData::exportUrlsToPortal(mime.get()); + } + QGuiApplication::clipboard()->setMimeData(mime.release()); + } } else if (_photo && _photoMedia->loaded()) { - const auto image = _photoMedia->image( - Data::PhotoSize::Large)->original(); - QGuiApplication::clipboard()->setImage(image); + _photoMedia->setToClipboard(); } }