Use final Image with different Images::Source-s.

This commit is contained in:
John Preston 2018-10-12 19:41:51 +03:00
parent 5a50248055
commit 4b5b79e415
16 changed files with 1376 additions and 993 deletions

View file

@ -660,8 +660,8 @@ bool DocumentData::loaded(FilePathResolveType type) const {
auto that = const_cast<DocumentData*>(this); auto that = const_cast<DocumentData*>(this);
that->_location = FileLocation(_loader->fileName()); that->_location = FileLocation(_loader->fileName());
that->_data = _loader->bytes(); that->_data = _loader->bytes();
if (that->sticker() && !_loader->imagePixmap().isNull()) { if (that->sticker() && !_loader->imageData().isNull()) {
that->sticker()->img = ImagePtr(_data, _loader->imageFormat(), _loader->imagePixmap()); that->sticker()->img = ImagePtr(_data, _loader->imageFormat(), _loader->imageData());
} }
destroyLoaderDelayed(); destroyLoaderDelayed();
} }
@ -954,7 +954,7 @@ ImagePtr DocumentData::makeReplyPreview(Data::FileOrigin origin) {
auto options = Images::Option::Smooth | (isVideoMessage() ? Images::Option::Circled : Images::Option::None) | Images::Option::TransparentBackground; auto options = Images::Option::Smooth | (isVideoMessage() ? Images::Option::Circled : Images::Option::None) | Images::Option::TransparentBackground;
auto outerSize = st::msgReplyBarSize.height(); auto outerSize = st::msgReplyBarSize.height();
auto image = thumb->pixNoCache(origin, thumbSize.width(), thumbSize.height(), options, outerSize, outerSize); auto image = thumb->pixNoCache(origin, thumbSize.width(), thumbSize.height(), options, outerSize, outerSize);
replyPreview = ImagePtr(image, "PNG"); replyPreview = ImagePtr(image.toImage(), "PNG");
} else { } else {
thumb->load(origin); thumb->load(origin);
} }

View file

@ -354,15 +354,14 @@ bool MediaPhoto::updateSentMedia(const MTPMessageMedia &media) {
if (key.isNull() || image->isNull() || !image->loaded()) { if (key.isNull() || image->isNull() || !image->loaded()) {
return; return;
} }
if (image->savedData().isEmpty()) { auto bytes = image->bytesForCache();
image->forget(); if (bytes.isEmpty() || bytes.size() > Storage::kMaxFileInMemory) {
} else if (image->savedData().size() > Storage::kMaxFileInMemory) {
return; return;
} }
Auth().data().cache().putIfEmpty( Auth().data().cache().putIfEmpty(
Data::StorageCacheKey(key), Data::StorageCacheKey(key),
Storage::Cache::Database::TaggedValue( Storage::Cache::Database::TaggedValue(
image->savedData(), std::move(bytes),
Data::kImageCacheTag)); Data::kImageCacheTag));
}; };
auto &sizes = photo.c_photo().vsizes.v; auto &sizes = photo.c_photo().vsizes.v;

View file

@ -195,6 +195,9 @@ ImagePtr PeerData::currentUserpic() const {
return _userpic; return _userpic;
} }
} }
if (!_userpicEmpty) {
refreshEmptyUserpic();
}
return ImagePtr(); return ImagePtr();
} }
@ -296,10 +299,9 @@ void PeerData::clearUserpic() {
auto image = Messenger::Instance().logoNoMargin().scaledToWidth( auto image = Messenger::Instance().logoNoMargin().scaledToWidth(
kUserpicSize, kUserpicSize,
Qt::SmoothTransformation); Qt::SmoothTransformation);
auto pixmap = App::pixmapFromImageInPlace(std::move(image));
return _userpic return _userpic
? _userpic ? _userpic
: ImagePtr(std::move(pixmap), "PNG"); : ImagePtr(std::move(image), "PNG");
} }
return ImagePtr(); return ImagePtr();
}(); }();

View file

@ -126,7 +126,8 @@ ImagePtr PhotoData::makeReplyPreview(Data::FileOrigin origin) {
origin, origin,
w * st::msgReplyBarSize.height() / h, w * st::msgReplyBarSize.height() / h,
st::msgReplyBarSize.height()) st::msgReplyBarSize.height())
: image->pix(origin, st::msgReplyBarSize.height())), : image->pix(origin, st::msgReplyBarSize.height())
).toImage(),
"PNG"); "PNG");
}; };
if (thumb->isDelayedStorageImage() if (thumb->isDelayedStorageImage()

View file

@ -777,9 +777,9 @@ not_null<PhotoData*> Session::photo(const MTPDphoto &data) {
not_null<PhotoData*> Session::photo( not_null<PhotoData*> Session::photo(
const MTPPhoto &data, const MTPPhoto &data,
const PreparedPhotoThumbs &thumbs) { const PreparedPhotoThumbs &thumbs) {
auto thumb = (const QPixmap*)nullptr; auto thumb = (const QImage*)nullptr;
auto medium = (const QPixmap*)nullptr; auto medium = (const QImage*)nullptr;
auto full = (const QPixmap*)nullptr; auto full = (const QImage*)nullptr;
auto thumbLevel = -1; auto thumbLevel = -1;
auto mediumLevel = -1; auto mediumLevel = -1;
auto fullLevel = -1; auto fullLevel = -1;
@ -813,9 +813,9 @@ not_null<PhotoData*> Session::photo(
data.c_photo().vaccess_hash.v, data.c_photo().vaccess_hash.v,
data.c_photo().vfile_reference.v, data.c_photo().vfile_reference.v,
data.c_photo().vdate.v, data.c_photo().vdate.v,
ImagePtr(*thumb, "JPG"), ImagePtr(base::duplicate(*thumb), "JPG"),
ImagePtr(*medium, "JPG"), ImagePtr(base::duplicate(*medium), "JPG"),
ImagePtr(*full, "JPG")); ImagePtr(base::duplicate(*full), "JPG"));
case mtpc_photoEmpty: case mtpc_photoEmpty:
return photo(data.c_photoEmpty().vid.v); return photo(data.c_photoEmpty().vid.v);
@ -1013,7 +1013,7 @@ not_null<DocumentData*> Session::document(const MTPDdocument &data) {
not_null<DocumentData*> Session::document( not_null<DocumentData*> Session::document(
const MTPdocument &data, const MTPdocument &data,
const QPixmap &thumb) { QImage &&thumb) {
switch (data.type()) { switch (data.type()) {
case mtpc_documentEmpty: case mtpc_documentEmpty:
return document(data.c_documentEmpty().vid.v); return document(data.c_documentEmpty().vid.v);
@ -1027,7 +1027,7 @@ not_null<DocumentData*> Session::document(
fields.vdate.v, fields.vdate.v,
fields.vattributes.v, fields.vattributes.v,
qs(fields.vmime_type), qs(fields.vmime_type),
ImagePtr(thumb, "JPG"), ImagePtr(std::move(thumb), "JPG"),
fields.vdc_id.v, fields.vdc_id.v,
fields.vsize.v, fields.vsize.v,
StorageImageLocation()); StorageImageLocation());

View file

@ -269,7 +269,7 @@ public:
not_null<DocumentData*> document(const MTPDdocument &data); not_null<DocumentData*> document(const MTPDdocument &data);
not_null<DocumentData*> document( not_null<DocumentData*> document(
const MTPdocument &data, const MTPdocument &data,
const QPixmap &thumb); QImage &&thumb);
not_null<DocumentData*> document( not_null<DocumentData*> document(
DocumentId id, DocumentId id,
const uint64 &access, const uint64 &access,

View file

@ -294,7 +294,7 @@ using WebPageId = uint64;
using GameId = uint64; using GameId = uint64;
constexpr auto CancelledWebPageId = WebPageId(0xFFFFFFFFFFFFFFFFULL); constexpr auto CancelledWebPageId = WebPageId(0xFFFFFFFFFFFFFFFFULL);
using PreparedPhotoThumbs = QMap<char, QPixmap>; using PreparedPhotoThumbs = QMap<char, QImage>;
// [0] == -1 -- counting, [0] == -2 -- could not count // [0] == -1 -- counting, [0] == -2 -- could not count
using VoiceWaveform = QVector<signed char>; using VoiceWaveform = QVector<signed char>;

View file

@ -127,6 +127,31 @@ FileLoader::FileLoader(
Expects(!_filename.isEmpty() || (_size <= Storage::kMaxFileInMemory)); Expects(!_filename.isEmpty() || (_size <= Storage::kMaxFileInMemory));
} }
void FileLoader::finishWithBytes(const QByteArray &data) {
_data = data;
_localStatus = LocalStatus::Loaded;
if (!_filename.isEmpty() && _toCache == LoadToCacheAsWell) {
if (!_fileIsOpen) _fileIsOpen = _file.open(QIODevice::WriteOnly);
if (!_fileIsOpen) {
cancel(true);
return;
}
if (_file.write(_data) != qint64(_data.size())) {
cancel(true);
return;
}
}
_finished = true;
if (_fileIsOpen) {
_file.close();
_fileIsOpen = false;
Platform::File::PostprocessDownloaded(
QFileInfo(_file).absoluteFilePath());
}
_downloader->taskFinished().notify();
}
QByteArray FileLoader::imageFormat(const QSize &shrinkBox) const { QByteArray FileLoader::imageFormat(const QSize &shrinkBox) const {
if (_imageFormat.isEmpty() && _locationType == UnknownFileLocation) { if (_imageFormat.isEmpty() && _locationType == UnknownFileLocation) {
readImage(shrinkBox); readImage(shrinkBox);
@ -134,11 +159,11 @@ QByteArray FileLoader::imageFormat(const QSize &shrinkBox) const {
return _imageFormat; return _imageFormat;
} }
QPixmap FileLoader::imagePixmap(const QSize &shrinkBox) const { QImage FileLoader::imageData(const QSize &shrinkBox) const {
if (_imagePixmap.isNull() && _locationType == UnknownFileLocation) { if (_imageData.isNull() && _locationType == UnknownFileLocation) {
readImage(shrinkBox); readImage(shrinkBox);
} }
return _imagePixmap; return _imageData;
} }
void FileLoader::readImage(const QSize &shrinkBox) const { void FileLoader::readImage(const QSize &shrinkBox) const {
@ -146,9 +171,9 @@ void FileLoader::readImage(const QSize &shrinkBox) const {
auto image = App::readImage(_data, &format, false); auto image = App::readImage(_data, &format, false);
if (!image.isNull()) { if (!image.isNull()) {
if (!shrinkBox.isEmpty() && (image.width() > shrinkBox.width() || image.height() > shrinkBox.height())) { if (!shrinkBox.isEmpty() && (image.width() > shrinkBox.width() || image.height() > shrinkBox.height())) {
_imagePixmap = App::pixmapFromImageInPlace(image.scaled(shrinkBox, Qt::KeepAspectRatio, Qt::SmoothTransformation)); _imageData = image.scaled(shrinkBox, Qt::KeepAspectRatio, Qt::SmoothTransformation);
} else { } else {
_imagePixmap = App::pixmapFromImageInPlace(std::move(image)); _imageData = std::move(image);
} }
_imageFormat = format; _imageFormat = format;
} }
@ -222,39 +247,18 @@ FileLoader::~FileLoader() {
void FileLoader::localLoaded( void FileLoader::localLoaded(
const StorageImageSaved &result, const StorageImageSaved &result,
const QByteArray &imageFormat, const QByteArray &imageFormat,
const QPixmap &imagePixmap) { const QImage &imageData) {
_localLoading.kill(); _localLoading.kill();
if (result.data.isEmpty()) { if (result.data.isEmpty()) {
_localStatus = LocalStatus::NotFound; _localStatus = LocalStatus::NotFound;
start(true); start(true);
return; return;
} }
_data = result.data; if (!imageData.isNull()) {
if (!imagePixmap.isNull()) {
_imageFormat = imageFormat; _imageFormat = imageFormat;
_imagePixmap = imagePixmap; _imageData = imageData;
} }
_localStatus = LocalStatus::Loaded; finishWithBytes(result.data);
if (!_filename.isEmpty() && _toCache == LoadToCacheAsWell) {
if (!_fileIsOpen) _fileIsOpen = _file.open(QIODevice::WriteOnly);
if (!_fileIsOpen) {
cancel(true);
return;
}
if (_file.write(_data) != qint64(_data.size())) {
cancel(true);
return;
}
}
_finished = true;
if (_fileIsOpen) {
_file.close();
_fileIsOpen = false;
Platform::File::PostprocessDownloaded(
QFileInfo(_file).absoluteFilePath());
}
_downloader->taskFinished().notify();
emit progress(this); emit progress(this);
@ -389,7 +393,7 @@ void FileLoader::loadLocal(const Storage::Cache::Key &key) {
localLoaded( localLoaded(
StorageImageSaved(std::move(value)), StorageImageSaved(std::move(value)),
format, format,
App::pixmapFromImageInPlace(std::move(image))); std::move(image));
}); });
}; };
Auth().data().cache().get(key, [=, callback = std::move(done)]( Auth().data().cache().get(key, [=, callback = std::move(done)](

View file

@ -84,6 +84,7 @@ public:
bool finished() const { bool finished() const {
return _finished; return _finished;
} }
void finishWithBytes(const QByteArray &data);
bool cancelled() const { bool cancelled() const {
return _cancelled; return _cancelled;
} }
@ -94,7 +95,7 @@ public:
return 0; return 0;
} }
QByteArray imageFormat(const QSize &shrinkBox = QSize()) const; QByteArray imageFormat(const QSize &shrinkBox = QSize()) const;
QPixmap imagePixmap(const QSize &shrinkBox = QSize()) const; QImage imageData(const QSize &shrinkBox = QSize()) const;
QString fileName() const { QString fileName() const {
return _filename; return _filename;
} }
@ -134,8 +135,8 @@ public:
void localLoaded( void localLoaded(
const StorageImageSaved &result, const StorageImageSaved &result,
const QByteArray &imageFormat = QByteArray(), const QByteArray &imageFormat,
const QPixmap &imagePixmap = QPixmap()); const QImage &imageData);
signals: signals:
void progress(FileLoader *loader); void progress(FileLoader *loader);
@ -191,7 +192,7 @@ protected:
base::binary_guard _localLoading; base::binary_guard _localLoading;
mutable QByteArray _imageFormat; mutable QByteArray _imageFormat;
mutable QPixmap _imagePixmap; mutable QImage _imageData;
}; };

View file

@ -124,7 +124,9 @@ void Uploader::uploadMedia(const FullMsgId &msgId, const SendMediaReady &media)
} else if (media.type == SendMediaType::File || media.type == SendMediaType::Audio) { } else if (media.type == SendMediaType::File || media.type == SendMediaType::Audio) {
const auto document = media.photoThumbs.isEmpty() const auto document = media.photoThumbs.isEmpty()
? Auth().data().document(media.document) ? Auth().data().document(media.document)
: Auth().data().document(media.document, media.photoThumbs.begin().value()); : Auth().data().document(
media.document,
base::duplicate(media.photoThumbs.begin().value()));
if (!media.data.isEmpty()) { if (!media.data.isEmpty()) {
document->setData(media.data); document->setData(media.data);
if (document->saveToCache() if (document->saveToCache()
@ -153,7 +155,9 @@ void Uploader::upload(
} else if (file->type == SendMediaType::File || file->type == SendMediaType::Audio) { } else if (file->type == SendMediaType::File || file->type == SendMediaType::Audio) {
auto document = file->thumb.isNull() auto document = file->thumb.isNull()
? Auth().data().document(file->document) ? Auth().data().document(file->document)
: Auth().data().document(file->document, file->thumb); : Auth().data().document(
file->document,
base::duplicate(file->thumb));
document->uploadingData = std::make_unique<Data::UploadState>(document->size); document->uploadingData = std::make_unique<Data::UploadState>(document->size);
if (!file->content.isEmpty()) { if (!file->content.isEmpty()) {
document->setData(file->content); document->setData(file->content);

View file

@ -31,26 +31,26 @@ SendMediaReady PreparePeerPhoto(PeerId peerId, QImage &&image) {
image.save(&jpegBuffer, "JPG", 87); image.save(&jpegBuffer, "JPG", 87);
const auto scaled = [&](int size) { const auto scaled = [&](int size) {
return App::pixmapFromImageInPlace(image.scaled( return image.scaled(
size, size,
size, size,
Qt::KeepAspectRatio, Qt::KeepAspectRatio,
Qt::SmoothTransformation)); Qt::SmoothTransformation);
}; };
const auto push = [&](const char *type, QPixmap &&pixmap) { const auto push = [&](const char *type, QImage &&image) {
photoSizes.push_back(MTP_photoSize( photoSizes.push_back(MTP_photoSize(
MTP_string(type), MTP_string(type),
MTP_fileLocationUnavailable( MTP_fileLocationUnavailable(
MTP_long(0), MTP_long(0),
MTP_int(0), MTP_int(0),
MTP_long(0)), MTP_long(0)),
MTP_int(pixmap.width()), MTP_int(image.width()),
MTP_int(pixmap.height()), MTP_int(0))); MTP_int(image.height()), MTP_int(0)));
photoThumbs.insert(type[0], std::move(pixmap)); photoThumbs.insert(type[0], std::move(image));
}; };
push("a", scaled(160)); push("a", scaled(160));
push("b", scaled(320)); push("b", scaled(320));
push("c", App::pixmapFromImageInPlace(std::move(image))); push("c", std::move(image));
const auto id = rand_value<PhotoId>(); const auto id = rand_value<PhotoId>();
const auto photo = MTP_photo( const auto photo = MTP_photo(
@ -531,7 +531,7 @@ void FileLoadTask::process() {
PreparedPhotoThumbs photoThumbs; PreparedPhotoThumbs photoThumbs;
QVector<MTPPhotoSize> photoSizes; QVector<MTPPhotoSize> photoSizes;
QPixmap thumb; QImage thumb;
QVector<MTPDocumentAttribute> attributes(1, MTP_documentAttributeFilename(MTP_string(filename))); QVector<MTPDocumentAttribute> attributes(1, MTP_documentAttributeFilename(MTP_string(filename)));
@ -552,7 +552,7 @@ void FileLoadTask::process() {
if (!song->cover.isNull()) { // cover to thumb if (!song->cover.isNull()) { // cover to thumb
auto coverWidth = song->cover.width(); auto coverWidth = song->cover.width();
auto coverHeight = song->cover.height(); auto coverHeight = song->cover.height();
auto full = (coverWidth > 90 || coverHeight > 90) ? App::pixmapFromImageInPlace(song->cover.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : App::pixmapFromImageInPlace(std::move(song->cover)); auto full = (coverWidth > 90 || coverHeight > 90) ? song->cover.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation) : std::move(song->cover);
{ {
auto thumbFormat = QByteArray("JPG"); auto thumbFormat = QByteArray("JPG");
auto thumbQuality = 87; auto thumbQuality = 87;
@ -588,10 +588,9 @@ void FileLoadTask::process() {
cover.save(&buffer, thumbFormat, thumbQuality); cover.save(&buffer, thumbFormat, thumbQuality);
} }
thumb = App::pixmapFromImageInPlace(std::move(cover));
thumbSize = MTP_photoSize(MTP_string(""), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0));
thumbId = rand_value<uint64>(); thumbId = rand_value<uint64>();
thumb = std::move(cover);
thumbSize = MTP_photoSize(MTP_string(""), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0));
} }
} }
@ -603,15 +602,15 @@ void FileLoadTask::process() {
if (isAnimation) { if (isAnimation) {
attributes.push_back(MTP_documentAttributeAnimated()); attributes.push_back(MTP_documentAttributeAnimated());
} else if (_type != SendMediaType::File) { } else if (_type != SendMediaType::File) {
auto thumb = (w > 100 || h > 100) ? App::pixmapFromImageInPlace(fullimage.scaled(100, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage); auto thumb = (w > 100 || h > 100) ? fullimage.scaled(100, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation) : fullimage;
photoThumbs.insert('s', thumb); photoThumbs.insert('s', thumb);
photoSizes.push_back(MTP_photoSize(MTP_string("s"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0))); photoSizes.push_back(MTP_photoSize(MTP_string("s"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0)));
auto medium = (w > 320 || h > 320) ? App::pixmapFromImageInPlace(fullimage.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage); auto medium = (w > 320 || h > 320) ? fullimage.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation) : fullimage;
photoThumbs.insert('m', medium); photoThumbs.insert('m', medium);
photoSizes.push_back(MTP_photoSize(MTP_string("m"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(medium.width()), MTP_int(medium.height()), MTP_int(0))); photoSizes.push_back(MTP_photoSize(MTP_string("m"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(medium.width()), MTP_int(medium.height()), MTP_int(0)));
auto full = (w > 1280 || h > 1280) ? App::pixmapFromImageInPlace(fullimage.scaled(1280, 1280, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage); auto full = (w > 1280 || h > 1280) ? fullimage.scaled(1280, 1280, Qt::KeepAspectRatio, Qt::SmoothTransformation) : fullimage;
photoThumbs.insert('y', full); photoThumbs.insert('y', full);
photoSizes.push_back(MTP_photoSize(MTP_string("y"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0))); photoSizes.push_back(MTP_photoSize(MTP_string("y"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0)));
@ -647,17 +646,13 @@ void FileLoadTask::process() {
thumbname = qsl("thumb.webp"); thumbname = qsl("thumb.webp");
} }
QPixmap full = (w > 90 || h > 90) ? App::pixmapFromImageInPlace(fullimage.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage, Qt::ColorOnly); thumbId = rand_value<uint64>();
thumb = (w > 90 || h > 90) ? fullimage.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation) : fullimage;
thumbSize = MTP_photoSize(MTP_string(""), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0));
{ {
QBuffer buffer(&thumbdata); QBuffer buffer(&thumbdata);
full.save(&buffer, thumbFormat, thumbQuality); thumb.save(&buffer, thumbFormat, thumbQuality);
} }
thumb = full;
thumbSize = MTP_photoSize(MTP_string(""), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0));
thumbId = rand_value<uint64>();
} }
} }
@ -704,7 +699,7 @@ void FileLoadTask::process() {
_result->thumbId = thumbId; _result->thumbId = thumbId;
_result->thumbname = thumbname; _result->thumbname = thumbname;
_result->setThumbData(thumbdata); _result->setThumbData(thumbdata);
_result->thumb = thumb; _result->thumb = std::move(thumb);
_result->photo = photo; _result->photo = photo;
_result->document = document; _result->document = document;

View file

@ -214,7 +214,7 @@ struct FileLoadResult {
QString thumbname; QString thumbname;
UploadFileParts thumbparts; UploadFileParts thumbparts;
QByteArray thumbmd5; QByteArray thumbmd5;
QPixmap thumb; QImage thumb;
MTPPhoto photo; MTPPhoto photo;
MTPDocument document; MTPDocument document;

File diff suppressed because it is too large Load diff

View file

@ -13,44 +13,363 @@ void ClearRemote();
void ClearAll(); void ClearAll();
void CheckCacheSize(); void CheckCacheSize();
class Source {
public:
virtual ~Source();
virtual void load(
Data::FileOrigin origin,
bool loadFirst,
bool prior) = 0;
virtual void loadEvenCancelled(
Data::FileOrigin origin,
bool loadFirst,
bool prior) = 0;
virtual QImage takeLoaded() = 0;
virtual void forget() = 0;
virtual void automaticLoad(
Data::FileOrigin origin,
const HistoryItem *item) = 0;
virtual void automaticLoadSettingsChanged() = 0;
virtual bool loading() = 0;
virtual bool displayLoading() = 0;
virtual void cancel() = 0;
virtual float64 progress() = 0;
virtual int loadOffset() = 0;
virtual const StorageImageLocation &location() = 0;
virtual void refreshFileReference(const QByteArray &data) = 0;
virtual std::optional<Storage::Cache::Key> cacheKey() = 0;
virtual void setDelayedStorageLocation(
const StorageImageLocation &location) = 0;
virtual void performDelayedLoad(Data::FileOrigin origin) = 0;
virtual bool isDelayedStorageImage() const = 0;
virtual void setImageBytes(const QByteArray &bytes) = 0;
virtual int width() = 0;
virtual int height() = 0;
virtual void setInformation(int size, int width, int height) = 0;
virtual QByteArray bytesForCache() = 0;
};
class ImageSource : public Source {
public:
ImageSource(QImage &&data, const QByteArray &format);
void load(
Data::FileOrigin origin,
bool loadFirst,
bool prior) override;
void loadEvenCancelled(
Data::FileOrigin origin,
bool loadFirst,
bool prior) override;
QImage takeLoaded() override;
void forget() override;
void automaticLoad(
Data::FileOrigin origin,
const HistoryItem *item) override;
void automaticLoadSettingsChanged() override;
bool loading() override;
bool displayLoading() override;
void cancel() override;
float64 progress() override;
int loadOffset() override;
const StorageImageLocation &location() override;
void refreshFileReference(const QByteArray &data) override;
std::optional<Storage::Cache::Key> cacheKey() override;
void setDelayedStorageLocation(
const StorageImageLocation &location) override;
void performDelayedLoad(Data::FileOrigin origin) override;
bool isDelayedStorageImage() const override;
void setImageBytes(const QByteArray &bytes) override;
int width() override;
int height() override;
void setInformation(int size, int width, int height) override;
QByteArray bytesForCache() override;
private:
QImage _data;
QByteArray _format;
};
class LocalFileSource : public Source {
public:
LocalFileSource(
const QString &path,
const QByteArray &content,
const QByteArray &format,
QImage &&data = QImage());
void load(
Data::FileOrigin origin,
bool loadFirst,
bool prior) override;
void loadEvenCancelled(
Data::FileOrigin origin,
bool loadFirst,
bool prior) override;
QImage takeLoaded() override;
void forget() override;
void automaticLoad(
Data::FileOrigin origin,
const HistoryItem *item) override;
void automaticLoadSettingsChanged() override;
bool loading() override;
bool displayLoading() override;
void cancel() override;
float64 progress() override;
int loadOffset() override;
const StorageImageLocation &location() override;
void refreshFileReference(const QByteArray &data) override;
std::optional<Storage::Cache::Key> cacheKey() override;
void setDelayedStorageLocation(
const StorageImageLocation &location) override;
void performDelayedLoad(Data::FileOrigin origin) override;
bool isDelayedStorageImage() const override;
void setImageBytes(const QByteArray &bytes) override;
int width() override;
int height() override;
void setInformation(int size, int width, int height) override;
QByteArray bytesForCache() override;
private:
void ensureDimensionsKnown();
QString _path;
QByteArray _bytes;
QByteArray _format;
QImage _data;
int _width = 0;
int _height = 0;
};
class RemoteSource : public Source {
public:
void load(
Data::FileOrigin origin,
bool loadFirst,
bool prior) override;
void loadEvenCancelled(
Data::FileOrigin origin,
bool loadFirst,
bool prior) override;
QImage takeLoaded() override;
void forget() override;
void automaticLoad(
Data::FileOrigin origin,
const HistoryItem *item) override;
void automaticLoadSettingsChanged() override;
bool loading() override;
bool displayLoading() override;
void cancel() override;
float64 progress() override;
int loadOffset() override;
const StorageImageLocation &location() override;
void refreshFileReference(const QByteArray &data) override;
void setDelayedStorageLocation(
const StorageImageLocation &location) override;
void performDelayedLoad(Data::FileOrigin origin) override;
bool isDelayedStorageImage() const override;
void setImageBytes(const QByteArray &bytes) override;
QByteArray bytesForCache() override;
~RemoteSource();
protected:
// If after loading the image we need to shrink it to fit into a
// specific size, you can return this size here.
virtual QSize shrinkBox() const = 0;
virtual FileLoader *createLoader(
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) = 0;
void loadLocal();
private:
bool loaderValid() const;
void destroyLoaderDelayed(FileLoader *newValue = nullptr);
FileLoader *_loader = nullptr;
};
class StorageSource : public RemoteSource {
public:
StorageSource(
const StorageImageLocation &location,
int size);
const StorageImageLocation &location() override;
std::optional<Storage::Cache::Key> cacheKey() override;
void refreshFileReference(const QByteArray &data) override;
int width() override;
int height() override;
void setInformation(int size, int width, int height) override;
protected:
QSize shrinkBox() const override;
FileLoader *createLoader(
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) override;
StorageImageLocation _location;
int _size = 0;
};
class WebCachedSource : public RemoteSource {
public:
WebCachedSource(const WebFileLocation &location, QSize box, int size = 0);
WebCachedSource(
const WebFileLocation &location,
int width,
int height,
int size = 0);
std::optional<Storage::Cache::Key> cacheKey() override;
int width() override;
int height() override;
void setInformation(int size, int width, int height) override;
protected:
QSize shrinkBox() const override;
FileLoader *createLoader(
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) override;
WebFileLocation _location;
QSize _box;
int _width = 0;
int _height = 0;
int _size = 0;
};
class GeoPointSource : public RemoteSource {
public:
GeoPointSource(const GeoPointLocation &location);
std::optional<Storage::Cache::Key> cacheKey() override;
int width() override;
int height() override;
void setInformation(int size, int width, int height) override;
protected:
QSize shrinkBox() const override;
FileLoader *createLoader(
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) override;
GeoPointLocation _location;
int _size = 0;
};
class DelayedStorageSource : public StorageSource {
public:
DelayedStorageSource();
DelayedStorageSource(int width, int height);
void load(
Data::FileOrigin origin,
bool loadFirst,
bool prior) override;
void loadEvenCancelled(
Data::FileOrigin origin,
bool loadFirst,
bool prior) override;
void setDelayedStorageLocation(
const StorageImageLocation &location) override;
bool isDelayedStorageImage() const override;
void performDelayedLoad(Data::FileOrigin origin) override;
void automaticLoad(
Data::FileOrigin origin,
const HistoryItem *item) override; // auto load photo
void automaticLoadSettingsChanged() override;
bool loading() override {
return _location.isNull() ? _loadRequested : StorageSource::loading();
}
bool displayLoading() override;
void cancel() override;
private:
bool _loadRequested = false;
bool _loadCancelled = false;
bool _loadFromCloud = false;
};
class WebUrlSource : public RemoteSource {
public:
// If !box.isEmpty() then resize the image to fit in this box.
explicit WebUrlSource(const QString &url, QSize box = QSize());
WebUrlSource(const QString &url, int width, int height);
std::optional<Storage::Cache::Key> cacheKey() override;
int width() override;
int height() override;
void setInformation(int size, int width, int height) override;
protected:
QSize shrinkBox() const override;
FileLoader *createLoader(
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) override;
private:
QString _url;
QSize _box;
int _size = 0;
int _width = 0;
int _height = 0;
};
} // namespace Images } // namespace Images
class HistoryItem; class HistoryItem;
class Image { class Image final {
public: public:
Image(const QString &file, QByteArray format = QByteArray()); explicit Image(std::unique_ptr<Images::Source> &&source);
Image(const QByteArray &filecontent, QByteArray format = QByteArray());
Image(const QPixmap &pixmap, QByteArray format = QByteArray());
Image(const QByteArray &filecontent, QByteArray format, const QPixmap &pixmap);
static Image *Blank(); static Image *Blank();
virtual void automaticLoad(
Data::FileOrigin origin,
const HistoryItem *item) {
}
virtual void automaticLoadSettingsChanged() {
}
virtual bool loaded() const {
return true;
}
virtual bool loading() const {
return false;
}
virtual bool displayLoading() const {
return false;
}
virtual void cancel() {
}
virtual float64 progress() const {
return 1;
}
virtual int32 loadOffset() const {
return 0;
}
const QPixmap &pix( const QPixmap &pix(
Data::FileOrigin origin, Data::FileOrigin origin,
int32 w = 0, int32 w = 0,
@ -120,285 +439,85 @@ public:
int32 w, int32 w,
int32 h = 0) const; int32 h = 0) const;
int32 width() const { void automaticLoad(Data::FileOrigin origin, const HistoryItem *item) {
return qMax(countWidth(), 1); if (!loaded()) {
_source->automaticLoad(origin, item);
}
} }
void automaticLoadSettingsChanged() {
int32 height() const { _source->automaticLoadSettingsChanged();
return qMax(countHeight(), 1);
} }
bool loading() const {
virtual void load( return _source->loading();
Data::FileOrigin origin,
bool loadFirst = false,
bool prior = true) {
} }
bool displayLoading() const {
virtual void loadEvenCancelled( return _source->displayLoading();
Data::FileOrigin origin,
bool loadFirst = false,
bool prior = true) {
} }
void cancel() {
virtual const StorageImageLocation &location() const { _source->cancel();
return StorageImageLocation::Null;
} }
virtual std::optional<Storage::Cache::Key> cacheKey() const; float64 progress() const {
return loaded() ? 1. : _source->progress();
bool isNull() const;
void forget() const;
QByteArray savedFormat() const {
return _format;
} }
QByteArray savedData() const { int loadOffset() const {
return _saved; return _source->loadOffset();
} }
int width() const {
virtual void setDelayedStorageLocation( return _source->width();
Data::FileOrigin origin,
const StorageImageLocation location) {
};
virtual bool isDelayedStorageImage() const {
return false;
} }
int height() const {
virtual ~Image(); return _source->height();
protected:
Image(QByteArray format = "PNG") : _format(format) {
} }
void setInformation(int size, int width, int height) {
void restore() const; _source->setInformation(size, width, height);
virtual void checkload() const {
} }
void invalidateSizeCache() const;
virtual int32 countWidth() const {
restore();
return _data.width();
}
virtual int32 countHeight() const {
restore();
return _data.height();
}
mutable QByteArray _saved, _format;
mutable bool _forgot = false;
mutable QPixmap _data;
private:
using Sizes = QMap<uint64, QPixmap>;
mutable Sizes _sizesCache;
};
class RemoteImage : public Image {
public:
void automaticLoad(
Data::FileOrigin origin,
const HistoryItem *item) override; // auto load photo
void automaticLoadSettingsChanged() override;
bool loaded() const override;
bool loading() const override {
return amLoading();
}
bool displayLoading() const override;
void cancel() override;
float64 progress() const override;
int32 loadOffset() const override;
void setImageBytes(
const QByteArray &bytes,
const QByteArray &format = QByteArray());
void load( void load(
Data::FileOrigin origin, Data::FileOrigin origin,
bool loadFirst = false, bool loadFirst = false,
bool prior = true) override; bool prior = true) {
if (!loaded()) {
_source->load(origin, loadFirst, prior);
}
}
void loadEvenCancelled( void loadEvenCancelled(
Data::FileOrigin origin, Data::FileOrigin origin,
bool loadFirst = false, bool loadFirst = false,
bool prior = true) override; bool prior = true) {
if (!loaded()) {
~RemoteImage(); _source->loadEvenCancelled(origin, loadFirst, prior);
}
protected:
// If after loading the image we need to shrink it to fit into a
// specific size, you can return this size here.
virtual QSize shrinkBox() const {
return QSize();
} }
virtual void setInformation(int32 size, int32 width, int32 height) = 0; const StorageImageLocation &location() const {
virtual FileLoader *createLoader( return _source->location();
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) = 0;
void checkload() const override {
doCheckload();
} }
void loadLocal();
private:
mutable FileLoader *_loader = nullptr;
bool amLoading() const;
void doCheckload() const;
void destroyLoaderDelayed(FileLoader *newValue = nullptr) const;
};
class StorageImage : public RemoteImage {
public:
explicit StorageImage(const StorageImageLocation &location, int32 size = 0);
StorageImage(const StorageImageLocation &location, const QByteArray &bytes);
const StorageImageLocation &location() const override {
return _location;
}
std::optional<Storage::Cache::Key> cacheKey() const override;
void refreshFileReference(const QByteArray &data) { void refreshFileReference(const QByteArray &data) {
_location.refreshFileReference(data); _source->refreshFileReference(data);
}
std::optional<Storage::Cache::Key> cacheKey() const;
QByteArray bytesForCache() const {
return _source->bytesForCache();
}
bool isDelayedStorageImage() const {
return _source->isDelayedStorageImage();
} }
protected: bool loaded() const;
void setInformation(int32 size, int32 width, int32 height) override; bool isNull() const;
FileLoader *createLoader( void forget() const;
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) override;
int32 countWidth() const override;
int32 countHeight() const override;
StorageImageLocation _location;
int32 _size;
};
class WebFileImage : public RemoteImage {
public:
WebFileImage(const WebFileLocation &location, QSize box, int size = 0);
WebFileImage(
const WebFileLocation &location,
int width,
int height,
int size = 0);
std::optional<Storage::Cache::Key> cacheKey() const override;
protected:
void setInformation(int size, int width, int height) override;
FileLoader *createLoader(
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) override;
QSize shrinkBox() const override {
return _box;
}
int countWidth() const override;
int countHeight() const override;
WebFileLocation _location;
QSize _box;
int _width = 0;
int _height = 0;
int _size = 0;
};
class GeoPointImage : public RemoteImage {
public:
GeoPointImage(const GeoPointLocation &location);
std::optional<Storage::Cache::Key> cacheKey() const override;
protected:
void setInformation(int size, int width, int height) override;
FileLoader *createLoader(
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) override;
int countWidth() const override;
int countHeight() const override;
GeoPointLocation _location;
int _size = 0;
};
class DelayedStorageImage : public StorageImage {
public:
DelayedStorageImage();
DelayedStorageImage(int32 w, int32 h);
//DelayedStorageImage(QByteArray &bytes);
void setDelayedStorageLocation( void setDelayedStorageLocation(
Data::FileOrigin origin, Data::FileOrigin origin,
const StorageImageLocation location) override; const StorageImageLocation &location);
bool isDelayedStorageImage() const override { void setImageBytes(const QByteArray &bytes);
return true;
}
void automaticLoad( ~Image();
Data::FileOrigin origin,
const HistoryItem *item) override; // auto load photo
void automaticLoadSettingsChanged() override;
bool loading() const override {
return _location.isNull() ? _loadRequested : StorageImage::loading();
}
bool displayLoading() const override;
void cancel() override;
void load(
Data::FileOrigin origin,
bool loadFirst = false,
bool prior = true) override;
void loadEvenCancelled(
Data::FileOrigin origin,
bool loadFirst = false,
bool prior = true) override;
private: private:
bool _loadRequested, _loadCancelled, _loadFromCloud; void checkSource() const;
void invalidateSizeCache() const;
}; std::unique_ptr<Images::Source> _source;
mutable QMap<uint64, QPixmap> _sizesCache;
class WebImage : public RemoteImage { mutable QImage _data;
public:
// If !box.isEmpty() then resize the image to fit in this box.
WebImage(const QString &url, QSize box = QSize());
WebImage(const QString &url, int width, int height);
void setSize(int width, int height);
std::optional<Storage::Cache::Key> cacheKey() const override;
protected:
QSize shrinkBox() const override {
return _box;
}
void setInformation(int32 size, int32 width, int32 height) override;
FileLoader *createLoader(
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) override;
int32 countWidth() const override;
int32 countHeight() const override;
private:
QString _url;
QSize _box;
int32 _size, _width, _height;
}; };
@ -409,28 +528,28 @@ Image *Create(const QString &file, QByteArray format);
Image *Create(const QString &url, QSize box); Image *Create(const QString &url, QSize box);
Image *Create(const QString &url, int width, int height); Image *Create(const QString &url, int width, int height);
Image *Create(const QByteArray &filecontent, QByteArray format); Image *Create(const QByteArray &filecontent, QByteArray format);
Image *Create(const QPixmap &pixmap, QByteArray format); Image *Create(QImage &&data, QByteArray format);
Image *Create( Image *Create(
const QByteArray &filecontent, const QByteArray &filecontent,
QByteArray format, QByteArray format,
const QPixmap &pixmap); QImage &&data);
Image *Create(int32 width, int32 height); Image *Create(int width, int height);
StorageImage *Create(const StorageImageLocation &location, int size = 0); Image *Create(const StorageImageLocation &location, int size = 0);
StorageImage *Create( // photoCachedSize Image *Create( // photoCachedSize
const StorageImageLocation &location, const StorageImageLocation &location,
const QByteArray &bytes); const QByteArray &bytes);
Image *Create(const MTPWebDocument &location); Image *Create(const MTPWebDocument &location);
Image *Create(const MTPWebDocument &location, QSize box); Image *Create(const MTPWebDocument &location, QSize box);
WebFileImage *Create( Image *Create(
const WebFileLocation &location, const WebFileLocation &location,
int width, int width,
int height, int height,
int size = 0); int size = 0);
WebFileImage *Create( Image *Create(
const WebFileLocation &location, const WebFileLocation &location,
QSize box, QSize box,
int size = 0); int size = 0);
GeoPointImage *Create( Image *Create(
const GeoPointLocation &location); const GeoPointLocation &location);
} // namespace details } // namespace details

View file

@ -389,12 +389,12 @@ ImagePtr::ImagePtr(const QByteArray &filecontent, QByteArray format)
ImagePtr::ImagePtr( ImagePtr::ImagePtr(
const QByteArray &filecontent, const QByteArray &filecontent,
QByteArray format, QByteArray format,
const QPixmap &pixmap) QImage &&data)
: _data(Images::details::Create(filecontent, format, pixmap)) { : _data(Images::details::Create(filecontent, format, std::move(data))) {
} }
ImagePtr::ImagePtr(const QPixmap &pixmap, QByteArray format) ImagePtr::ImagePtr(QImage &&data, QByteArray format)
: _data(Images::details::Create(pixmap, format)) { : _data(Images::details::Create(std::move(data), format)) {
} }
ImagePtr::ImagePtr(const StorageImageLocation &location, int32 size) ImagePtr::ImagePtr(const StorageImageLocation &location, int32 size)

View file

@ -287,8 +287,8 @@ public:
ImagePtr(const QString &url, QSize box); ImagePtr(const QString &url, QSize box);
ImagePtr(const QString &url, int width, int height); ImagePtr(const QString &url, int width, int height);
ImagePtr(const QByteArray &filecontent, QByteArray format = QByteArray()); ImagePtr(const QByteArray &filecontent, QByteArray format = QByteArray());
ImagePtr(const QByteArray &filecontent, QByteArray format, const QPixmap &pixmap); ImagePtr(const QByteArray &filecontent, QByteArray format, QImage &&data);
ImagePtr(const QPixmap &pixmap, QByteArray format); ImagePtr(QImage &&data, QByteArray format);
ImagePtr(const StorageImageLocation &location, int32 size = 0); ImagePtr(const StorageImageLocation &location, int32 size = 0);
ImagePtr(const StorageImageLocation &location, const QByteArray &bytes); ImagePtr(const StorageImageLocation &location, const QByteArray &bytes);
ImagePtr(const MTPWebDocument &location); ImagePtr(const MTPWebDocument &location);