Copy/Paste original JPEG bytes to clipboard.
This commit is contained in:
		
							parent
							
								
									9b154b3c91
								
							
						
					
					
						commit
						b1d1d73541
					
				
					 13 changed files with 112 additions and 60 deletions
				
			
		| 
						 | 
				
			
			@ -78,15 +78,12 @@ 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()) {
 | 
			
		||||
	} else if (auto read = Core::ReadMimeImage(data)) {
 | 
			
		||||
		return Storage::PrepareMediaFromImage(
 | 
			
		||||
				std::move(image),
 | 
			
		||||
				QByteArray(),
 | 
			
		||||
			std::move(read.image),
 | 
			
		||||
			std::move(read.content),
 | 
			
		||||
			st::sendMediaPreviewSize);
 | 
			
		||||
	}
 | 
			
		||||
	}
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -976,15 +976,12 @@ 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()) {
 | 
			
		||||
		} else if (auto read = Core::ReadMimeImage(data)) {
 | 
			
		||||
			return Storage::PrepareMediaFromImage(
 | 
			
		||||
					std::move(image),
 | 
			
		||||
					QByteArray(),
 | 
			
		||||
				std::move(read.image),
 | 
			
		||||
				std::move(read.content),
 | 
			
		||||
				st::sendMediaPreviewSize);
 | 
			
		||||
		}
 | 
			
		||||
		}
 | 
			
		||||
		return result;
 | 
			
		||||
	}();
 | 
			
		||||
	return addFiles(std::move(list));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,6 +48,7 @@ public:
 | 
			
		|||
	void collectLocalData(not_null<PhotoMedia*> local);
 | 
			
		||||
 | 
			
		||||
	bool saveToFile(const QString &path);
 | 
			
		||||
	bool setToClipboard();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	struct PhotoImage {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,17 +5189,14 @@ bool HistoryWidget::confirmSendingFiles(
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (hasImage) {
 | 
			
		||||
		auto image = qvariant_cast<QImage>(data->imageData());
 | 
			
		||||
		if (!image.isNull()) {
 | 
			
		||||
	if (auto read = Core::ReadMimeImage(data)) {
 | 
			
		||||
		confirmSendingFiles(
 | 
			
		||||
				std::move(image),
 | 
			
		||||
				QByteArray(),
 | 
			
		||||
			std::move(read.image),
 | 
			
		||||
			std::move(read.content),
 | 
			
		||||
			overrideSendImagesAsPhotos,
 | 
			
		||||
			insertTextOnCancel);
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
	}
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,17 +911,14 @@ bool RepliesWidget::confirmSendingFiles(
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (hasImage) {
 | 
			
		||||
		auto image = qvariant_cast<QImage>(data->imageData());
 | 
			
		||||
		if (!image.isNull()) {
 | 
			
		||||
	if (auto read = Core::ReadMimeImage(data)) {
 | 
			
		||||
		confirmSendingFiles(
 | 
			
		||||
				std::move(image),
 | 
			
		||||
				QByteArray(),
 | 
			
		||||
			std::move(read.image),
 | 
			
		||||
			std::move(read.content),
 | 
			
		||||
			overrideSendImagesAsPhotos,
 | 
			
		||||
			insertTextOnCancel);
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
	}
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,17 +370,14 @@ bool ScheduledWidget::confirmSendingFiles(
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (hasImage) {
 | 
			
		||||
		auto image = qvariant_cast<QImage>(data->imageData());
 | 
			
		||||
		if (!image.isNull()) {
 | 
			
		||||
	if (auto read = Core::ReadMimeImage(data)) {
 | 
			
		||||
		confirmSendingFiles(
 | 
			
		||||
				std::move(image),
 | 
			
		||||
				QByteArray(),
 | 
			
		||||
			std::move(read.image),
 | 
			
		||||
			std::move(read.content),
 | 
			
		||||
			overrideSendImagesAsPhotos,
 | 
			
		||||
			insertTextOnCancel);
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
	}
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue