Copy/Paste original JPEG bytes to clipboard.

This commit is contained in:
John Preston 2023-01-13 11:51:59 +04:00
parent 9b154b3c91
commit b1d1d73541
13 changed files with 112 additions and 60 deletions

View file

@ -78,14 +78,11 @@ auto ListFromMimeData(not_null<const QMimeData*> data, bool premium) {
: Ui::PreparedList(Error::EmptyFile, QString());
if (result.error == Error::None) {
return result;
} else if (data->hasImage()) {
auto image = qvariant_cast<QImage>(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;
}

View file

@ -976,14 +976,11 @@ bool SendFilesBox::addFiles(not_null<const QMimeData*> data) {
QString());
if (result.error == Ui::PreparedList::Error::None) {
return result;
} else if (data->hasImage()) {
auto image = qvariant_cast<QImage>(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;
}();

View file

@ -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 <QtCore/QMimeDatabase>
#include <QtCore/QMimeData>
@ -164,10 +165,31 @@ std::shared_ptr<QMimeData> 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<const QMimeData*> 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<QImage>(data->imageData()) };
}
return {};
}
} // namespace Core

View file

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QMimeType>
#include <QtGui/QImage>
class QMimeData;
@ -52,4 +53,17 @@ private:
[[nodiscard]] std::shared_ptr<QMimeData> ShareMimeMediaData(
not_null<const QMimeData*> 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<const QMimeData*> data);
} // namespace Core

View file

@ -18,6 +18,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/file_download.h"
#include "ui/image/image.h"
#include <QtGui/QGuiApplication>
#include <QtGui/QClipboard>
namespace Data {
PhotoMedia::PhotoMedia(not_null<PhotoData*> 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<QMimeData>();
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

View file

@ -48,6 +48,7 @@ public:
void collectLocalData(not_null<PhotoMedia*> local);
bool saveToFile(const QString &path);
bool setToClipboard();
private:
struct PhotoImage {

View file

@ -1362,9 +1362,7 @@ void InnerWidget::copyContextImage(not_null<PhotoData*> 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() {

View file

@ -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();
}
}

View file

@ -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<QImage>(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;
}

View file

@ -124,9 +124,7 @@ void CopyImage(not_null<PhotoData*> 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(

View file

@ -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<QImage>(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;
}

View file

@ -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<QImage>(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;
}

View file

@ -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<QMimeData>();
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();
}
}