upload radial progress and upload cancel done, photo / file / audio autodownload settings respected

This commit is contained in:
John Preston 2015-12-24 22:26:28 +03:00
parent 7c7d517b34
commit 4ed2d75c74
32 changed files with 2011 additions and 1558 deletions

View File

@ -593,6 +593,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
"lng_emoji_category7" = "Symbols & Flags"; "lng_emoji_category7" = "Symbols & Flags";
"lng_switch_stickers" = "Stickers"; "lng_switch_stickers" = "Stickers";
"lng_switch_stickers_gifs" = "GIFs & Stickers";
"lng_switch_emoji" = "Emoji"; "lng_switch_emoji" = "Emoji";
"lng_box_remove" = "Remove"; "lng_box_remove" = "Remove";

View File

@ -1176,7 +1176,7 @@ namespace App {
case 'm': newThumbLevel = 2; newMediumLevel = 0; newFullLevel = 3; break; // box 320x320 case 'm': newThumbLevel = 2; newMediumLevel = 0; newFullLevel = 3; break; // box 320x320
case 'x': newThumbLevel = 5; newMediumLevel = 3; newFullLevel = 1; break; // box 800x800 case 'x': newThumbLevel = 5; newMediumLevel = 3; newFullLevel = 1; break; // box 800x800
case 'y': newThumbLevel = 6; newMediumLevel = 6; newFullLevel = 0; break; // box 1280x1280 case 'y': newThumbLevel = 6; newMediumLevel = 6; newFullLevel = 0; break; // box 1280x1280
case 'w': newThumbLevel = 8; newMediumLevel = 8; newFullLevel = 2; break; // box 2560x2560 case 'w': newThumbLevel = 8; newMediumLevel = 8; newFullLevel = 2; break; // box 2560x2560 // if loading this fix HistoryPhoto::updateFrom
case 'a': newThumbLevel = 1; newMediumLevel = 4; newFullLevel = 8; break; // crop 160x160 case 'a': newThumbLevel = 1; newMediumLevel = 4; newFullLevel = 8; break; // crop 160x160
case 'b': newThumbLevel = 3; newMediumLevel = 1; newFullLevel = 7; break; // crop 320x320 case 'b': newThumbLevel = 3; newMediumLevel = 1; newFullLevel = 7; break; // crop 320x320
case 'c': newThumbLevel = 4; newMediumLevel = 2; newFullLevel = 6; break; // crop 640x640 case 'c': newThumbLevel = 4; newMediumLevel = 2; newFullLevel = 6; break; // crop 640x640
@ -1431,6 +1431,8 @@ namespace App {
photosData.erase(i); photosData.erase(i);
} }
convert->id = photo; convert->id = photo;
delete convert->uploadingData;
convert->uploadingData = 0;
} }
convert->access = access; convert->access = access;
if (!convert->date && date) { if (!convert->date && date) {
@ -1624,7 +1626,7 @@ namespace App {
} }
} }
} }
if (convert->sticker() && !convert->sticker()->loc.dc && thumbLocation.dc) { if (convert->sticker() && convert->sticker()->loc.isNull() && !thumbLocation.isNull()) {
convert->sticker()->loc = thumbLocation; convert->sticker()->loc = thumbLocation;
} }
@ -1671,7 +1673,7 @@ namespace App {
} }
} }
} }
if (result->sticker() && !result->sticker()->loc.dc && thumbLocation.dc) { if (result->sticker() && result->sticker()->loc.isNull() && !thumbLocation.isNull()) {
result->sticker()->loc = thumbLocation; result->sticker()->loc = thumbLocation;
} }
} }

View File

@ -455,7 +455,7 @@ void AudioPlayer::play(const AudioMsgId &audio, int64 position) {
} }
current->audio = audio; current->audio = audio;
current->file = audio.audio->location(true); current->file = audio.audio->location(true);
current->data = audio.audio->data; current->data = audio.audio->data();
if (current->file.isEmpty() && current->data.isEmpty()) { if (current->file.isEmpty() && current->data.isEmpty()) {
setStoppedState(current, AudioPlayerStoppedAtError); setStoppedState(current, AudioPlayerStoppedAtError);
onError(audio); onError(audio);
@ -499,14 +499,11 @@ void AudioPlayer::play(const SongMsgId &song, int64 position) {
} }
current->song = song; current->song = song;
current->file = song.song->location(true); current->file = song.song->location(true);
current->data = song.song->data; current->data = song.song->data();
if (current->file.isEmpty() && current->data.isEmpty()) { if (current->file.isEmpty() && current->data.isEmpty()) {
setStoppedState(current); setStoppedState(current);
if (!song.song->loader) { if (!song.song->loading()) {
DocumentOpenLink::doOpen(song.song); DocumentOpenLink::doOpen(song.song);
song.song->openOnSave = 0;
song.song->openOnSaveMsgId = FullMsgId();
if (song.song->loader) song.song->loader->start(true, true);
} }
} else { } else {
current->state = fadedStart ? AudioPlayerStarting : AudioPlayerPlaying; current->state = fadedStart ? AudioPlayerStarting : AudioPlayerPlaying;

View File

@ -147,16 +147,14 @@ void StickerSetInner::paintEvent(QPaintEvent *e) {
if (goodThumb) { if (goodThumb) {
doc->thumb->load(); doc->thumb->load();
} else { } else {
bool already = !doc->already().isEmpty(), hasdata = !doc->data.isEmpty(); if (doc->status == FileReady) {
if (!already && !hasdata && !doc->loader && doc->status == FileReady) { doc->automaticLoad(0);
doc->openOnSave = 0;
doc->save(QString());
} }
if (doc->sticker()->img->isNull() && (already || hasdata)) { if (doc->sticker()->img->isNull() && doc->loaded() && doc->loaded(true)) {
if (already) { if (doc->data().isEmpty()) {
doc->sticker()->img = ImagePtr(doc->already()); doc->sticker()->img = ImagePtr(doc->already());
} else { } else {
doc->sticker()->img = ImagePtr(doc->data); doc->sticker()->img = ImagePtr(doc->data());
} }
} }
} }

View File

@ -1331,18 +1331,7 @@ void StickerPanInner::paintEvent(QPaintEvent *e) {
if (goodThumb) { if (goodThumb) {
sticker->thumb->load(); sticker->thumb->load();
} else { } else {
bool already = !sticker->already().isEmpty(), hasdata = !sticker->data.isEmpty(); sticker->checkSticker();
if (!already && !hasdata && !sticker->loader && sticker->status == FileReady) {
sticker->openOnSave = 0;
sticker->save(QString());
}
if (sticker->sticker()->img->isNull() && (already || hasdata)) {
if (already) {
sticker->sticker()->img = ImagePtr(sticker->already());
} else {
sticker->sticker()->img = ImagePtr(sticker->data);
}
}
} }
float64 coef = qMin((st::stickerPanSize.width() - st::msgRadius * 2) / float64(sticker->dimensions.width()), (st::stickerPanSize.height() - st::msgRadius * 2) / float64(sticker->dimensions.height())); float64 coef = qMin((st::stickerPanSize.width() - st::msgRadius * 2) / float64(sticker->dimensions.width()), (st::stickerPanSize.height() - st::msgRadius * 2) / float64(sticker->dimensions.height()));
@ -1521,18 +1510,7 @@ void StickerPanInner::preloadImages() {
if (goodThumb) { if (goodThumb) {
sticker->thumb->load(); sticker->thumb->load();
} else { } else {
bool already = !sticker->already().isEmpty(), hasdata = !sticker->data.isEmpty(); sticker->automaticLoad(0);
if (!already && !hasdata && !sticker->loader && sticker->status == FileReady) {
sticker->openOnSave = 0;
sticker->save(QString());
}
//if (sticker->sticker->img->isNull() && (already || hasdata)) {
// if (already) {
// sticker->sticker->img = ImagePtr(sticker->already());
// } else {
// sticker->sticker->img = ImagePtr(sticker->data);
// }
//}
} }
} }
if (k > StickerPanPerRow * (StickerPanPerRow + 1)) break; if (k > StickerPanPerRow * (StickerPanPerRow + 1)) break;

View File

@ -154,9 +154,7 @@ namespace Notify {
if (HistoryMedia *media = item->getMedia()) { if (HistoryMedia *media = item->getMedia()) {
media->stopInline(item); media->stopInline(item);
if (DocumentData *document = media->getDocument()) { // forget data from memory if (DocumentData *document = media->getDocument()) { // forget data from memory
if (!document->data.isEmpty() && document->prepareAutoLoader(item)) { document->forget();
document->data.clear();
}
} }
stopped = true; stopped = true;
} }

View File

@ -46,7 +46,7 @@ void FileUploader::uploadMedia(const FullMsgId &msgId, const ReadyLocalMedia &me
} else if (media.type == PrepareAudio) { } else if (media.type == PrepareAudio) {
AudioData *audio = App::feedAudio(media.audio); AudioData *audio = App::feedAudio(media.audio);
audio->status = FileUploading; audio->status = FileUploading;
audio->data = media.data; audio->setData(media.data);
} }
queue.insert(msgId, File(media)); queue.insert(msgId, File(media));
sendNext(); sendNext();
@ -54,7 +54,8 @@ void FileUploader::uploadMedia(const FullMsgId &msgId, const ReadyLocalMedia &me
void FileUploader::upload(const FullMsgId &msgId, const FileLoadResultPtr &file) { void FileUploader::upload(const FullMsgId &msgId, const FileLoadResultPtr &file) {
if (file->type == PreparePhoto) { if (file->type == PreparePhoto) {
App::feedPhoto(file->photo, file->photoThumbs); PhotoData *photo = App::feedPhoto(file->photo, file->photoThumbs);
photo->uploadingData = new PhotoData::UploadingData(file->partssize);
} else if (file->type == PrepareDocument) { } else if (file->type == PrepareDocument) {
DocumentData *document; DocumentData *document;
if (file->thumb.isNull()) { if (file->thumb.isNull()) {
@ -69,7 +70,7 @@ void FileUploader::upload(const FullMsgId &msgId, const FileLoadResultPtr &file)
} else if (file->type == PrepareAudio) { } else if (file->type == PrepareAudio) {
AudioData *audio = App::feedAudio(file->audio); AudioData *audio = App::feedAudio(file->audio);
audio->status = FileUploading; audio->status = FileUploading;
audio->data = file->content; audio->setData(file->content);
} }
queue.insert(msgId, File(file)); queue.insert(msgId, File(file));
sendNext(); sendNext();
@ -115,7 +116,7 @@ void FileUploader::killSessions() {
} }
void FileUploader::sendNext() { void FileUploader::sendNext() {
if (sentSize >= MaxUploadFileParallelSize) return; if (sentSize >= MaxUploadFileParallelSize || _paused.msg) return;
bool killing = killSessionsTimer.isActive(); bool killing = killSessionsTimer.isActive();
if (queue.isEmpty()) { if (queue.isEmpty()) {
@ -232,6 +233,15 @@ void FileUploader::cancel(const FullMsgId &msgId) {
} }
} }
void FileUploader::pause(const FullMsgId &msgId) {
_paused = msgId;
}
void FileUploader::unpause() {
_paused = FullMsgId();
sendNext();
}
void FileUploader::confirm(const FullMsgId &msgId) { void FileUploader::confirm(const FullMsgId &msgId) {
} }
@ -274,21 +284,28 @@ void FileUploader::partLoaded(const MTPBool &result, mtpRequestId requestId) {
int32 dc = dcIt.value(); int32 dc = dcIt.value();
dcMap.erase(dcIt); dcMap.erase(dcIt);
int32 sentPartSize = 0;
Queue::const_iterator k = queue.constFind(uploading); Queue::const_iterator k = queue.constFind(uploading);
if (i != requestsSent.cend()) { if (i != requestsSent.cend()) {
sentSize -= i.value().size(); sentPartSize = i.value().size();
sentSizes[dc] -= i.value().size();
requestsSent.erase(i); requestsSent.erase(i);
} else { } else {
sentSize -= k->docPartSize; sentPartSize = k->docPartSize;
sentSizes[dc] -= k->docPartSize;
docRequestsSent.erase(j); docRequestsSent.erase(j);
} }
sentSize -= sentPartSize;
sentSizes[dc] -= sentPartSize;
if (k->type() == PreparePhoto) { if (k->type() == PreparePhoto) {
k->fileSentSize += sentPartSize;
PhotoData *photo = App::photo(k->id());
if (photo->uploading() && k->file) {
photo->uploadingData->size = k->file->partssize;
photo->uploadingData->offset = k->fileSentSize;
}
emit photoProgress(k.key()); emit photoProgress(k.key());
} else if (k->type() == PrepareDocument) { } else if (k->type() == PrepareDocument) {
DocumentData *doc = App::document(k->id()); DocumentData *doc = App::document(k->id());
if (doc->status == FileUploading) { if (doc->uploading()) {
doc->uploadOffset = (k->docSentParts - docRequestsSent.size()) * k->docPartSize; doc->uploadOffset = (k->docSentParts - docRequestsSent.size()) * k->docPartSize;
if (doc->uploadOffset > doc->size) { if (doc->uploadOffset > doc->size) {
doc->uploadOffset = doc->size; doc->uploadOffset = doc->size;
@ -297,7 +314,7 @@ void FileUploader::partLoaded(const MTPBool &result, mtpRequestId requestId) {
emit documentProgress(k.key()); emit documentProgress(k.key());
} else if (k->type() == PrepareAudio) { } else if (k->type() == PrepareAudio) {
AudioData *audio = App::audio(k->id()); AudioData *audio = App::audio(k->id());
if (audio->status == FileUploading) { if (audio->uploading()) {
audio->uploadOffset = (k->docSentParts - docRequestsSent.size()) * k->docPartSize; audio->uploadOffset = (k->docSentParts - docRequestsSent.size()) * k->docPartSize;
if (audio->uploadOffset > audio->size) { if (audio->uploadOffset > audio->size) {
audio->uploadOffset = audio->size; audio->uploadOffset = audio->size;

View File

@ -35,12 +35,14 @@ public:
int32 fullSize(const FullMsgId &msgId) const; int32 fullSize(const FullMsgId &msgId) const;
void cancel(const FullMsgId &msgId); void cancel(const FullMsgId &msgId);
void pause(const FullMsgId &msgId);
void confirm(const FullMsgId &msgId); void confirm(const FullMsgId &msgId);
void clear(); void clear();
public slots: public slots:
void unpause();
void sendNext(); void sendNext();
void killSessions(); void killSessions();
@ -101,6 +103,7 @@ private:
FileLoadResultPtr file; FileLoadResultPtr file;
ReadyLocalMedia media; ReadyLocalMedia media;
int32 partsCount; int32 partsCount;
mutable int32 fileSentSize;
uint64 id() const { uint64 id() const {
return file ? file->id : media.id; return file ? file->id : media.id;
@ -136,7 +139,7 @@ private:
uint32 sentSize; uint32 sentSize;
uint32 sentSizes[MTPUploadSessionsCount]; uint32 sentSizes[MTPUploadSessionsCount];
FullMsgId uploading; FullMsgId uploading, _paused;
Queue queue; Queue queue;
Queue uploaded; Queue uploaded;
QTimer nextTimer, killSessionsTimer; QTimer nextTimer, killSessionsTimer;

View File

@ -619,97 +619,165 @@ int64 imageCacheSize() {
return globalAquiredSize; return globalAquiredSize;
} }
StorageImage::StorageImage(const StorageImageLocation &location, int32 size) : w(location.width), h(location.height), loader(new mtpFileLoader(location.dc, location.volume, location.local, location.secret, size)) { StorageImage::StorageImage(const StorageImageLocation &location, int32 size) : _location(location), _size(size), _loader(0) {
} }
StorageImage::StorageImage(const StorageImageLocation &location, QByteArray &bytes) : w(location.width), h(location.height), loader(0) { StorageImage::StorageImage(const StorageImageLocation &location, QByteArray &bytes) : _location(location), _size(bytes.size()), _loader(0) {
setData(bytes); setData(bytes);
if (location.dc) { if (!_location.isNull()) {
Local::writeImage(storageKey(location.dc, location.volume, location.local), StorageImageSaved(mtpToStorageType(mtpc_storage_filePartial), bytes)); Local::writeImage(storageKey(_location), StorageImageSaved(mtpToStorageType(mtpc_storage_filePartial), bytes));
} }
} }
const QPixmap &StorageImage::pixData() const { const QPixmap &StorageImage::pixData() const {
return data; return _data;
} }
int32 StorageImage::width() const { int32 StorageImage::width() const {
return w; return _location.width();
} }
int32 StorageImage::height() const { int32 StorageImage::height() const {
return h; return _location.height();
} }
bool StorageImage::check() const { void StorageImage::checkload() const {
if (loader->done()) { if (!amLoading() || !_loader->done()) return;
if (!data.isNull()) {
globalAquiredSize -= int64(data.width()) * data.height() * 4;
}
format = loader->imageFormat();
data = loader->imagePixmap();
QByteArray bytes = loader->bytes();
if (!data.isNull()) {
globalAquiredSize += int64(data.width()) * data.height() * 4;
}
w = data.width(); QPixmap data = _loader->imagePixmap();
h = data.height(); if (data.isNull()) {
invalidateSizeCache(); _loader->deleteLater();
loader->deleteLater(); _loader->rpcInvalidate();
loader->rpcInvalidate(); _loader = CancelledFileLoader;
loader = 0; return;
saved = bytes;
forgot = false;
return true;
}
return false;
}
void StorageImage::setData(QByteArray &bytes, const QByteArray &format) {
QBuffer buffer(&bytes);
if (!data.isNull()) {
globalAquiredSize -= int64(data.width()) * data.height() * 4;
}
QByteArray fmt(format);
data = QPixmap::fromImage(App::readImage(bytes, &fmt, false), Qt::ColorOnly);
if (!data.isNull()) {
globalAquiredSize += int64(data.width()) * data.height() * 4;
} }
w = data.width(); if (!_data.isNull()) {
h = data.height(); globalAquiredSize -= int64(_data.width()) * _data.height() * 4;
}
format = _loader->imageFormat();
_data = data;
saved = _loader->bytes();
const_cast<StorageImage*>(this)->_size = saved.size();
const_cast<StorageImage*>(this)->_location.setSize(_data.width(), _data.height());
globalAquiredSize += int64(_data.width()) * _data.height() * 4;
invalidateSizeCache(); invalidateSizeCache();
if (loader) {
loader->deleteLater(); _loader->deleteLater();
loader->rpcInvalidate(); _loader->rpcInvalidate();
loader = 0; _loader = 0;
}
this->saved = bytes;
this->format = fmt;
forgot = false; forgot = false;
} }
StorageImage::~StorageImage() { void StorageImage::setData(QByteArray &bytes, const QByteArray &bytesFormat) {
if (!data.isNull()) { QBuffer buffer(&bytes);
globalAquiredSize -= int64(data.width()) * data.height() * 4;
if (!_data.isNull()) {
globalAquiredSize -= int64(_data.width()) * _data.height() * 4;
} }
if (loader) { QByteArray fmt(bytesFormat);
loader->deleteLater(); _data = QPixmap::fromImage(App::readImage(bytes, &fmt, false), Qt::ColorOnly);
loader->rpcInvalidate(); if (!_data.isNull()) {
loader = 0; globalAquiredSize += int64(_data.width()) * _data.height() * 4;
_location.setSize(_data.width(), _data.height());
}
invalidateSizeCache();
if (amLoading()) {
_loader->deleteLater();
_loader->rpcInvalidate();
_loader = 0;
}
saved = bytes;
format = fmt;
forgot = false;
}
void StorageImage::automaticLoad(const HistoryItem *item) {
if (loaded()) return;
if (_loader != CancelledFileLoader && item) {
bool loadFromCloud = false;
if (item->history()->peer->isUser()) {
loadFromCloud = !(cAutoDownloadPhoto() & dbiadNoPrivate);
} else {
loadFromCloud = !(cAutoDownloadPhoto() & dbiadNoGroups);
}
if (_loader) {
if (loadFromCloud) _loader->permitLoadFromCloud();
} else if (!_location.isNull()) {
_loader = new mtpFileLoader(&_location, _size, loadFromCloud ? LoadFromCloudOrLocal : LoadFromLocalOnly, true);
_loader->start();
}
}
}
void StorageImage::load(bool loadFirst, bool prior) {
if (loaded()) return;
if (!_loader && !_location.isNull()) {
_loader = new mtpFileLoader(&_location, _size, LoadFromCloudOrLocal, false);
}
if (amLoading()) {
_loader->start(loadFirst, prior);
}
}
void StorageImage::loadEvenCancelled(bool loadFirst, bool prior) {
if (_loader == CancelledFileLoader) _loader = 0;
return load(loadFirst, prior);
}
StorageImage::~StorageImage() {
if (!_data.isNull()) {
globalAquiredSize -= int64(_data.width()) * _data.height() * 4;
}
if (amLoading()) {
_loader->deleteLater();
_loader->rpcInvalidate();
_loader = 0;
} }
} }
bool StorageImage::loaded() const { bool StorageImage::loaded() const {
if (!loader) return true; checkload();
return check(); return (!_data.isNull() || !saved.isNull());
}
bool StorageImage::loading() const {
return amLoading();
}
bool StorageImage::displayLoading() const {
return amLoading() && (!_loader->loadingLocal() || !_loader->autoLoading());
}
void StorageImage::cancel() {
if (!amLoading()) return;
mtpFileLoader *l = _loader;
_loader = CancelledFileLoader;
if (l) {
l->cancel();
l->deleteLater();
l->rpcInvalidate();
}
}
float64 StorageImage::progress() const {
return amLoading() ? _loader->currentProgress() : (loaded() ? 1 : 0);
}
int32 StorageImage::loadOffset() const {
return amLoading() ? _loader->currentOffset() : 0;
} }
StorageImage *getImage(const StorageImageLocation &location, int32 size) { StorageImage *getImage(const StorageImageLocation &location, int32 size) {
StorageKey key(storageKey(location.dc, location.volume, location.local)); StorageKey key(storageKey(location));
StorageImages::const_iterator i = storageImages.constFind(key); StorageImages::const_iterator i = storageImages.constFind(key);
if (i == storageImages.cend()) { if (i == storageImages.cend()) {
i = storageImages.insert(key, new StorageImage(location, size)); i = storageImages.insert(key, new StorageImage(location, size));
@ -718,7 +786,7 @@ StorageImage *getImage(const StorageImageLocation &location, int32 size) {
} }
StorageImage *getImage(const StorageImageLocation &location, const QByteArray &bytes) { StorageImage *getImage(const StorageImageLocation &location, const QByteArray &bytes) {
StorageKey key(storageKey(location.dc, location.volume, location.local)); StorageKey key(storageKey(location));
StorageImages::const_iterator i = storageImages.constFind(key); StorageImages::const_iterator i = storageImages.constFind(key);
if (i == storageImages.cend()) { if (i == storageImages.cend()) {
QByteArray bytesArr(bytes); QByteArray bytesArr(bytes);
@ -726,8 +794,8 @@ StorageImage *getImage(const StorageImageLocation &location, const QByteArray &b
} else if (!i.value()->loaded()) { } else if (!i.value()->loaded()) {
QByteArray bytesArr(bytes); QByteArray bytesArr(bytes);
i.value()->setData(bytesArr); i.value()->setData(bytesArr);
if (location.dc) { if (!location.isNull()) {
Local::writeImage(storageKey(location.dc, location.volume, location.local), StorageImageSaved(mtpToStorageType(mtpc_storage_filePartial), bytes)); Local::writeImage(key, StorageImageSaved(mtpToStorageType(mtpc_storage_filePartial), bytes));
} }
} }
return i.value(); return i.value();

View File

@ -25,43 +25,116 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
QImage imageBlur(QImage img); QImage imageBlur(QImage img);
void imageRound(QImage &img); void imageRound(QImage &img);
struct StorageImageLocation { inline uint32 packInt(int32 a) {
StorageImageLocation() : width(0), height(0), dc(0), volume(0), local(0), secret(0) { return (a < 0) ? uint32(int64(a) + 0x100000000LL) : uint32(a);
}
inline int32 unpackInt(uint32 a) {
return (a > 0x7FFFFFFFU) ? int32(int64(a) - 0x100000000LL) : int32(a);
}
inline uint64 packUIntUInt(uint32 a, uint32 b) {
return (uint64(a) << 32) | uint64(b);
}
inline uint64 packUIntInt(uint32 a, int32 b) {
return packUIntUInt(a, packInt(b));
}
inline uint64 packIntUInt(int32 a, uint32 b) {
return packUIntUInt(packInt(a), b);
}
inline uint64 packIntInt(int32 a, int32 b) {
return packUIntUInt(packInt(a), packInt(b));
}
inline uint32 unpackUIntFirst(uint64 v) {
return uint32(v >> 32);
}
inline int32 unpackIntFirst(uint64 v) {
return unpackInt(unpackUIntFirst(v));
}
inline uint32 unpackUIntSecond(uint64 v) {
return uint32(v & 0xFFFFFFFFULL);
}
inline int32 unpackIntSecond(uint64 v) {
return unpackInt(unpackUIntSecond(v));
}
class StorageImageLocation {
public:
StorageImageLocation() : _widthheight(0), _dclocal(0), _volume(0), _secret(0) {
} }
StorageImageLocation(int32 width, int32 height, int32 dc, const uint64 &volume, int32 local, const uint64 &secret) : width(width), height(height), dc(dc), volume(volume), local(local), secret(secret) { StorageImageLocation(int32 width, int32 height, int32 dc, const uint64 &volume, int32 local, const uint64 &secret) : _widthheight(packIntInt(width, height)), _dclocal(packIntInt(dc, local)), _volume(volume), _secret(secret) {
} }
StorageImageLocation(int32 width, int32 height, const MTPDfileLocation &location) : width(width), height(height), dc(location.vdc_id.v), volume(location.vvolume_id.v), local(location.vlocal_id.v), secret(location.vsecret.v) { StorageImageLocation(int32 width, int32 height, const MTPDfileLocation &location) : _widthheight(packIntInt(width, height)), _dclocal(packIntInt(location.vdc_id.v, location.vlocal_id.v)), _volume(location.vvolume_id.v), _secret(location.vsecret.v) {
} }
bool isNull() const { bool isNull() const {
return !dc; return !_dclocal;
} }
int32 width, height; int32 width() const {
int32 dc; return unpackIntFirst(_widthheight);
uint64 volume; }
int32 local; int32 height() const {
uint64 secret; return unpackIntSecond(_widthheight);
}
void setSize(int32 width, int32 height) {
_widthheight = packIntInt(width, height);
}
int32 dc() const {
return unpackIntFirst(_dclocal);
}
uint64 volume() const {
return _volume;
}
int32 local() const {
return unpackIntSecond(_dclocal);
}
uint64 secret() const {
return _secret;
}
private:
uint64 _widthheight;
uint64 _dclocal;
uint64 _volume;
uint64 _secret;
friend inline bool operator==(const StorageImageLocation &a, const StorageImageLocation &b) {
return (a._dclocal == b._dclocal) && (a._volume == b._volume) && (a._secret == b._secret);
}
}; };
inline bool operator==(const StorageImageLocation &a, const StorageImageLocation &b) {
return (a.width == b.width) && (a.height == b.height) && (a.dc == b.dc) && (a.volume == b.volume) && (a.local == b.local) && (a.secret == b.secret);
}
inline bool operator!=(const StorageImageLocation &a, const StorageImageLocation &b) { inline bool operator!=(const StorageImageLocation &a, const StorageImageLocation &b) {
return !(a == b); return !(a == b);
} }
QPixmap imagePix(QImage img, int32 w, int32 h, bool smooth, bool blurred, bool rounded, int32 outerw, int32 outerh); QPixmap imagePix(QImage img, int32 w, int32 h, bool smooth, bool blurred, bool rounded, int32 outerw, int32 outerh);
class HistoryItem;
class Image { class Image {
public: public:
Image(QByteArray format = "PNG") : format(format), forgot(false) { Image(QByteArray format = "PNG") : format(format), forgot(false) {
} }
virtual void automaticLoad(const HistoryItem *item) { // auto load photo
}
virtual bool loaded() const { virtual bool loaded() const {
return true; return true;
} }
virtual bool loading() const { virtual bool loading() const {
return false; 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(int32 w = 0, int32 h = 0) const; const QPixmap &pix(int32 w = 0, int32 h = 0) const;
const QPixmap &pixRounded(int32 w = 0, int32 h = 0) const; const QPixmap &pixRounded(int32 w = 0, int32 h = 0) const;
const QPixmap &pixBlurred(int32 w = 0, int32 h = 0) const; const QPixmap &pixBlurred(int32 w = 0, int32 h = 0) const;
@ -76,10 +149,9 @@ public:
virtual int32 width() const = 0; virtual int32 width() const = 0;
virtual int32 height() const = 0; virtual int32 height() const = 0;
virtual void load(bool /*loadFirst*/ = false, bool /*prior*/ = true) { virtual void load(bool loadFirst = false, bool prior = true) {
} }
virtual void loadEvenCancelled(bool loadFirst = false, bool prior = true) {
virtual void checkload() const {
} }
bool isNull() const; bool isNull() const;
@ -100,6 +172,9 @@ public:
protected: protected:
virtual void checkload() const {
}
virtual const QPixmap &pixData() const = 0; virtual const QPixmap &pixData() const = 0;
virtual void doForget() const = 0; virtual void doForget() const = 0;
virtual void doRestore() const = 0; virtual void doRestore() const = 0;
@ -165,7 +240,7 @@ inline StorageKey storageKey(const MTPDfileLocation &location) {
return storageKey(location.vdc_id.v, location.vvolume_id.v, location.vlocal_id.v); return storageKey(location.vdc_id.v, location.vvolume_id.v, location.vlocal_id.v);
} }
inline StorageKey storageKey(const StorageImageLocation &location) { inline StorageKey storageKey(const StorageImageLocation &location) {
return storageKey(location.dc, location.volume, location.local); return storageKey(location.dc(), location.volume(), location.local());
} }
class StorageImage : public Image { class StorageImage : public Image {
@ -176,35 +251,29 @@ public:
int32 width() const; int32 width() const;
int32 height() const; int32 height() const;
void automaticLoad(const HistoryItem *item); // auto load photo
bool loaded() const; bool loaded() const;
bool loading() const { bool loading() const;
return loader ? loader->loading() : false; bool displayLoading() const;
} void cancel();
float64 progress() const;
int32 loadOffset() const;
void setData(QByteArray &bytes, const QByteArray &format = QByteArray()); void setData(QByteArray &bytes, const QByteArray &format = QByteArray());
void load(bool loadFirst = false, bool prior = true) { void load(bool loadFirst = false, bool prior = true);
if (loader) { void loadEvenCancelled(bool loadFirst = false, bool prior = true);
loader->start(loadFirst, prior);
if (loader) check();
}
}
void checkload() const {
if (loader) {
if (!loader->loading()) {
loader->start(true);
}
if (loader) check();
}
}
~StorageImage(); ~StorageImage();
protected: protected:
const QPixmap &pixData() const; const QPixmap &pixData() const;
bool check() const; void checkload() const;
void doForget() const { void doForget() const {
data = QPixmap(); _data = QPixmap();
} }
void doRestore() const { void doRestore() const {
QBuffer buffer(&saved); QBuffer buffer(&saved);
@ -212,14 +281,19 @@ protected:
#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0) #if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
reader.setAutoTransform(true); reader.setAutoTransform(true);
#endif #endif
data = QPixmap::fromImageReader(&reader, Qt::ColorOnly); _data = QPixmap::fromImageReader(&reader, Qt::ColorOnly);
} }
private: private:
mutable QPixmap _data;
StorageImageLocation _location;
int32 _size;
mutable mtpFileLoader *_loader;
bool amLoading() const {
return _loader && _loader != CancelledFileLoader;
}
mutable QPixmap data;
mutable int32 w, h;
mutable mtpFileLoader *loader;
}; };
StorageImage *getImage(const StorageImageLocation &location, int32 size = 0); StorageImage *getImage(const StorageImageLocation &location, int32 size = 0);

View File

@ -2878,44 +2878,6 @@ void HistoryBlock::removeItem(HistoryItem *item) {
} }
} }
void ItemAnimations::step_animate(float64 ms, bool timer) {
for (Animations::iterator i = _animations.begin(); i != _animations.end();) {
const HistoryItem *item = i.key();
if (item->animating()) {
if (timer) Ui::redrawHistoryItem(item);
++i;
} else {
i = _animations.erase(i);
}
}
if (_animations.isEmpty()) {
_a_animate.stop();
}
}
uint64 ItemAnimations::animate(const HistoryItem *item, uint64 ms) {
if (_animations.isEmpty()) {
_animations.insert(item, ms);
_a_animate.start();
return 0;
}
Animations::const_iterator i = _animations.constFind(item);
if (i == _animations.cend()) i = _animations.insert(item, ms);
return ms - i.value();
}
void ItemAnimations::remove(const HistoryItem *item) {
_animations.remove(item);
}
namespace {
ItemAnimations _itemAnimations;
}
ItemAnimations &itemAnimations() {
return _itemAnimations;
}
HistoryItem::HistoryItem(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime msgDate, int32 from) : y(0) HistoryItem::HistoryItem(History *history, HistoryBlock *block, MsgId msgId, int32 flags, QDateTime msgDate, int32 from) : y(0)
, id(msgId) , id(msgId)
, date(msgDate) , date(msgDate)
@ -2989,7 +2951,6 @@ void HistoryItem::setId(MsgId newId) {
} }
HistoryItem::~HistoryItem() { HistoryItem::~HistoryItem() {
itemAnimations().remove(this);
App::historyUnregItem(this); App::historyUnregItem(this);
if (id < 0) { if (id < 0) {
App::app()->uploader()->cancel(fullId()); App::app()->uploader()->cancel(fullId());
@ -3079,35 +3040,49 @@ void RadialAnimation::draw(Painter &p, const QRect &inner, int32 thickness, cons
p.setOpacity(o); p.setOpacity(o);
} }
HistoryPhoto::HistoryPhoto(const MTPDphoto &photo, const QString &caption, HistoryItem *parent) : HistoryMedia() HistoryPhoto::HistoryPhoto(const MTPDphoto &photo, const QString &caption, HistoryItem *parent) : HistoryFileMedia()
, _data(App::feedPhoto(photo)) , _data(App::feedPhoto(photo))
, _openl(new PhotoLink(_data))
, _pixw(1) , _pixw(1)
, _pixh(1) , _pixh(1)
, _caption(st::minPhotoSize - st::msgPadding.left() - st::msgPadding.right()) { , _caption(st::minPhotoSize - st::msgPadding.left() - st::msgPadding.right()) {
setLinks(new PhotoLink(_data), new PhotoLink(_data), new PhotoCancelLink(_data));
if (!caption.isEmpty()) { if (!caption.isEmpty()) {
_caption.setText(st::msgFont, caption + parent->skipBlock(), itemTextNoMonoOptions(parent)); _caption.setText(st::msgFont, caption + parent->skipBlock(), itemTextNoMonoOptions(parent));
} }
init(); init();
} }
HistoryPhoto::HistoryPhoto(PhotoData *photo) : HistoryMedia() HistoryPhoto::HistoryPhoto(PhotoData *photo) : HistoryFileMedia()
, _data(photo) , _data(photo)
, _openl(new PhotoLink(_data))
, _pixw(1) , _pixw(1)
, _pixh(1) { , _pixh(1) {
setLinks(new PhotoLink(_data), new PhotoLink(_data), new PhotoCancelLink(_data));
init(); init();
} }
HistoryPhoto::HistoryPhoto(PeerData *chat, const MTPDphoto &photo, int32 width) : HistoryMedia() HistoryPhoto::HistoryPhoto(PeerData *chat, const MTPDphoto &photo, int32 width) : HistoryFileMedia()
, _data(App::feedPhoto(photo)) , _data(App::feedPhoto(photo))
, _openl(new PhotoLink(_data, chat))
, _pixw(1) , _pixw(1)
, _pixh(1) { , _pixh(1) {
setLinks(new PhotoLink(_data, chat), new PhotoLink(_data, chat), new PhotoCancelLink(_data));
_width = width; _width = width;
init(); init();
} }
HistoryPhoto::HistoryPhoto(const HistoryPhoto &other) : HistoryFileMedia()
, _data(other._data)
, _caption(other._caption)
, _pixw(other._pixw)
, _pixh(other._pixh) {
setLinks(new PhotoLink(_data), new PhotoLink(_data), new PhotoCancelLink(_data));
init();
}
void HistoryPhoto::init() { void HistoryPhoto::init() {
_data->thumb->load(); _data->thumb->load();
} }
@ -3196,12 +3171,25 @@ int32 HistoryPhoto::resize(int32 width, const HistoryItem *parent) {
void HistoryPhoto::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { void HistoryPhoto::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const {
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return;
_data->automaticLoad(parent);
bool loaded = _data->loaded(), displayLoading = _data->displayLoading();
bool notChild = (parent->getMedia() == this);
int32 skipx = 0, skipy = 0, width = _width, height = _height; int32 skipx = 0, skipy = 0, width = _width, height = _height;
bool bubble = parent->hasBubble(); bool bubble = parent->hasBubble();
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel;
int32 captionw = width - st::msgPadding.left() - st::msgPadding.right(); int32 captionw = width - st::msgPadding.left() - st::msgPadding.right();
if (displayLoading) {
ensureAnimation(parent);
if (!_animation->radial.animating()) {
_animation->radial.start(_data->progress());
}
}
bool radial = isRadialAnimation(ms);
if (bubble) { if (bubble) {
skipx = st::mediaPadding.left(); skipx = st::mediaPadding.left();
skipy = st::mediaPadding.top(); skipy = st::mediaPadding.top();
@ -3214,45 +3202,61 @@ void HistoryPhoto::draw(Painter &p, const HistoryItem *parent, const QRect &r, b
} else { } else {
App::roundShadow(p, 0, 0, width, height, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners); App::roundShadow(p, 0, 0, width, height, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners);
} }
_data->full->load(false, false);
bool full = _data->full->loaded();
QPixmap pix; QPixmap pix;
if (full) { if (loaded) {
pix = _data->full->pixSingle(_pixw, _pixh, width, height); pix = _data->full->pixSingle(_pixw, _pixh, width, height);
} else { } else {
pix = _data->thumb->pixBlurredSingle(_pixw, _pixh, width, height); pix = _data->thumb->pixBlurredSingle(_pixw, _pixh, width, height);
} }
QRect rthumb(rtlrect(skipx, skipy, width, height, _width));
p.drawPixmapLeft(skipx, skipy, _width, pix); p.drawPixmap(rthumb.topLeft(), pix);
if (!full) { if (selected) {
uint64 dt = itemAnimations().animate(parent, ms); App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners);
int32 cnt = int32(st::photoLoaderCnt), period = int32(st::photoLoaderPeriod), t = dt % period, delta = int32(st::photoLoaderDelta);
int32 x = (width - st::photoLoader.width()) / 2, y = (height - st::photoLoader.height()) / 2;
p.fillRect(skipx + x, skipy + y, st::photoLoader.width(), st::photoLoader.height(), st::photoLoaderBg->b);
x += (st::photoLoader.width() - cnt * st::photoLoaderPoint.width() - (cnt - 1) * st::photoLoaderSkip) / 2;
y += (st::photoLoader.height() - st::photoLoaderPoint.height()) / 2;
QColor c(st::white->c);
QBrush b(c);
for (int32 i = 0; i < cnt; ++i) {
t -= delta;
while (t < 0) t += period;
float64 alpha = (t >= st::photoLoaderDuration1 + st::photoLoaderDuration2) ? 0 : ((t > st::photoLoaderDuration1 ? ((st::photoLoaderDuration1 + st::photoLoaderDuration2 - t) / st::photoLoaderDuration2) : (t / st::photoLoaderDuration1)));
c.setAlphaF(st::photoLoaderAlphaMin + alpha * (1 - st::photoLoaderAlphaMin));
b.setColor(c);
p.fillRect(skipx + x + i * (st::photoLoaderPoint.width() + st::photoLoaderSkip), skipy + y, st::photoLoaderPoint.width(), st::photoLoaderPoint.height(), b);
}
} }
if (selected) { if (notChild && (radial || (!loaded && !_data->loading()))) {
App::roundRect(p, rtlrect(skipx, skipy, width, height, _width), textstyleCurrent()->selectOverlay, SelectedOverlayCorners); float64 radialOpacity = (radial && loaded && !_data->uploading()) ? _animation->radial.opacity() : 1;
QRect inner(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
p.setPen(Qt::NoPen);
if (selected) {
p.setBrush(st::msgDateImgBgSelected);
} else if (_animation && _animation->_a_thumbOver.animating()) {
_animation->_a_thumbOver.step(ms);
float64 over = _animation->a_thumbOver.current();
p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over));
p.setBrush(st::black);
} else {
bool over = textlnkDrawOver(_data->loading() ? _cancell : _savel);
p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg);
}
p.setOpacity(radialOpacity * p.opacity());
p.setRenderHint(QPainter::HighQualityAntialiasing);
p.drawEllipse(inner);
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
p.setOpacity(radial ? _animation->radial.opacity() : 1);
p.setOpacity(radialOpacity);
style::sprite icon;
if (radial || _data->loading()) {
icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
} else {
icon = (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload);
}
p.drawSpriteCenter(inner, icon);
if (radial) {
p.setOpacity(1);
QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine)));
_animation->radial.draw(p, rinner, st::msgFileRadialLine, selected ? st::msgInBgSelected : st::msgInBg);
}
} }
// date // date
if (_caption.isEmpty()) { if (_caption.isEmpty()) {
if (parent->getMedia() == this) { if (notChild) {
int32 fullRight = skipx + width, fullBottom = skipy + height; int32 fullRight = skipx + width, fullBottom = skipy + height;
parent->drawInfo(p, fullRight, fullBottom, 2 * skipx + width, selected, InfoDisplayOverImage); parent->drawInfo(p, fullRight, fullBottom, 2 * skipx + width, selected, InfoDisplayOverImage);
} }
@ -3284,7 +3288,11 @@ void HistoryPhoto::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x
height -= skipy + st::mediaPadding.bottom(); height -= skipy + st::mediaPadding.bottom();
} }
if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height) { if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height) {
lnk = _openl; if (_data->uploading()) {
lnk = _cancell;
} else {
lnk = _data->loaded() ? _openl : (_data->loading() ? _cancell : _savel);
}
if (_caption.isEmpty() && parent->getMedia() == this) { if (_caption.isEmpty() && parent->getMedia() == this) {
int32 fullRight = skipx + width, fullBottom = skipy + height; int32 fullRight = skipx + width, fullBottom = skipy + height;
bool inDate = parent->pointInTime(fullRight, fullBottom, x, y, InfoDisplayOverImage); bool inDate = parent->pointInTime(fullRight, fullBottom, x, y, InfoDisplayOverImage);
@ -3299,21 +3307,25 @@ void HistoryPhoto::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x
void HistoryPhoto::updateFrom(const MTPMessageMedia &media, HistoryItem *parent, bool allowEmitResize) { void HistoryPhoto::updateFrom(const MTPMessageMedia &media, HistoryItem *parent, bool allowEmitResize) {
if (media.type() == mtpc_messageMediaPhoto) { if (media.type() == mtpc_messageMediaPhoto) {
const MTPPhoto &photo(media.c_messageMediaPhoto().vphoto); const MTPPhoto &photo(media.c_messageMediaPhoto().vphoto);
App::feedPhoto(photo, _data);
if (photo.type() == mtpc_photo) { if (photo.type() == mtpc_photo) {
const QVector<MTPPhotoSize> &sizes(photo.c_photo().vsizes.c_vector().v); const QVector<MTPPhotoSize> &sizes(photo.c_photo().vsizes.c_vector().v);
for (QVector<MTPPhotoSize>::const_iterator i = sizes.cbegin(), e = sizes.cend(); i != e; ++i) { int32 max = 0;
const MTPDfileLocation *maxLocation = 0;
for (int32 i = 0, l = sizes.size(); i < l; ++i) {
char size = 0; char size = 0;
const MTPFileLocation *loc = 0; const MTPFileLocation *loc = 0;
switch (i->type()) { switch (sizes.at(i).type()) {
case mtpc_photoSize: { case mtpc_photoSize: {
const string &s(i->c_photoSize().vtype.c_string().v); const string &s(sizes.at(i).c_photoSize().vtype.c_string().v);
loc = &i->c_photoSize().vlocation; loc = &sizes.at(i).c_photoSize().vlocation;
if (s.size()) size = s[0]; if (s.size()) size = s[0];
} break; } break;
case mtpc_photoCachedSize: { case mtpc_photoCachedSize: {
const string &s(i->c_photoCachedSize().vtype.c_string().v); const string &s(sizes.at(i).c_photoCachedSize().vtype.c_string().v);
loc = &i->c_photoCachedSize().vlocation; loc = &sizes.at(i).c_photoCachedSize().vlocation;
if (s.size()) size = s[0]; if (s.size()) size = s[0];
} break; } break;
} }
@ -3322,10 +3334,20 @@ void HistoryPhoto::updateFrom(const MTPMessageMedia &media, HistoryItem *parent,
Local::writeImage(storageKey(loc->c_fileLocation()), _data->thumb); Local::writeImage(storageKey(loc->c_fileLocation()), _data->thumb);
} else if (size == 'm') { } else if (size == 'm') {
Local::writeImage(storageKey(loc->c_fileLocation()), _data->medium); Local::writeImage(storageKey(loc->c_fileLocation()), _data->medium);
} else if (size == 'x') { } else if (size == 'x' && max < 1) {
Local::writeImage(storageKey(loc->c_fileLocation()), _data->full); max = 1;
maxLocation = &loc->c_fileLocation();
} else if (size == 'y' && max < 2) {
max = 2;
maxLocation = &loc->c_fileLocation();
//} else if (size == 'w' && max < 3) {
// max = 3;
// maxLocation = &loc->c_fileLocation();
} }
} }
if (maxLocation) {
Local::writeImage(storageKey(*maxLocation), _data->full);
}
} }
} }
} }
@ -3508,7 +3530,7 @@ void HistoryVideo::initDimensions(const HistoryItem *parent) {
_thumbw = qMax(tw, 1); _thumbw = qMax(tw, 1);
int32 minWidth = qMax(st::minPhotoSize, parent->infoWidth() + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x())); int32 minWidth = qMax(st::minPhotoSize, parent->infoWidth() + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x()));
minWidth = qMax(minWidth, videoMaxStatusWidth(_data) + 2 * int32(st::msgDateImgDelta + st::msgDateImgPadding.x())); minWidth = qMax(minWidth, videoMaxStatusWidth(_data) + 2 * int32(st::msgDateImgDelta + st::msgDateImgPadding.x()));
_maxw = qMax(_thumbw, minWidth); _maxw = qMax(_thumbw, int16(minWidth));
_minh = qMax(th, int32(st::minPhotoSize)); _minh = qMax(th, int32(st::minPhotoSize));
if (bubble) { if (bubble) {
_maxw += st::mediaPadding.left() + st::mediaPadding.right(); _maxw += st::mediaPadding.left() + st::mediaPadding.right();
@ -3544,7 +3566,7 @@ int32 HistoryVideo::resize(int32 width, const HistoryItem *parent) {
int32 minWidth = qMax(st::minPhotoSize, parent->infoWidth() + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x())); int32 minWidth = qMax(st::minPhotoSize, parent->infoWidth() + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x()));
minWidth = qMax(minWidth, videoMaxStatusWidth(_data) + 2 * int32(st::msgDateImgDelta + st::msgDateImgPadding.x())); minWidth = qMax(minWidth, videoMaxStatusWidth(_data) + 2 * int32(st::msgDateImgDelta + st::msgDateImgPadding.x()));
_width = qMax(_thumbw, minWidth); _width = qMax(_thumbw, int16(minWidth));
_height = qMax(th, int32(st::minPhotoSize)); _height = qMax(th, int32(st::minPhotoSize));
if (bubble) { if (bubble) {
_width += st::mediaPadding.left() + st::mediaPadding.right(); _width += st::mediaPadding.left() + st::mediaPadding.right();
@ -3559,13 +3581,17 @@ int32 HistoryVideo::resize(int32 width, const HistoryItem *parent) {
void HistoryVideo::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { void HistoryVideo::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const {
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return;
_data->automaticLoad(parent);
bool loaded = _data->loaded(), displayLoading = _data->displayLoading();
int32 skipx = 0, skipy = 0, width = _width, height = _height; int32 skipx = 0, skipy = 0, width = _width, height = _height;
bool bubble = parent->hasBubble(); bool bubble = parent->hasBubble();
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel;
int32 captionw = width - st::msgPadding.left() - st::msgPadding.right(); int32 captionw = width - st::msgPadding.left() - st::msgPadding.right();
if (_data->loader) { if (displayLoading) {
ensureAnimation(parent); ensureAnimation(parent);
if (!_animation->radial.animating()) { if (!_animation->radial.animating()) {
_animation->radial.start(_data->progress()); _animation->radial.start(_data->progress());
@ -3586,7 +3612,6 @@ void HistoryVideo::draw(Painter &p, const HistoryItem *parent, const QRect &r, b
} else { } else {
App::roundShadow(p, 0, 0, width, height, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners); App::roundShadow(p, 0, 0, width, height, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners);
} }
_data->thumb->checkload();
QRect rthumb(rtlrect(skipx, skipy, width, height, _width)); QRect rthumb(rtlrect(skipx, skipy, width, height, _width));
@ -3606,7 +3631,7 @@ void HistoryVideo::draw(Painter &p, const HistoryItem *parent, const QRect &r, b
p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over)); p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over));
p.setBrush(st::black); p.setBrush(st::black);
} else { } else {
bool over = textlnkDrawOver(_data->loader ? _cancell : _savel); bool over = textlnkDrawOver(_data->loading() ? _cancell : _savel);
p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg); p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg);
} }
@ -3619,9 +3644,9 @@ void HistoryVideo::draw(Painter &p, const HistoryItem *parent, const QRect &r, b
} }
style::sprite icon; style::sprite icon;
if (!_data->already().isEmpty()) { if (loaded) {
icon = (selected ? st::msgFileInPlaySelected : st::msgFileInPlay); icon = (selected ? st::msgFileInPlaySelected : st::msgFileInPlay);
} else if (_data->loader) { } else if (radial || _data->loading()) {
icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel); icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
} else { } else {
icon = (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload); icon = (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload);
@ -3654,6 +3679,9 @@ void HistoryVideo::draw(Painter &p, const HistoryItem *parent, const QRect &r, b
void HistoryVideo::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const { void HistoryVideo::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const {
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return;
bool loaded = _data->loaded();
int32 skipx = 0, skipy = 0, width = _width, height = _height; int32 skipx = 0, skipy = 0, width = _width, height = _height;
bool bubble = parent->hasBubble(); bool bubble = parent->hasBubble();
@ -3674,7 +3702,7 @@ void HistoryVideo::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x
height -= skipy + st::mediaPadding.bottom(); height -= skipy + st::mediaPadding.bottom();
} }
if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height) { if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height) {
lnk = _data->already().isEmpty() ? (_data->loader ? _cancell : _savel) : _openl; lnk = loaded ? _openl : (_data->loading() ? _cancell : _savel);
if (_caption.isEmpty() && parent->getMedia() == this) { if (_caption.isEmpty() && parent->getMedia() == this) {
int32 fullRight = skipx + width, fullBottom = skipy + height; int32 fullRight = skipx + width, fullBottom = skipy + height;
bool inDate = parent->pointInTime(fullRight, fullBottom, x, y, InfoDisplayOverImage); bool inDate = parent->pointInTime(fullRight, fullBottom, x, y, InfoDisplayOverImage);
@ -3705,8 +3733,8 @@ void HistoryVideo::updateStatusText(const HistoryItem *parent) const {
statusSize = FileStatusSizeFailed; statusSize = FileStatusSizeFailed;
} else if (_data->status == FileUploading) { } else if (_data->status == FileUploading) {
statusSize = _data->uploadOffset; statusSize = _data->uploadOffset;
} else if (_data->loader) { } else if (_data->loading()) {
statusSize = _data->loader->currentOffset(); statusSize = _data->progress();
} else if (!_data->already().isEmpty()) { } else if (!_data->already().isEmpty()) {
statusSize = FileStatusSizeLoaded; statusSize = FileStatusSizeLoaded;
} else { } else {
@ -3754,8 +3782,6 @@ HistoryAudio::HistoryAudio(const HistoryAudio &other) : HistoryFileMedia()
} }
void HistoryAudio::initDimensions(const HistoryItem *parent) { void HistoryAudio::initDimensions(const HistoryItem *parent) {
_data->prepareAutoLoader(parent);
_maxw = st::msgFileMinWidth; _maxw = st::msgFileMinWidth;
int32 tleft = 0, tright = 0; int32 tleft = 0, tright = 0;
@ -3773,14 +3799,12 @@ void HistoryAudio::initDimensions(const HistoryItem *parent) {
void HistoryAudio::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { void HistoryAudio::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const {
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return;
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; _data->automaticLoad(parent);
bool loaded = _data->loaded(); bool loaded = _data->loaded(), displayLoading = _data->displayLoading();
if (!loaded && _data->status == FileReady && _data->loader && !_data->loadingStarted()) {
_data->openOnSave = 0;
_data->save(QString());
}
if (_data->loadingStarted() && !_data->loader->loadingLocal()) { bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel;
if (displayLoading) {
ensureAnimation(parent); ensureAnimation(parent);
if (!_animation->radial.animating()) { if (!_animation->radial.animating()) {
_animation->radial.start(_data->progress()); _animation->radial.start(_data->progress());
@ -3805,7 +3829,7 @@ void HistoryAudio::draw(Painter &p, const HistoryItem *parent, const QRect &r, b
float64 over = _animation->a_thumbOver.current(); float64 over = _animation->a_thumbOver.current();
p.setBrush(style::interpolate(outbg ? st::msgFileOutBg : st::msgFileInBg, outbg ? st::msgFileOutBgOver : st::msgFileInBgOver, over)); p.setBrush(style::interpolate(outbg ? st::msgFileOutBg : st::msgFileInBg, outbg ? st::msgFileOutBgOver : st::msgFileInBgOver, over));
} else { } else {
bool over = textlnkDrawOver(_data->loadingStarted() ? _cancell : _savel); bool over = textlnkDrawOver(_data->loading() ? _cancell : _savel);
p.setBrush(outbg ? (over ? st::msgFileOutBgOver : st::msgFileOutBg) : (over ? st::msgFileInBgOver : st::msgFileInBg)); p.setBrush(outbg ? (over ? st::msgFileOutBgOver : st::msgFileOutBg) : (over ? st::msgFileInBgOver : st::msgFileInBg));
} }
@ -3822,10 +3846,10 @@ void HistoryAudio::draw(Painter &p, const HistoryItem *parent, const QRect &r, b
style::sprite icon; style::sprite icon;
if (showPause) { if (showPause) {
icon = outbg ? (selected ? st::msgFileOutPauseSelected : st::msgFileOutPause) : (selected ? st::msgFileInPauseSelected : st::msgFileInPause); icon = outbg ? (selected ? st::msgFileOutPauseSelected : st::msgFileOutPause) : (selected ? st::msgFileInPauseSelected : st::msgFileInPause);
} else if (_statusSize < 0 || _statusSize == FileStatusSizeLoaded) { } else if (radial || _data->loading()) {
icon = outbg ? (selected ? st::msgFileOutPlaySelected : st::msgFileOutPlay) : (selected ? st::msgFileInPlaySelected : st::msgFileInPlay);
} else if (_data->loadingStarted()) {
icon = outbg ? (selected ? st::msgFileOutCancelSelected : st::msgFileOutCancel) : (selected ? st::msgFileInCancelSelected : st::msgFileInCancel); icon = outbg ? (selected ? st::msgFileOutCancelSelected : st::msgFileOutCancel) : (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
} else if (loaded) {
icon = outbg ? (selected ? st::msgFileOutPlaySelected : st::msgFileOutPlay) : (selected ? st::msgFileInPlaySelected : st::msgFileInPlay);
} else { } else {
icon = outbg ? (selected ? st::msgFileOutDownloadSelected : st::msgFileOutDownload) : (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload); icon = outbg ? (selected ? st::msgFileOutDownloadSelected : st::msgFileOutDownload) : (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload);
} }
@ -3866,12 +3890,12 @@ void HistoryAudio::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x
int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, linktop = 0; int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, linktop = 0;
QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, _width)); QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, _width));
if ((_data->loadingStarted() || _data->status == FileUploading || !loaded) && inner.contains(x, y)) { if ((_data->loading() || _data->status == FileUploading || !loaded) && inner.contains(x, y)) {
lnk = (_data->loadingStarted() || _data->status == FileUploading) ? _cancell : _savel; lnk = (_data->loading() || _data->status == FileUploading) ? _cancell : _savel;
return; return;
} }
if (x >= 0 && y >= 0 && x < _width && y < _height && !_data->loadingStarted() && _data->access) { if (x >= 0 && y >= 0 && x < _width && y < _height && _data->access && !_data->loading()) {
lnk = _openl; lnk = _openl;
return; return;
} }
@ -3896,8 +3920,8 @@ void HistoryAudio::unregItem(HistoryItem *item) {
void HistoryAudio::updateFrom(const MTPMessageMedia &media, HistoryItem *parent, bool allowEmitResize) { void HistoryAudio::updateFrom(const MTPMessageMedia &media, HistoryItem *parent, bool allowEmitResize) {
if (media.type() == mtpc_messageMediaAudio) { if (media.type() == mtpc_messageMediaAudio) {
App::feedAudio(media.c_messageMediaAudio().vaudio, _data); App::feedAudio(media.c_messageMediaAudio().vaudio, _data);
if (!_data->data.isEmpty()) { if (!_data->data().isEmpty()) {
Local::writeAudio(mediaKey(mtpToLocationType(mtpc_inputAudioFileLocation), _data->dc, _data->id), _data->data); Local::writeAudio(mediaKey(AudioFileLocation, _data->dc, _data->id), _data->data());
} }
} }
} }
@ -3913,8 +3937,8 @@ bool HistoryAudio::updateStatusText(const HistoryItem *parent) const {
statusSize = FileStatusSizeFailed; statusSize = FileStatusSizeFailed;
} else if (_data->status == FileUploading) { } else if (_data->status == FileUploading) {
statusSize = _data->uploadOffset; statusSize = _data->uploadOffset;
} else if (_data->loadingStarted()) { } else if (_data->loading()) {
statusSize = _data->loader->currentOffset(); statusSize = _data->loadOffset();
} else if (_data->loaded()) { } else if (_data->loaded()) {
AudioMsgId playing; AudioMsgId playing;
AudioPlayerState playingState = AudioPlayerStopped; AudioPlayerState playingState = AudioPlayerStopped;
@ -3976,8 +4000,6 @@ HistoryDocument::HistoryDocument(const HistoryDocument &other) : HistoryFileMedi
} }
void HistoryDocument::initDimensions(const HistoryItem *parent) { void HistoryDocument::initDimensions(const HistoryItem *parent) {
_data->prepareAutoLoader(parent);
_maxw = st::msgFileMinWidth; _maxw = st::msgFileMinWidth;
int32 tleft = 0, tright = 0; int32 tleft = 0, tright = 0;
@ -4006,10 +4028,12 @@ void HistoryDocument::initDimensions(const HistoryItem *parent) {
void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const {
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return;
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel; _data->automaticLoad(parent);
bool loaded = _data->loaded(); bool loaded = _data->loaded(), displayLoading = _data->displayLoading();
if (_data->loadingStarted()) { bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel;
if (displayLoading) {
ensureAnimation(parent); ensureAnimation(parent);
if (!_animation->radial.animating()) { if (!_animation->radial.animating()) {
_animation->radial.start(_data->progress()); _animation->radial.start(_data->progress());
@ -4038,35 +4062,35 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners); App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners);
} }
if (radial || !loaded) { if (radial || (!loaded && !_data->loading())) {
float64 radialOpacity = (radial && loaded) ? _animation->radial.opacity() : 1;
QRect inner(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize); QRect inner(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
if (selected) { if (selected) {
p.setBrush(st::msgDateImgBgSelected); p.setBrush(st::msgDateImgBgSelected);
} else if (radial && loaded) {
p.setOpacity(st::msgDateImgBg->c.alphaF() * _animation->radial.opacity());
p.setBrush(st::black);
} else if (_animation && _animation->_a_thumbOver.animating()) { } else if (_animation && _animation->_a_thumbOver.animating()) {
_animation->_a_thumbOver.step(ms); _animation->_a_thumbOver.step(ms);
float64 over = _animation->a_thumbOver.current(); float64 over = _animation->a_thumbOver.current();
p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over)); p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over));
p.setBrush(st::black); p.setBrush(st::black);
} else { } else {
bool over = textlnkDrawOver(_data->loadingStarted() ? _cancell : _savel); bool over = textlnkDrawOver(_data->loading() ? _cancell : _savel);
p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg); p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg);
} }
p.setOpacity(radialOpacity * p.opacity());
p.setRenderHint(QPainter::HighQualityAntialiasing); p.setRenderHint(QPainter::HighQualityAntialiasing);
p.drawEllipse(inner); p.drawEllipse(inner);
p.setRenderHint(QPainter::HighQualityAntialiasing, false); p.setRenderHint(QPainter::HighQualityAntialiasing, false);
p.setOpacity(radialOpacity);
style::sprite icon; style::sprite icon;
if (loaded || _data->loadingStarted()) { if (radial || _data->loading()) {
icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel); icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
} else { } else {
icon = (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload); icon = (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload);
} }
p.setOpacity(radial ? _animation->radial.opacity() : 1); p.setOpacity((radial && loaded) ? _animation->radial.opacity() : 1);
p.drawSpriteCenter(inner, icon); p.drawSpriteCenter(inner, icon);
if (radial) { if (radial) {
p.setOpacity(1); p.setOpacity(1);
@ -4077,7 +4101,7 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r
} }
if (_data->status != FileUploadFailed) { if (_data->status != FileUploadFailed) {
const TextLinkPtr &lnk((_data->loadingStarted() || _data->status == FileUploading) ? _linkcancell : _linksavel); const TextLinkPtr &lnk((_data->loading() || _data->status == FileUploading) ? _linkcancell : _linksavel);
bool over = textlnkDrawOver(lnk); bool over = textlnkDrawOver(lnk);
p.setFont(over ? st::semiboldFont->underline() : st::semiboldFont); p.setFont(over ? st::semiboldFont->underline() : st::semiboldFont);
p.setPen(outbg ? (selected ? st::msgFileThumbLinkOutFgSelected : st::msgFileThumbLinkOutFg) : (selected ? st::msgFileThumbLinkInFgSelected : st::msgFileThumbLinkInFg)); p.setPen(outbg ? (selected ? st::msgFileThumbLinkOutFgSelected : st::msgFileThumbLinkOutFg) : (selected ? st::msgFileThumbLinkInFgSelected : st::msgFileThumbLinkInFg));
@ -4097,7 +4121,7 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r
float64 over = _animation->a_thumbOver.current(); float64 over = _animation->a_thumbOver.current();
p.setBrush(style::interpolate(outbg ? st::msgFileOutBg : st::msgFileInBg, outbg ? st::msgFileOutBgOver : st::msgFileInBgOver, over)); p.setBrush(style::interpolate(outbg ? st::msgFileOutBg : st::msgFileInBg, outbg ? st::msgFileOutBgOver : st::msgFileInBgOver, over));
} else { } else {
bool over = textlnkDrawOver(_data->loadingStarted() ? _cancell : _savel); bool over = textlnkDrawOver(_data->loading() ? _cancell : _savel);
p.setBrush(outbg ? (over ? st::msgFileOutBgOver : st::msgFileOutBg) : (over ? st::msgFileInBgOver : st::msgFileInBg)); p.setBrush(outbg ? (over ? st::msgFileOutBgOver : st::msgFileOutBg) : (over ? st::msgFileInBgOver : st::msgFileInBg));
} }
@ -4114,7 +4138,9 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r
style::sprite icon; style::sprite icon;
if (showPause) { if (showPause) {
icon = outbg ? (selected ? st::msgFileOutPauseSelected : st::msgFileOutPause) : (selected ? st::msgFileInPauseSelected : st::msgFileInPause); icon = outbg ? (selected ? st::msgFileOutPauseSelected : st::msgFileOutPause) : (selected ? st::msgFileInPauseSelected : st::msgFileInPause);
} else if (_statusSize < 0 || _statusSize == FileStatusSizeLoaded) { } else if (radial || _data->loading()) {
icon = outbg ? (selected ? st::msgFileOutCancelSelected : st::msgFileOutCancel) : (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
} else if (loaded) {
if (_data->song()) { if (_data->song()) {
icon = outbg ? (selected ? st::msgFileOutPlaySelected : st::msgFileOutPlay) : (selected ? st::msgFileInPlaySelected : st::msgFileInPlay); icon = outbg ? (selected ? st::msgFileOutPlaySelected : st::msgFileOutPlay) : (selected ? st::msgFileInPlaySelected : st::msgFileInPlay);
} else if (_data->isImage()) { } else if (_data->isImage()) {
@ -4122,8 +4148,6 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r
} else { } else {
icon = outbg ? (selected ? st::msgFileOutFileSelected : st::msgFileOutFile) : (selected ? st::msgFileInFileSelected : st::msgFileInFile); icon = outbg ? (selected ? st::msgFileOutFileSelected : st::msgFileOutFile) : (selected ? st::msgFileInFileSelected : st::msgFileInFile);
} }
} else if (_data->loadingStarted()) {
icon = outbg ? (selected ? st::msgFileOutCancelSelected : st::msgFileOutCancel) : (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
} else { } else {
icon = outbg ? (selected ? st::msgFileOutDownloadSelected : st::msgFileOutDownload) : (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload); icon = outbg ? (selected ? st::msgFileOutDownloadSelected : st::msgFileOutDownload) : (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload);
} }
@ -4161,28 +4185,25 @@ void HistoryDocument::getState(TextLinkPtr &lnk, HistoryCursorState &state, int3
QRect rthumb(rtlrect(st::msgFileThumbPadding.left(), st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, _width)); QRect rthumb(rtlrect(st::msgFileThumbPadding.left(), st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, _width));
if (loaded) { if ((_data->loading() || _data->uploading() || !loaded) && rthumb.contains(x, y)) {
} else { lnk = (_data->loading() || _data->uploading()) ? _cancell : _savel;
if (rthumb.contains(x, y)) { return;
lnk = (_data->loadingStarted() || _data->status == FileUploading) ? _cancell : _savel;
return;
}
} }
if (_data->status != FileUploadFailed) { if (_data->status != FileUploadFailed) {
if (rtlrect(nameleft, linktop, _linkw, st::semiboldFont->height, _width).contains(x, y)) { if (rtlrect(nameleft, linktop, _linkw, st::semiboldFont->height, _width).contains(x, y)) {
lnk = (_data->loadingStarted() || _data->status == FileUploading) ? _linkcancell : _linksavel; lnk = (_data->loading() || _data->uploading()) ? _linkcancell : _linksavel;
return; return;
} }
} }
} else { } else {
QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, _width)); QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, _width));
if ((_data->loadingStarted() || _data->status == FileUploading || !loaded) && inner.contains(x, y)) { if ((_data->loading() || _data->uploading() || !loaded) && inner.contains(x, y)) {
lnk = (_data->loadingStarted() || _data->status == FileUploading) ? _cancell : _savel; lnk = (_data->loading() || _data->uploading()) ? _cancell : _savel;
return; return;
} }
} }
if (x >= 0 && y >= 0 && x < _width && y < _height && !_data->loadingStarted() && _data->access) { if (x >= 0 && y >= 0 && x < _width && y < _height && !_data->loading() && !_data->uploading() && _data->access) {
lnk = _openl; lnk = _openl;
return; return;
} }
@ -4220,8 +4241,8 @@ bool HistoryDocument::updateStatusText(const HistoryItem *parent) const {
statusSize = FileStatusSizeFailed; statusSize = FileStatusSizeFailed;
} else if (_data->status == FileUploading) { } else if (_data->status == FileUploading) {
statusSize = _data->uploadOffset; statusSize = _data->uploadOffset;
} else if (_data->loadingStarted()) { } else if (_data->loading()) {
statusSize = _data->loader->currentOffset(); statusSize = _data->loadOffset();
} else if (_data->loaded()) { } else if (_data->loaded()) {
if (_data->song()) { if (_data->song()) {
SongMsgId playing; SongMsgId playing;
@ -4277,7 +4298,7 @@ HistoryGif::HistoryGif(DocumentData *document) : HistoryFileMedia()
, _thumbw(1) , _thumbw(1)
, _thumbh(1) , _thumbh(1)
, _gif(0) { , _gif(0) {
setLinks(new GifOpenLink(_data), new GifOpenLink(_data), new DocumentCancelLink(_data)); setLinks(new DocumentOpenLink(_data), new GifOpenLink(_data), new DocumentCancelLink(_data));
setStatusSize(FileStatusSizeReady); setStatusSize(FileStatusSizeReady);
@ -4289,14 +4310,12 @@ HistoryGif::HistoryGif(const HistoryGif &other) : HistoryFileMedia()
, _thumbw(other._thumbw) , _thumbw(other._thumbw)
, _thumbh(other._thumbh) , _thumbh(other._thumbh)
, _gif(0) { , _gif(0) {
setLinks(new GifOpenLink(_data), new GifOpenLink(_data), new DocumentCancelLink(_data)); setLinks(new DocumentOpenLink(_data), new GifOpenLink(_data), new DocumentCancelLink(_data));
setStatusSize(other._statusSize); setStatusSize(other._statusSize);
} }
void HistoryGif::initDimensions(const HistoryItem *parent) { void HistoryGif::initDimensions(const HistoryItem *parent) {
_data->prepareAutoLoader(parent);
bool bubble = parent->hasBubble(); bool bubble = parent->hasBubble();
int32 tw = 0, th = 0; int32 tw = 0, th = 0;
if (_gif && _gif->state() == ClipError) { if (_gif && _gif->state() == ClipError) {
@ -4397,23 +4416,21 @@ int32 HistoryGif::resize(int32 width, const HistoryItem *parent) {
void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const {
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return;
int32 skipx = 0, skipy = 0, width = _width, height = _height;
bool bubble = parent->hasBubble();
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel;
bool loaded = _data->loaded(_gif ? false : true); _data->automaticLoad(parent);
if (!loaded && _data->status == FileReady && _data->loader && !_data->loadingStarted()) { bool loaded = _data->loaded(), displayLoading = _data->displayLoading();
_data->openOnSave = 0;
_data->save(QString());
}
if (loaded && !_gif) { if (loaded && !_gif) {
const_cast<HistoryGif*>(this)->playInline(const_cast<HistoryItem*>(parent)); const_cast<HistoryGif*>(this)->playInline(const_cast<HistoryItem*>(parent));
} }
int32 skipx = 0, skipy = 0, width = _width, height = _height;
bool bubble = parent->hasBubble();
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel;
bool animating = (_gif && _gif->started()); bool animating = (_gif && _gif->started());
if (!animating) { if (!animating || _data->uploading()) {
if (_data->loadingStarted() && !_data->loader->loadingLocal()) { if (displayLoading) {
ensureAnimation(parent); ensureAnimation(parent);
if (!_animation->radial.animating()) { if (!_animation->radial.animating()) {
_animation->radial.start(_data->progress()); _animation->radial.start(_data->progress());
@ -4432,7 +4449,6 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, boo
} else { } else {
App::roundShadow(p, 0, 0, width, _height, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners); App::roundShadow(p, 0, 0, width, _height, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners);
} }
_data->thumb->checkload();
QRect rthumb(rtlrect(skipx, skipy, width, height, _width)); QRect rthumb(rtlrect(skipx, skipy, width, height, _width));
@ -4445,7 +4461,8 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, boo
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners); App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners);
} }
if (radial || (!animating && !_gif && (!_data->loader || !_data->loader->loadingLocal() || _data->size > AnimationInMemory))) { if (radial || (!_gif && !loaded && !_data->loading())) {
float64 radialOpacity = radial ? _animation->radial.opacity() : 1;
QRect inner(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize); QRect inner(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
if (selected) { if (selected) {
@ -4456,33 +4473,32 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, boo
p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over)); p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over));
p.setBrush(st::black); p.setBrush(st::black);
} else { } else {
bool over = textlnkDrawOver(_data->loadingStarted() ? _cancell : _savel); bool over = textlnkDrawOver(_data->loading() ? _cancell : _savel);
p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg); p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg);
} }
p.setOpacity(radialOpacity * p.opacity());
p.setRenderHint(QPainter::HighQualityAntialiasing); p.setRenderHint(QPainter::HighQualityAntialiasing);
p.drawEllipse(inner); p.drawEllipse(inner);
p.setRenderHint(QPainter::HighQualityAntialiasing, false); p.setRenderHint(QPainter::HighQualityAntialiasing, false);
if (!selected && _animation) { p.setOpacity(radialOpacity);
p.setOpacity(1);
}
style::sprite icon; style::sprite icon;
if (_data->loaded() && !radial) { if (_data->loaded() && !radial) {
icon = (selected ? st::msgFileInPlaySelected : st::msgFileInPlay); icon = (selected ? st::msgFileInPlaySelected : st::msgFileInPlay);
} else if (_data->loadingStarted() || radial) { } else if (radial || _data->loading()) {
icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel); icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
} else { } else {
icon = (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload); icon = (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload);
} }
p.drawSpriteCenter(inner, icon); p.drawSpriteCenter(inner, icon);
if (radial) { if (radial) {
p.setOpacity(1);
QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine))); QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine)));
_animation->radial.draw(p, rinner, st::msgFileRadialLine, selected ? st::msgInBgSelected : st::msgInBg); _animation->radial.draw(p, rinner, st::msgFileRadialLine, selected ? st::msgInBgSelected : st::msgInBg);
} }
if (!animating) { if (!animating || _data->uploading()) {
int32 statusX = skipx + st::msgDateImgDelta + st::msgDateImgPadding.x(), statusY = skipy + st::msgDateImgDelta + st::msgDateImgPadding.y(); int32 statusX = skipx + st::msgDateImgDelta + st::msgDateImgPadding.x(), statusY = skipy + st::msgDateImgDelta + st::msgDateImgPadding.y();
int32 statusW = st::normalFont->width(_statusText) + 2 * st::msgDateImgPadding.x(); int32 statusW = st::normalFont->width(_statusText) + 2 * st::msgDateImgPadding.x();
int32 statusH = st::normalFont->height + 2 * st::msgDateImgPadding.y(); int32 statusH = st::normalFont->height + 2 * st::msgDateImgPadding.y();
@ -4512,11 +4528,11 @@ void HistoryGif::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x,
height -= skipy + st::mediaPadding.bottom(); height -= skipy + st::mediaPadding.bottom();
} }
if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height) { if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height) {
if (_gif && _gif->started()) { if (_data->uploading()) {
} else { lnk = _cancell;
lnk = _data->loaded() ? _savel : (_data->loadingStarted() ? _cancell : _savel); } else if (!_gif) {
lnk = _data->loaded() ? _openl : (_data->loading() ? _cancell : _savel);
} }
if (parent->getMedia() == this) { if (parent->getMedia() == this) {
int32 fullRight = skipx + width, fullBottom = skipy + height; int32 fullRight = skipx + width, fullBottom = skipy + height;
bool inDate = parent->pointInTime(fullRight, fullBottom, x, y, InfoDisplayOverImage); bool inDate = parent->pointInTime(fullRight, fullBottom, x, y, InfoDisplayOverImage);
@ -4547,8 +4563,8 @@ void HistoryGif::updateStatusText(const HistoryItem *parent) const {
statusSize = FileStatusSizeFailed; statusSize = FileStatusSizeFailed;
} else if (_data->status == FileUploading) { } else if (_data->status == FileUploading) {
statusSize = _data->uploadOffset; statusSize = _data->uploadOffset;
} else if (_data->loadingStarted()) { } else if (_data->loading()) {
statusSize = _data->loader->currentOffset(); statusSize = _data->loadOffset();
} else if (_data->loaded()) { } else if (_data->loaded()) {
statusSize = FileStatusSizeLoaded; statusSize = FileStatusSizeLoaded;
} else { } else {
@ -4581,7 +4597,7 @@ bool HistoryGif::playInline(HistoryItem *parent) {
if (_gif) { if (_gif) {
stopInline(parent); stopInline(parent);
} else { } else {
_gif = new ClipReader(_data->location(), _data->data); _gif = new ClipReader(_data->location(), _data->data());
App::regGifItem(_gif, parent); App::regGifItem(_gif, parent);
} }
return true; return true;
@ -4620,8 +4636,6 @@ HistorySticker::HistorySticker(DocumentData *document) : HistoryMedia()
} }
void HistorySticker::initDimensions(const HistoryItem *parent) { void HistorySticker::initDimensions(const HistoryItem *parent) {
_data->prepareAutoLoader(parent);
_pixw = _data->dimensions.width(); _pixw = _data->dimensions.width();
_pixh = _data->dimensions.height(); _pixh = _data->dimensions.height();
if (_pixw > st::maxStickerSize) { if (_pixw > st::maxStickerSize) {
@ -4645,12 +4659,10 @@ void HistorySticker::initDimensions(const HistoryItem *parent) {
void HistorySticker::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { void HistorySticker::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const {
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return;
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel, hovered, pressed; _data->checkSticker();
bool loaded = _data->loaded(); bool loaded = _data->loaded();
if (!loaded && _data->status == FileReady && _data->loader && !_data->loader->started()) {
_data->openOnSave = 0; bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel, hovered, pressed;
_data->save(QString());
}
int32 usew = _maxw, usex = 0; int32 usew = _maxw, usex = 0;
const HistoryReply *reply = toHistoryReply(parent); const HistoryReply *reply = toHistoryReply(parent);
@ -4663,13 +4675,6 @@ void HistorySticker::draw(Painter &p, const HistoryItem *parent, const QRect &r,
} }
if (rtl()) usex = _width - usex - usew; if (rtl()) usex = _width - usex - usew;
if (_data->sticker()->img->isNull() && loaded) {
if (_data->data.isEmpty()) {
_data->sticker()->img = ImagePtr(_data->already());
} else {
_data->sticker()->img = ImagePtr(_data->data);
}
}
if (selected) { if (selected) {
if (_data->sticker()->img->isNull()) { if (_data->sticker()->img->isNull()) {
p.drawPixmap(QPoint(usex + (usew - _pixw) / 2, (_minh - _pixh) / 2), _data->thumb->pixBlurredColored(st::msgStickerOverlay, _pixw, _pixh)); p.drawPixmap(QPoint(usex + (usew - _pixw) / 2, (_minh - _pixh) / 2), _data->thumb->pixBlurredColored(st::msgStickerOverlay, _pixw, _pixh));
@ -4750,8 +4755,8 @@ void HistorySticker::unregItem(HistoryItem *item) {
void HistorySticker::updateFrom(const MTPMessageMedia &media, HistoryItem *parent, bool allowEmitResize) { void HistorySticker::updateFrom(const MTPMessageMedia &media, HistoryItem *parent, bool allowEmitResize) {
if (media.type() == mtpc_messageMediaDocument) { if (media.type() == mtpc_messageMediaDocument) {
App::feedDocument(media.c_messageMediaDocument().vdocument, _data); App::feedDocument(media.c_messageMediaDocument().vdocument, _data);
if (!_data->data.isEmpty()) { if (!_data->data().isEmpty()) {
Local::writeStickerImage(mediaKey(mtpToLocationType(mtpc_inputDocumentFileLocation), _data->dc, _data->id), _data->data); Local::writeStickerImage(mediaKey(DocumentFileLocation, _data->dc, _data->id), _data->data());
} }
} }
} }
@ -5346,7 +5351,7 @@ void HistoryWebPage::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32
int32 attachLeft = lshift - bubble.left(), attachTop = tshift - bubble.top(); int32 attachLeft = lshift - bubble.left(), attachTop = tshift - bubble.top();
if (rtl()) attachLeft = _width - attachLeft - _attach->currentWidth(); if (rtl()) attachLeft = _width - attachLeft - _attach->currentWidth();
_attach->getState(lnk, state, x - attachLeft, y - attachTop, parent); _attach->getState(lnk, state, x - attachLeft, y - attachTop, parent);
if (lnk && _data->photo) { if (lnk && !_data->doc && _data->photo) {
if (_data->type == WebPageProfile || _data->type == WebPageVideo) { if (_data->type == WebPageProfile || _data->type == WebPageVideo) {
lnk = _openl; lnk = _openl;
} else if (_data->type == WebPagePhoto || _data->siteName == qstr("Twitter") || _data->siteName == qstr("Facebook")) { } else if (_data->type == WebPagePhoto || _data->siteName == qstr("Twitter") || _data->siteName == qstr("Facebook")) {
@ -6036,10 +6041,6 @@ void HistoryMessage::fromNameUpdated() const {
} }
} }
bool HistoryMessage::uploading() const {
return _media ? _media->uploading() : false;
}
QString HistoryMessage::selectedText(uint32 selection) const { QString HistoryMessage::selectedText(uint32 selection) const {
if (_media && selection == FullSelection) { if (_media && selection == FullSelection) {
QString text = _text.original(0, 0xFFFF, Text::ExpandLinksAll), mediaText = _media->inHistoryText(); QString text = _text.original(0, 0xFFFF, Text::ExpandLinksAll), mediaText = _media->inHistoryText();

View File

@ -768,23 +768,6 @@ protected:
}; };
class ItemAnimations {
public:
ItemAnimations() : _a_animate(animation(this, &ItemAnimations::step_animate)) {
}
void step_animate(float64 ms, bool timer);
uint64 animate(const HistoryItem *item, uint64 ms);
void remove(const HistoryItem *item);
private:
typedef QMap<const HistoryItem*, uint64> Animations;
Animations _animations;
Animation _a_animate;
};
ItemAnimations &itemAnimations();
class HistoryReply; // dynamic_cast optimize class HistoryReply; // dynamic_cast optimize
class HistoryMessage; // dynamic_cast optimize class HistoryMessage; // dynamic_cast optimize
class HistoryForwarded; // dynamic_cast optimize class HistoryForwarded; // dynamic_cast optimize
@ -1014,10 +997,6 @@ public:
return textcmdSkipBlock(skipBlockWidth(), skipBlockHeight()); return textcmdSkipBlock(skipBlockWidth(), skipBlockHeight());
} }
virtual bool animating() const {
return false;
}
virtual HistoryMessage *toHistoryMessage() { // dynamic_cast optimize virtual HistoryMessage *toHistoryMessage() { // dynamic_cast optimize
return 0; return 0;
} }
@ -1218,70 +1197,6 @@ protected:
}; };
class HistoryPhoto : public HistoryMedia {
public:
HistoryPhoto(const MTPDphoto &photo, const QString &caption, HistoryItem *parent);
HistoryPhoto(PhotoData *photo);
HistoryPhoto(PeerData *chat, const MTPDphoto &photo, int32 width = 0);
void init();
HistoryMediaType type() const {
return MediaTypePhoto;
}
HistoryMedia *clone() const {
return new HistoryPhoto(*this);
}
void initDimensions(const HistoryItem *parent);
int32 resize(int32 width, const HistoryItem *parent);
void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const;
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const;
const QString inDialogsText() const;
const QString inHistoryText() const;
PhotoData *photo() const {
return _data;
}
void updateFrom(const MTPMessageMedia &media, HistoryItem *parent, bool allowEmitResize);
virtual bool animating() const {
if (_data->full->loaded()) return false;
return _data->full->loading() ? true : !_data->medium->loaded();
}
bool hasReplyPreview() const {
return !_data->thumb->isNull();
}
ImagePtr replyPreview();
QString getCaption() const {
return _caption.original();
}
bool needsBubble(const HistoryItem *parent) const {
return !_caption.isEmpty() || parent->toHistoryReply();
}
bool customInfoLayout() const {
return _caption.isEmpty();
}
bool hideFromName() const {
return true;
}
bool hideForwardedFrom() const {
return true;
}
private:
PhotoData *_data;
TextLinkPtr _openl;
int16 _pixw, _pixh;
Text _caption;
};
class HistoryFileMedia : public HistoryMedia { class HistoryFileMedia : public HistoryMedia {
public: public:
@ -1343,6 +1258,76 @@ private:
}; };
class HistoryPhoto : public HistoryFileMedia {
public:
HistoryPhoto(const MTPDphoto &photo, const QString &caption, HistoryItem *parent);
HistoryPhoto(PhotoData *photo);
HistoryPhoto(PeerData *chat, const MTPDphoto &photo, int32 width = 0);
HistoryPhoto(const HistoryPhoto &other);
void init();
HistoryMediaType type() const {
return MediaTypePhoto;
}
HistoryMedia *clone() const {
return new HistoryPhoto(*this);
}
void initDimensions(const HistoryItem *parent);
int32 resize(int32 width, const HistoryItem *parent);
void draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const;
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const;
const QString inDialogsText() const;
const QString inHistoryText() const;
PhotoData *photo() const {
return _data;
}
void updateFrom(const MTPMessageMedia &media, HistoryItem *parent, bool allowEmitResize);
bool hasReplyPreview() const {
return !_data->thumb->isNull();
}
ImagePtr replyPreview();
QString getCaption() const {
return _caption.original();
}
bool needsBubble(const HistoryItem *parent) const {
return !_caption.isEmpty() || parent->toHistoryReply();
}
bool customInfoLayout() const {
return _caption.isEmpty();
}
bool hideFromName() const {
return true;
}
bool hideForwardedFrom() const {
return true;
}
protected:
float64 dataProgress() const {
return _data->progress();
}
bool dataFinished() const {
return !_data->loading() && !_data->uploading();
}
bool dataLoaded() const {
return _data->loaded();
}
private:
PhotoData *_data;
int16 _pixw, _pixh;
Text _caption;
};
class HistoryVideo : public HistoryFileMedia { class HistoryVideo : public HistoryFileMedia {
public: public:
@ -1369,7 +1354,7 @@ public:
} }
bool uploading() const { bool uploading() const {
return (_data->status == FileUploading); return _data->uploading();
} }
void regItem(HistoryItem *item); void regItem(HistoryItem *item);
@ -1399,16 +1384,16 @@ protected:
return _data->progress(); return _data->progress();
} }
bool dataFinished() const { bool dataFinished() const {
return !_data->loader; return !_data->loading() && !_data->uploading();
} }
bool dataLoaded() const { bool dataLoaded() const {
return !_data->already().isEmpty(); return _data->loaded();
} }
private: private:
VideoData *_data; VideoData *_data;
int16 _thumbw;
Text _caption; Text _caption;
int32 _thumbw;
void setStatusSize(int32 newSize) const; void setStatusSize(int32 newSize) const;
void updateStatusText(const HistoryItem *parent) const; void updateStatusText(const HistoryItem *parent) const;
@ -1436,7 +1421,7 @@ public:
const QString inHistoryText() const; const QString inHistoryText() const;
bool uploading() const { bool uploading() const {
return (_data->status == FileUploading); return _data->uploading();
} }
AudioData *audio() { AudioData *audio() {
@ -1464,7 +1449,7 @@ protected:
return _data->progress(); return _data->progress();
} }
bool dataFinished() const { bool dataFinished() const {
return !_data->loader; return !_data->loading() && !_data->uploading();
} }
bool dataLoaded() const { bool dataLoaded() const {
return _data->loaded(); return _data->loaded();
@ -1499,7 +1484,7 @@ public:
const QString inHistoryText() const; const QString inHistoryText() const;
bool uploading() const { bool uploading() const {
return (_data->status == FileUploading); return _data->uploading();
} }
bool withThumb() const { bool withThumb() const {
@ -1539,7 +1524,7 @@ protected:
return _data->progress(); return _data->progress();
} }
bool dataFinished() const { bool dataFinished() const {
return !_data->loader; return !_data->loading() && !_data->uploading();
} }
bool dataLoaded() const { bool dataLoaded() const {
return _data->loaded(); return _data->loaded();
@ -1584,7 +1569,7 @@ public:
const QString inHistoryText() const; const QString inHistoryText() const;
bool uploading() const { bool uploading() const {
return (_data->status == FileUploading); return _data->uploading();
} }
DocumentData *getDocument() { DocumentData *getDocument() {
@ -1625,7 +1610,7 @@ protected:
return _data->progress(); return _data->progress();
} }
bool dataFinished() const { bool dataFinished() const {
return !_data->loader; return !_data->loading() && !_data->uploading();
} }
bool dataLoaded() const { bool dataLoaded() const {
return _data->loaded(); return _data->loaded();
@ -1807,10 +1792,6 @@ public:
} }
ImagePtr replyPreview(); ImagePtr replyPreview();
virtual bool animating() const {
return _attach ? _attach->animating() : false;
}
WebPageData *webpage() { WebPageData *webpage() {
return _data; return _data;
} }
@ -1956,7 +1937,9 @@ public:
bool displayFromName() const { bool displayFromName() const {
return hasFromName() && (!emptyText() || !_media || !_media->isDisplayed() || toHistoryReply() || !_media->hideFromName()); return hasFromName() && (!emptyText() || !_media || !_media->isDisplayed() || toHistoryReply() || !_media->hideFromName());
} }
bool uploading() const; bool uploading() const {
return _media && _media->uploading();
}
void drawInfo(Painter &p, int32 right, int32 bottom, int32 width, bool selected, InfoDisplayType type) const; void drawInfo(Painter &p, int32 right, int32 bottom, int32 width, bool selected, InfoDisplayType type) const;
void setViewsCount(int32 count); void setViewsCount(int32 count);
@ -2034,9 +2017,6 @@ public:
int32 viewsWidth() const { int32 viewsWidth() const {
return _viewsWidth; return _viewsWidth;
} }
virtual bool animating() const {
return _media ? _media->animating() : false;
}
virtual QDateTime dateForwarded() const { // dynamic_cast optimize virtual QDateTime dateForwarded() const { // dynamic_cast optimize
return date; return date;
@ -2201,10 +2181,6 @@ public:
HistoryMedia *getMedia(bool inOverview = false) const; HistoryMedia *getMedia(bool inOverview = false) const;
virtual bool animating() const {
return _media ? _media->animating() : false;
}
void setServiceText(const QString &text); void setServiceText(const QString &text);
~HistoryServiceMsg(); ~HistoryServiceMsg();

View File

@ -880,7 +880,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
_menu->addAction(lang(lng_context_save_image), this, SLOT(saveContextImage()))->setEnabled(true); _menu->addAction(lang(lng_context_save_image), this, SLOT(saveContextImage()))->setEnabled(true);
_menu->addAction(lang(lng_context_copy_image), this, SLOT(copyContextImage()))->setEnabled(true); _menu->addAction(lang(lng_context_copy_image), this, SLOT(copyContextImage()))->setEnabled(true);
} else { } else {
if ((lnkVideo && lnkVideo->video()->loader) || (lnkAudio && lnkAudio->audio()->loadingStarted()) || (lnkDocument && lnkDocument->document()->loadingStarted())) { if ((lnkVideo && lnkVideo->video()->loading()) || (lnkAudio && lnkAudio->audio()->loading()) || (lnkDocument && lnkDocument->document()->loading())) {
_menu->addAction(lang(lng_context_cancel_download), this, SLOT(cancelContextDownload()))->setEnabled(true); _menu->addAction(lang(lng_context_cancel_download), this, SLOT(cancelContextDownload()))->setEnabled(true);
} else { } else {
if ((lnkVideo && !lnkVideo->video()->already(true).isEmpty()) || (lnkAudio && !lnkAudio->audio()->already(true).isEmpty()) || (lnkDocument && !lnkDocument->document()->already(true).isEmpty())) { if ((lnkVideo && !lnkVideo->video()->already(true).isEmpty()) || (lnkAudio && !lnkAudio->audio()->already(true).isEmpty()) || (lnkDocument && !lnkDocument->document()->already(true).isEmpty())) {
@ -1050,8 +1050,13 @@ void HistoryInner::cancelContextDownload() {
VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data()); VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data());
AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_contextMenuLnk.data()); AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_contextMenuLnk.data());
DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data()); DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data());
mtpFileLoader *loader = lnkVideo ? lnkVideo->video()->loader : (lnkAudio ? lnkAudio->audio()->loader : (lnkDocument ? lnkDocument->document()->loader : 0)); if (lnkVideo) {
if (loader) loader->cancel(); lnkVideo->video()->cancel();
} else if (lnkAudio) {
lnkAudio->audio()->cancel();
} else if (lnkDocument) {
lnkDocument->document()->cancel();
}
} }
void HistoryInner::showContextInFolder() { void HistoryInner::showContextInFolder() {
@ -5436,7 +5441,7 @@ void HistoryWidget::onPhotoProgress(const FullMsgId &newId) {
if (!item->fromChannel()) { if (!item->fromChannel()) {
updateSendAction(item->history(), SendActionUploadPhoto, 0); updateSendAction(item->history(), SendActionUploadPhoto, 0);
} }
// Ui::redrawHistoryItem(item); Ui::redrawHistoryItem(item);
} }
} }

View File

@ -273,18 +273,7 @@ QSize StickerPreviewWidget::currentDimensions() const {
QPixmap StickerPreviewWidget::currentImage() const { QPixmap StickerPreviewWidget::currentImage() const {
if (_doc && _cacheStatus != CacheLoaded) { if (_doc && _cacheStatus != CacheLoaded) {
bool already = !_doc->already().isEmpty(), hasdata = !_doc->data.isEmpty(); _doc->checkSticker();
if (!already && !hasdata && !_doc->loader && _doc->status == FileReady) {
_doc->openOnSave = 0;
_doc->save(QString());
}
if (_doc->sticker()->img->isNull() && (already || hasdata)) {
if (already) {
_doc->sticker()->img = ImagePtr(_doc->already());
} else {
_doc->sticker()->img = ImagePtr(_doc->data);
}
}
if (_doc->sticker()->img->isNull()) { if (_doc->sticker()->img->isNull()) {
if (_cacheStatus != CacheThumbLoaded) { if (_cacheStatus != CacheThumbLoaded) {
QSize s = currentDimensions(); QSize s = currentDimensions();

View File

@ -392,8 +392,10 @@ int32 LayoutOverviewVideo::resizeGetHeight(int32 width) {
void LayoutOverviewVideo::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const { void LayoutOverviewVideo::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
bool selected = (selection == FullSelection), thumbLoaded = _data->thumb->loaded(); bool selected = (selection == FullSelection), thumbLoaded = _data->thumb->loaded();
bool already = !_data->already().isEmpty();
if (_data->loader) { _data->automaticLoad(_parent);
bool loaded = _data->loaded(), displayLoading = _data->displayLoading();
if (displayLoading) {
ensureRadial(); ensureRadial();
if (!_radial->animating()) { if (!_radial->animating()) {
_radial->start(_data->progress()); _radial->start(_data->progress());
@ -437,7 +439,7 @@ void LayoutOverviewVideo::paint(Painter &p, const QRect &clip, uint32 selection,
p.fillRect(QRect(0, 0, _width, _height), st::overviewPhotoSelectOverlay); p.fillRect(QRect(0, 0, _width, _height), st::overviewPhotoSelectOverlay);
} }
if (!selected && !context->selecting && !already) { if (!selected && !context->selecting && !loaded) {
if (clip.intersects(QRect(0, _height - st::normalFont->height, _width, st::normalFont->height))) { if (clip.intersects(QRect(0, _height - st::normalFont->height, _width, st::normalFont->height))) {
int32 statusX = st::msgDateImgPadding.x(), statusY = _height - st::normalFont->height - st::msgDateImgPadding.y(); int32 statusX = st::msgDateImgPadding.x(), statusY = _height - st::normalFont->height - st::msgDateImgPadding.y();
int32 statusW = st::normalFont->width(_statusText) + 2 * st::msgDateImgPadding.x(); int32 statusW = st::normalFont->width(_statusText) + 2 * st::msgDateImgPadding.x();
@ -470,7 +472,7 @@ void LayoutOverviewVideo::paint(Painter &p, const QRect &clip, uint32 selection,
p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over)); p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over));
p.setBrush(st::black); p.setBrush(st::black);
} else { } else {
bool over = textlnkDrawOver(already ? _openl : (_data->loader ? _cancell : _savel)); bool over = textlnkDrawOver(loaded ? _openl : (_data->loading() ? _cancell : _savel));
p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg); p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg);
} }
@ -478,19 +480,18 @@ void LayoutOverviewVideo::paint(Painter &p, const QRect &clip, uint32 selection,
p.drawEllipse(inner); p.drawEllipse(inner);
p.setRenderHint(QPainter::HighQualityAntialiasing, false); p.setRenderHint(QPainter::HighQualityAntialiasing, false);
p.setOpacity(1);
style::sprite icon; style::sprite icon;
if (radial) { if (radial) {
icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel); icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
} else if (already) { } else if (loaded) {
icon = (selected ? st::msgFileInPlaySelected : st::msgFileInPlay); icon = (selected ? st::msgFileInPlaySelected : st::msgFileInPlay);
} else { } else {
icon = (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload); icon = (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload);
} }
p.setOpacity(radial ? _radial->opacity() : 1); p.setOpacity((radial && loaded) ? _radial->opacity() : 1);
p.drawSpriteCenter(inner, icon); p.drawSpriteCenter(inner, icon);
if (radial) { if (radial) {
p.setOpacity(1);
QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine))); QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine)));
_radial->draw(p, rinner, st::msgFileRadialLine, selected ? st::msgInBgSelected : st::msgInBg); _radial->draw(p, rinner, st::msgFileRadialLine, selected ? st::msgInBgSelected : st::msgInBg);
} }
@ -504,8 +505,10 @@ void LayoutOverviewVideo::paint(Painter &p, const QRect &clip, uint32 selection,
} }
void LayoutOverviewVideo::getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const { void LayoutOverviewVideo::getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const {
bool loaded = _data->loaded();
if (hasPoint(x, y)) { if (hasPoint(x, y)) {
link = _data->already().isEmpty() ? (_data->loader ? _cancell : _savel) : _openl; link = loaded ? _openl : (_data->loading() ? _cancell : _savel);
} }
} }
@ -516,8 +519,8 @@ void LayoutOverviewVideo::updateStatusText() const {
statusSize = FileStatusSizeFailed; statusSize = FileStatusSizeFailed;
} else if (_data->status == FileUploading) { } else if (_data->status == FileUploading) {
statusSize = _data->uploadOffset; statusSize = _data->uploadOffset;
} else if (_data->loader) { } else if (_data->loading()) {
statusSize = _data->loader->currentOffset(); statusSize = _data->loadOffset();
} else if (!_data->already().isEmpty()) { } else if (!_data->already().isEmpty()) {
statusSize = FileStatusSizeLoaded; statusSize = FileStatusSizeLoaded;
} else { } else {
@ -535,9 +538,8 @@ void LayoutOverviewVideo::updateStatusText() const {
} }
LayoutOverviewAudio::LayoutOverviewAudio(AudioData *audio, HistoryItem *parent) : LayoutAbstractFileItem(parent) LayoutOverviewAudio::LayoutOverviewAudio(AudioData *audio, HistoryItem *parent) : LayoutAbstractFileItem(parent)
, _data(audio) { , _data(audio)
_data->prepareAutoLoader(_parent); , _namel(new AudioOpenLink(_data)) {
setLinks(new AudioOpenLink(_data), new AudioOpenLink(_data), new AudioCancelLink(_data)); setLinks(new AudioOpenLink(_data), new AudioOpenLink(_data), new AudioCancelLink(_data));
updateName(); updateName();
QString d = textcmdLink(1, textRichPrepare(langDateTime(date(_data->date)))); QString d = textcmdLink(1, textRichPrepare(langDateTime(date(_data->date))));
@ -553,13 +555,11 @@ void LayoutOverviewAudio::initDimensions() {
void LayoutOverviewAudio::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const { void LayoutOverviewAudio::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
bool selected = (selection == FullSelection); bool selected = (selection == FullSelection);
bool loaded = _data->loaded();
if (!loaded && _data->status == FileReady && _data->loader && !_data->loadingStarted()) {
_data->openOnSave = 0;
_data->save(QString());
}
if (_data->loadingStarted() && !_data->loader->loadingLocal()) { _data->automaticLoad(_parent);
bool loaded = _data->loaded(), displayLoading = _data->displayLoading();
if (displayLoading) {
ensureRadial(); ensureRadial();
if (!_radial->animating()) { if (!_radial->animating()) {
_radial->start(_data->progress()); _radial->start(_data->progress());
@ -593,7 +593,7 @@ void LayoutOverviewAudio::paint(Painter &p, const QRect &clip, uint32 selection,
float64 over = a_iconOver.current(); float64 over = a_iconOver.current();
p.setBrush(style::interpolate(st::msgFileInBg, st::msgFileInBgOver, over)); p.setBrush(style::interpolate(st::msgFileInBg, st::msgFileInBgOver, over));
} else { } else {
bool over = textlnkDrawOver(loaded ? _openl : (_data->loadingStarted() ? _cancell : _savel)); bool over = textlnkDrawOver(loaded ? _openl : (_data->loading() ? _cancell : _openl));
p.setBrush(over ? st::msgFileInBgOver : st::msgFileInBg); p.setBrush(over ? st::msgFileInBgOver : st::msgFileInBg);
} }
@ -612,7 +612,7 @@ void LayoutOverviewAudio::paint(Painter &p, const QRect &clip, uint32 selection,
icon = selected ? st::msgFileInPauseSelected : st::msgFileInPause; icon = selected ? st::msgFileInPauseSelected : st::msgFileInPause;
} else if (_statusSize < 0 || _statusSize == FileStatusSizeLoaded) { } else if (_statusSize < 0 || _statusSize == FileStatusSizeLoaded) {
icon = selected ? st::msgFileInPlaySelected : st::msgFileInPlay; icon = selected ? st::msgFileInPlaySelected : st::msgFileInPlay;
} else if (_data->loadingStarted()) { } else if (_data->loading()) {
icon = selected ? st::msgFileInCancelSelected : st::msgFileInCancel; icon = selected ? st::msgFileInCancelSelected : st::msgFileInCancel;
} else { } else {
icon = selected ? st::msgFileInDownloadSelected : st::msgFileInDownload; icon = selected ? st::msgFileInDownloadSelected : st::msgFileInDownload;
@ -654,7 +654,7 @@ void LayoutOverviewAudio::getState(TextLinkPtr &link, HistoryCursorState &cursor
QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, _width)); QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, _width));
if (inner.contains(x, y)) { if (inner.contains(x, y)) {
link = loaded ? _openl : ((_data->loadingStarted() || _data->status == FileUploading) ? _cancell : _savel); link = loaded ? _openl : ((_data->loading() || _data->status == FileUploading) ? _cancell : _openl);
return; return;
} }
if (rtlrect(nameleft, statustop, _width - nameleft - nameright, st::normalFont->height, _width).contains(x, y)) { if (rtlrect(nameleft, statustop, _width - nameleft - nameright, st::normalFont->height, _width).contains(x, y)) {
@ -664,6 +664,10 @@ void LayoutOverviewAudio::getState(TextLinkPtr &link, HistoryCursorState &cursor
cursor = inText ? HistoryInTextCursorState : HistoryDefaultCursorState; cursor = inText ? HistoryInTextCursorState : HistoryDefaultCursorState;
} }
} }
if (hasPoint(x, y) && !link && !_data->loading()) {
link = _namel;
return;
}
} }
void LayoutOverviewAudio::updateName() const { void LayoutOverviewAudio::updateName() const {
@ -683,7 +687,7 @@ bool LayoutOverviewAudio::updateStatusText() const {
int32 statusSize = 0, realDuration = 0; int32 statusSize = 0, realDuration = 0;
if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) { if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) {
statusSize = FileStatusSizeFailed; statusSize = FileStatusSizeFailed;
} else if (!_data->already().isEmpty() || !_data->data.isEmpty()) { } else if (_data->loaded()) {
AudioMsgId playing; AudioMsgId playing;
AudioPlayerState playingState = AudioPlayerStopped; AudioPlayerState playingState = AudioPlayerStopped;
int64 playingPosition = 0, playingDuration = 0; int64 playingPosition = 0, playingDuration = 0;
@ -717,8 +721,6 @@ LayoutOverviewDocument::LayoutOverviewDocument(DocumentData *document, HistoryIt
, _namew(st::semiboldFont->width(_name)) , _namew(st::semiboldFont->width(_name))
, _datew(st::normalFont->width(_date)) , _datew(st::normalFont->width(_date))
, _colorIndex(documentColorIndex(_data, _ext)) { , _colorIndex(documentColorIndex(_data, _ext)) {
_data->prepareAutoLoader(_parent);
setLinks(new DocumentOpenLink(_data), new DocumentSaveLink(_data), new DocumentCancelLink(_data)); setLinks(new DocumentOpenLink(_data), new DocumentSaveLink(_data), new DocumentCancelLink(_data));
setStatusSize(FileStatusSizeReady, _data->size, _data->song() ? _data->song()->duration : -1, 0); setStatusSize(FileStatusSizeReady, _data->size, _data->song() ? _data->song()->duration : -1, 0);
@ -753,8 +755,11 @@ void LayoutOverviewDocument::initDimensions() {
void LayoutOverviewDocument::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const { void LayoutOverviewDocument::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
bool selected = (selection == FullSelection); bool selected = (selection == FullSelection);
bool loaded = _data->loaded() || (_data->loader && _data->loader->localAvailable());
if (_data->loadingStarted() && !_data->loader->loadingLocal()) { _data->automaticLoad(_parent);
bool loaded = _data->loaded() || Local::willStickerImageLoad(mediaKey(DocumentFileLocation, _data->dc, _data->id)), displayLoading = _data->displayLoading();
if (displayLoading) {
ensureRadial(); ensureRadial();
if (!_radial->animating()) { if (!_radial->animating()) {
_radial->start(_data->progress()); _radial->start(_data->progress());
@ -785,7 +790,7 @@ void LayoutOverviewDocument::paint(Painter &p, const QRect &clip, uint32 selecti
float64 over = a_iconOver.current(); float64 over = a_iconOver.current();
p.setBrush(style::interpolate(st::msgFileInBg, st::msgFileInBgOver, over)); p.setBrush(style::interpolate(st::msgFileInBg, st::msgFileInBgOver, over));
} else { } else {
bool over = textlnkDrawOver(loaded ? _openl : (_data->loadingStarted() ? _cancell : _savel)); bool over = textlnkDrawOver(loaded ? _openl : (_data->loading() ? _cancell : _openl));
p.setBrush(over ? st::msgFileInBgOver : st::msgFileInBg); p.setBrush(over ? st::msgFileInBgOver : st::msgFileInBg);
} }
@ -802,9 +807,9 @@ void LayoutOverviewDocument::paint(Painter &p, const QRect &clip, uint32 selecti
style::sprite icon; style::sprite icon;
if (showPause) { if (showPause) {
icon = selected ? st::msgFileInPauseSelected : st::msgFileInPause; icon = selected ? st::msgFileInPauseSelected : st::msgFileInPause;
} else if (_statusSize < 0 || _statusSize == FileStatusSizeLoaded) { } else if (loaded) {
icon = selected ? st::msgFileInPlaySelected : st::msgFileInPlay; icon = selected ? st::msgFileInPlaySelected : st::msgFileInPlay;
} else if (_data->loadingStarted() && !_data->loader->loadingLocal()) { } else if (_data->loading()) {
icon = selected ? st::msgFileInCancelSelected : st::msgFileInCancel; icon = selected ? st::msgFileInCancelSelected : st::msgFileInCancel;
} else { } else {
icon = selected ? st::msgFileInDownloadSelected : st::msgFileInDownload; icon = selected ? st::msgFileInDownloadSelected : st::msgFileInDownload;
@ -847,36 +852,35 @@ void LayoutOverviewDocument::paint(Painter &p, const QRect &clip, uint32 selecti
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners); App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners);
} }
if (radial || (!loaded && !_data->loadingStarted())) { if (radial || (!loaded && !_data->loading())) {
QRect inner(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize); QRect inner(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
if (clip.intersects(inner)) { if (clip.intersects(inner)) {
float64 radialOpacity = (radial && loaded) ? _radial->opacity() : 1;
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
if (selected) { if (selected) {
p.setBrush(st::msgDateImgBgSelected); p.setBrush(st::msgDateImgBgSelected);
} else if (radial && loaded) {
p.setOpacity(st::msgDateImgBg->c.alphaF() * _radial->opacity());
p.setBrush(st::black);
} else if (_a_iconOver.animating()) { } else if (_a_iconOver.animating()) {
_a_iconOver.step(context->ms); _a_iconOver.step(context->ms);
float64 over = a_iconOver.current(); float64 over = a_iconOver.current();
p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over)); p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over));
p.setBrush(st::black); p.setBrush(st::black);
} else { } else {
bool over = textlnkDrawOver(_data->loadingStarted() ? _cancell : _savel); bool over = textlnkDrawOver(_data->loading() ? _cancell : _savel);
p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg); p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg);
} }
p.setOpacity(radialOpacity * p.opacity());
p.setRenderHint(QPainter::HighQualityAntialiasing); p.setRenderHint(QPainter::HighQualityAntialiasing);
p.drawEllipse(inner); p.drawEllipse(inner);
p.setRenderHint(QPainter::HighQualityAntialiasing, false); p.setRenderHint(QPainter::HighQualityAntialiasing, false);
p.setOpacity(radialOpacity);
style::sprite icon; style::sprite icon;
if (loaded || (_data->loadingStarted() && !_data->loader->loadingLocal())) { if (loaded || _data->loading()) {
icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel); icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
} else { } else {
icon = (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload); icon = (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload);
} }
p.setOpacity(radial ? _radial->opacity() : 1);
p.drawSpriteCenter(inner, icon); p.drawSpriteCenter(inner, icon);
if (radial) { if (radial) {
p.setOpacity(1); p.setOpacity(1);
@ -919,7 +923,7 @@ void LayoutOverviewDocument::paint(Painter &p, const QRect &clip, uint32 selecti
} }
void LayoutOverviewDocument::getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const { void LayoutOverviewDocument::getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const {
bool loaded = _data->loaded() || (_data->loader && _data->loader->localAvailable()); bool loaded = _data->loaded() || Local::willStickerImageLoad(mediaKey(DocumentFileLocation, _data->dc, _data->id));
bool showPause = updateStatusText(); bool showPause = updateStatusText();
@ -934,7 +938,11 @@ void LayoutOverviewDocument::getState(TextLinkPtr &link, HistoryCursorState &cur
QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, _width)); QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, _width));
if (inner.contains(x, y)) { if (inner.contains(x, y)) {
link = loaded ? _openl : ((_data->loadingStarted() || _data->status == FileUploading) ? _cancell : _savel); link = loaded ? _openl : ((_data->loading() || _data->status == FileUploading) ? _cancell : _openl);
return;
}
if (hasPoint(x, y) && !_data->loading()) {
link = _namel;
return; return;
} }
} else { } else {
@ -946,7 +954,7 @@ void LayoutOverviewDocument::getState(TextLinkPtr &link, HistoryCursorState &cur
QRect rthumb(rtlrect(0, st::linksBorder + st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, _width)); QRect rthumb(rtlrect(0, st::linksBorder + st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, _width));
if (rthumb.contains(x, y)) { if (rthumb.contains(x, y)) {
link = loaded ? _openl : ((_data->loadingStarted() || _data->status == FileUploading) ? _cancell : _savel); link = loaded ? _openl : ((_data->loading() || _data->status == FileUploading) ? _cancell : _savel);
return; return;
} }
@ -956,7 +964,7 @@ void LayoutOverviewDocument::getState(TextLinkPtr &link, HistoryCursorState &cur
return; return;
} }
} }
if (!_data->loadingStarted() && _data->access) { if (!_data->loading() && _data->access) {
if (loaded && rtlrect(0, st::linksBorder, nameleft, _height - st::linksBorder, _width).contains(x, y)) { if (loaded && rtlrect(0, st::linksBorder, nameleft, _height - st::linksBorder, _width).contains(x, y)) {
link = _namel; link = _namel;
return; return;
@ -976,8 +984,8 @@ bool LayoutOverviewDocument::updateStatusText() const {
statusSize = FileStatusSizeFailed; statusSize = FileStatusSizeFailed;
} else if (_data->status == FileUploading) { } else if (_data->status == FileUploading) {
statusSize = _data->uploadOffset; statusSize = _data->uploadOffset;
} else if (_data->loadingStarted()) { } else if (_data->loading()) {
statusSize = _data->loader->currentOffset(); statusSize = _data->loadOffset();
} else if (_data->loaded()) { } else if (_data->loaded()) {
if (_data->song()) { if (_data->song()) {
SongMsgId playing; SongMsgId playing;

View File

@ -323,10 +323,10 @@ protected:
return _data->progress(); return _data->progress();
} }
virtual bool dataFinished() const { virtual bool dataFinished() const {
return !_data->loader; return !_data->loading();
} }
virtual bool dataLoaded() const { virtual bool dataLoaded() const {
return !_data->already().isEmpty(); return _data->loaded();
} }
virtual bool iconAnimated() const { virtual bool iconAnimated() const {
return true; return true;
@ -363,10 +363,10 @@ protected:
return _data->progress(); return _data->progress();
} }
virtual bool dataFinished() const { virtual bool dataFinished() const {
return !_data->loader; return !_data->loading();
} }
virtual bool dataLoaded() const { virtual bool dataLoaded() const {
return !_data->already().isEmpty() || !_data->data.isEmpty(); return _data->loaded();
} }
virtual bool iconAnimated() const { virtual bool iconAnimated() const {
return true; return true;
@ -375,6 +375,7 @@ protected:
private: private:
OverviewItemInfo _info; OverviewItemInfo _info;
AudioData *_data; AudioData *_data;
TextLinkPtr _namel;
mutable Text _name, _details; mutable Text _name, _details;
mutable int32 _nameVersion; mutable int32 _nameVersion;
@ -407,13 +408,13 @@ protected:
return _data->progress(); return _data->progress();
} }
virtual bool dataFinished() const { virtual bool dataFinished() const {
return !_data->loader; return !_data->loading();
} }
virtual bool dataLoaded() const { virtual bool dataLoaded() const {
return _data->loaded(); return _data->loaded();
} }
virtual bool iconAnimated() const { virtual bool iconAnimated() const {
return _data->song() || !dataLoaded() || (_radial && _radial->animating()); return _data->song() || !_data->loaded() || (_radial && _radial->animating());
} }
private: private:

View File

@ -194,6 +194,7 @@ struct FileLoadResult {
int32 filesize; int32 filesize;
UploadFileParts fileparts; UploadFileParts fileparts;
QByteArray filemd5; QByteArray filemd5;
int32 partssize;
uint64 thumbId; // id is always file-id of media, thumbId is file-id of thumb ( == id for photos) uint64 thumbId; // id is always file-id of media, thumbId is file-id of thumb ( == id for photos)
QString thumbname; QString thumbname;
@ -211,9 +212,11 @@ struct FileLoadResult {
QString originalText; // when pasted had an image mime save text mime here to insert if image send was cancelled QString originalText; // when pasted had an image mime save text mime here to insert if image send was cancelled
void setFileData(const QByteArray &filedata) { void setFileData(const QByteArray &filedata) {
if (!filedata.isEmpty()) { if (filedata.isEmpty()) {
int32 size = filedata.size(); partssize = 0;
for (int32 i = 0, part = 0; i < size; i += UploadPartSize, ++part) { } else {
partssize = filedata.size();
for (int32 i = 0, part = 0; i < partssize; i += UploadPartSize, ++part) {
fileparts.insert(part, filedata.mid(i, UploadPartSize)); fileparts.insert(part, filedata.mid(i, UploadPartSize));
} }
filemd5.resize(32); filemd5.resize(32);

View File

@ -2469,13 +2469,6 @@ namespace Local {
return _localLoader->addTask(new ImageLoadTask(j->first, location, loader)); return _localLoader->addTask(new ImageLoadTask(j->first, location, loader));
} }
bool willImageLoad(const StorageKey &location, bool check) {
StorageMap::const_iterator j = _imagesMap.constFind(location);
if (j == _imagesMap.cend()) return false;
if (check && !fileExists(j->first, UserPath)) return false;
return true;
}
int32 hasImages() { int32 hasImages() {
return _imagesMap.size(); return _imagesMap.size();
} }
@ -2535,11 +2528,8 @@ namespace Local {
return _localLoader->addTask(new StickerImageLoadTask(j->first, location, loader)); return _localLoader->addTask(new StickerImageLoadTask(j->first, location, loader));
} }
bool willStickerImageLoad(const StorageKey &location, bool check) { bool willStickerImageLoad(const StorageKey &location) {
StorageMap::const_iterator j = _stickerImagesMap.constFind(location); return _stickerImagesMap.constFind(location) != _stickerImagesMap.cend();
if (j == _stickerImagesMap.cend()) return false;
if (check && !fileExists(j->first, UserPath)) return false;
return true;
} }
int32 hasStickers() { int32 hasStickers() {
@ -2601,13 +2591,6 @@ namespace Local {
return _localLoader->addTask(new AudioLoadTask(j->first, location, loader)); return _localLoader->addTask(new AudioLoadTask(j->first, location, loader));
} }
bool willAudioLoad(const StorageKey &location, bool check) {
StorageMap::const_iterator j = _audiosMap.constFind(location);
if (j == _audiosMap.cend()) return false;
if (check && !fileExists(j->first, UserPath)) return false;
return true;
}
int32 hasAudios() { int32 hasAudios() {
return _audiosMap.size(); return _audiosMap.size();
} }
@ -2623,8 +2606,8 @@ namespace Local {
} }
void _writeStorageImageLocation(QDataStream &stream, const StorageImageLocation &loc) { void _writeStorageImageLocation(QDataStream &stream, const StorageImageLocation &loc) {
stream << qint32(loc.width) << qint32(loc.height); stream << qint32(loc.width()) << qint32(loc.height());
stream << qint32(loc.dc) << quint64(loc.volume) << qint32(loc.local) << quint64(loc.secret); stream << qint32(loc.dc()) << quint64(loc.volume()) << qint32(loc.local()) << quint64(loc.secret());
} }
uint32 _storageImageLocationSize() { uint32 _storageImageLocationSize() {
@ -2896,7 +2879,7 @@ namespace Local {
attributes.push_back(MTP_documentAttributeImageSize(MTP_int(width), MTP_int(height))); attributes.push_back(MTP_documentAttributeImageSize(MTP_int(width), MTP_int(height)));
} }
DocumentData *doc = App::documentSet(id, 0, access, date, attributes, mime, thumb.dc ? ImagePtr(thumb) : ImagePtr(), dc, size, thumb); DocumentData *doc = App::documentSet(id, 0, access, date, attributes, mime, thumb.isNull() ? ImagePtr() : ImagePtr(thumb), dc, size, thumb);
if (!doc->sticker()) continue; if (!doc->sticker()) continue;
set.stickers.push_back(doc); set.stickers.push_back(doc);

View File

@ -124,19 +124,17 @@ namespace Local {
void writeImage(const StorageKey &location, const ImagePtr &img); void writeImage(const StorageKey &location, const ImagePtr &img);
void writeImage(const StorageKey &location, const StorageImageSaved &jpeg, bool overwrite = true); void writeImage(const StorageKey &location, const StorageImageSaved &jpeg, bool overwrite = true);
TaskId startImageLoad(const StorageKey &location, mtpFileLoader *loader); TaskId startImageLoad(const StorageKey &location, mtpFileLoader *loader);
bool willImageLoad(const StorageKey &location, bool check = false);
int32 hasImages(); int32 hasImages();
qint64 storageImagesSize(); qint64 storageImagesSize();
void writeStickerImage(const StorageKey &location, const QByteArray &data, bool overwrite = true); void writeStickerImage(const StorageKey &location, const QByteArray &data, bool overwrite = true);
TaskId startStickerImageLoad(const StorageKey &location, mtpFileLoader *loader); TaskId startStickerImageLoad(const StorageKey &location, mtpFileLoader *loader);
bool willStickerImageLoad(const StorageKey &location, bool check = false); bool willStickerImageLoad(const StorageKey &location);
int32 hasStickers(); int32 hasStickers();
qint64 storageStickersSize(); qint64 storageStickersSize();
void writeAudio(const StorageKey &location, const QByteArray &data, bool overwrite = true); void writeAudio(const StorageKey &location, const QByteArray &data, bool overwrite = true);
TaskId startAudioLoad(const StorageKey &location, mtpFileLoader *loader); TaskId startAudioLoad(const StorageKey &location, mtpFileLoader *loader);
bool willAudioLoad(const StorageKey &location, bool check = false);
int32 hasAudios(); int32 hasAudios();
qint64 storageAudiosSize(); qint64 storageAudiosSize();

View File

@ -23,6 +23,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include "lang.h" #include "lang.h"
#include "boxes/addcontactbox.h" #include "boxes/addcontactbox.h"
#include "fileuploader.h"
#include "application.h" #include "application.h"
#include "window.h" #include "window.h"
#include "settingswidget.h" #include "settingswidget.h"
@ -886,6 +887,12 @@ void MainWidget::deleteLayer(int32 selectedCount) {
QString str((selectedCount < 0) ? lang(selectedCount < -1 ? lng_selected_cancel_sure_this : lng_selected_delete_sure_this) : lng_selected_delete_sure(lt_count, selectedCount)); QString str((selectedCount < 0) ? lang(selectedCount < -1 ? lng_selected_cancel_sure_this : lng_selected_delete_sure_this) : lng_selected_delete_sure(lt_count, selectedCount));
ConfirmBox *box = new ConfirmBox((selectedCount < 0) ? str : str.arg(selectedCount), lang(lng_box_delete)); ConfirmBox *box = new ConfirmBox((selectedCount < 0) ? str : str.arg(selectedCount), lang(lng_box_delete));
if (selectedCount < 0) { if (selectedCount < 0) {
if (selectedCount < -1) {
if (HistoryItem *item = App::contextItem()) {
App::uploader()->pause(item->fullId());
connect(box, SIGNAL(destroyed(QObject*)), App::uploader(), SLOT(unpause()));
}
}
connect(box, SIGNAL(confirmed()), overview ? overview : static_cast<QWidget*>(&history), SLOT(onDeleteContextSure())); connect(box, SIGNAL(confirmed()), overview ? overview : static_cast<QWidget*>(&history), SLOT(onDeleteContextSure()));
} else { } else {
connect(box, SIGNAL(confirmed()), overview ? overview : static_cast<QWidget*>(&history), SLOT(onDeleteSelectedSure())); connect(box, SIGNAL(confirmed()), overview ? overview : static_cast<QWidget*>(&history), SLOT(onDeleteSelectedSure()));
@ -1619,21 +1626,10 @@ void MainWidget::messagesAffected(PeerData *peer, const MTPmessages_AffectedMess
void MainWidget::videoLoadProgress(mtpFileLoader *loader) { void MainWidget::videoLoadProgress(mtpFileLoader *loader) {
VideoData *video = App::video(loader->objId()); VideoData *video = App::video(loader->objId());
if (video->loader) { if (video->loaded()) {
video->status = FileReady; video->performActionOnLoad();
if (video->loader->done()) {
video->finish();
QString already = video->already();
if (!already.isEmpty() && video->openOnSave) {
QPoint pos(QCursor::pos());
if (video->openOnSave < 0 && !psShowOpenWithMenu(pos.x(), pos.y(), already)) {
psOpenFile(already, true);
} else {
psOpenFile(already, video->openOnSave < 0);
}
}
}
} }
const VideoItems &items(App::videoItems()); const VideoItems &items(App::videoItems());
VideoItems::const_iterator i = items.constFind(video); VideoItems::const_iterator i = items.constFind(video);
if (i != items.cend()) { if (i != items.cend()) {
@ -1673,7 +1669,7 @@ void MainWidget::videoLoadFailed(mtpFileLoader *loader, bool started) {
loadFailed(loader, started, SLOT(videoLoadRetry())); loadFailed(loader, started, SLOT(videoLoadRetry()));
VideoData *video = App::video(loader->objId()); VideoData *video = App::video(loader->objId());
if (video) { if (video) {
if (video->loader) video->finish(); if (video->loading()) video->cancel();
video->status = FileDownloadFailed; video->status = FileDownloadFailed;
} }
} }
@ -1686,35 +1682,10 @@ void MainWidget::videoLoadRetry() {
void MainWidget::audioLoadProgress(mtpFileLoader *loader) { void MainWidget::audioLoadProgress(mtpFileLoader *loader) {
AudioData *audio = App::audio(loader->objId()); AudioData *audio = App::audio(loader->objId());
if (audio->loader) { if (audio->loaded()) {
audio->status = FileReady; audio->performActionOnLoad();
if (audio->loader->done()) {
audio->finish();
QString already = audio->already();
bool play = audio->openOnSave > 0 && audio->openOnSaveMsgId.msg && audioPlayer();
if ((!already.isEmpty() && audio->openOnSave) || (!audio->data.isEmpty() && play)) {
if (play) {
AudioMsgId playing;
AudioPlayerState state = AudioPlayerStopped;
audioPlayer()->currentState(&playing, &state);
if (playing.msgId == audio->openOnSaveMsgId && !(state & AudioPlayerStoppedMask) && state != AudioPlayerFinishing) {
audioPlayer()->pauseresume(OverviewAudios);
} else {
audioPlayer()->play(AudioMsgId(audio, audio->openOnSaveMsgId));
if (App::main()) App::main()->audioMarkRead(audio);
}
} else {
QPoint pos(QCursor::pos());
if (audio->openOnSave < 0 && !psShowOpenWithMenu(pos.x(), pos.y(), already)) {
psOpenFile(already, true);
} else {
psOpenFile(already, audio->openOnSave < 0);
}
if (App::main()) App::main()->audioMarkRead(audio);
}
}
}
} }
const AudioItems &items(App::audioItems()); const AudioItems &items(App::audioItems());
AudioItems::const_iterator i = items.constFind(audio); AudioItems::const_iterator i = items.constFind(audio);
if (i != items.cend()) { if (i != items.cend()) {
@ -1733,13 +1704,13 @@ void MainWidget::audioPlayProgress(const AudioMsgId &audioId) {
AudioData *audio = audioId.audio; AudioData *audio = audioId.audio;
QString already = audio->already(true); QString already = audio->already(true);
if (already.isEmpty() && !audio->data.isEmpty()) { if (already.isEmpty() && !audio->data().isEmpty()) {
bool mp3 = (audio->mime == qstr("audio/mp3")); bool mp3 = (audio->mime == qstr("audio/mp3"));
QString filename = saveFileName(lang(lng_save_audio), mp3 ? qsl("MP3 Audio (*.mp3);;All files (*.*)") : qsl("OGG Opus Audio (*.ogg);;All files (*.*)"), qsl("audio"), mp3 ? qsl(".mp3") : qsl(".ogg"), false); QString filename = saveFileName(lang(lng_save_audio), mp3 ? qsl("MP3 Audio (*.mp3);;All files (*.*)") : qsl("OGG Opus Audio (*.ogg);;All files (*.*)"), qsl("audio"), mp3 ? qsl(".mp3") : qsl(".ogg"), false);
if (!filename.isEmpty()) { if (!filename.isEmpty()) {
QFile f(filename); QFile f(filename);
if (f.open(QIODevice::WriteOnly)) { if (f.open(QIODevice::WriteOnly)) {
if (f.write(audio->data) == audio->data.size()) { if (f.write(audio->data()) == audio->data().size()) {
f.close(); f.close();
already = filename; already = filename;
audio->setLocation(FileLocation(StorageFilePartial, filename)); audio->setLocation(FileLocation(StorageFilePartial, filename));
@ -1770,7 +1741,7 @@ void MainWidget::documentPlayProgress(const SongMsgId &songId) {
DocumentData *document = songId.song; DocumentData *document = songId.song;
QString already = document->already(true); QString already = document->already(true);
if (already.isEmpty() && !document->data.isEmpty()) { if (already.isEmpty() && !document->data().isEmpty()) {
QString name = document->name, filter; QString name = document->name, filter;
MimeType mimeType = mimeTypeForName(document->mime); MimeType mimeType = mimeTypeForName(document->mime);
QStringList p = mimeType.globPatterns(); QStringList p = mimeType.globPatterns();
@ -1787,7 +1758,7 @@ void MainWidget::documentPlayProgress(const SongMsgId &songId) {
if (!filename.isEmpty()) { if (!filename.isEmpty()) {
QFile f(filename); QFile f(filename);
if (f.open(QIODevice::WriteOnly)) { if (f.open(QIODevice::WriteOnly)) {
if (f.write(document->data) == document->data.size()) { if (f.write(document->data()) == document->data().size()) {
f.close(); f.close();
already = filename; already = filename;
document->setLocation(FileLocation(StorageFilePartial, filename)); document->setLocation(FileLocation(StorageFilePartial, filename));
@ -1832,8 +1803,8 @@ void MainWidget::audioLoadFailed(mtpFileLoader *loader, bool started) {
loadFailed(loader, started, SLOT(audioLoadRetry())); loadFailed(loader, started, SLOT(audioLoadRetry()));
AudioData *audio = App::audio(loader->objId()); AudioData *audio = App::audio(loader->objId());
if (audio) { if (audio) {
if (audio->loading()) audio->cancel();
audio->status = FileDownloadFailed; audio->status = FileDownloadFailed;
if (audio->loader) audio->finish();
} }
} }
@ -1844,70 +1815,11 @@ void MainWidget::audioLoadRetry() {
} }
void MainWidget::documentLoadProgress(mtpFileLoader *loader) { void MainWidget::documentLoadProgress(mtpFileLoader *loader) {
bool songPlayActivated = false;
DocumentData *document = App::document(loader->objId()); DocumentData *document = App::document(loader->objId());
if (document->loader) { if (document->loaded()) {
document->status = FileReady; document->performActionOnLoad();
if (document->loader->done()) {
document->finish();
QString already = document->already();
HistoryItem *item = (document->openOnSave && document->openOnSaveMsgId.msg) ? App::histItemById(document->openOnSaveMsgId) : 0;
bool playMusic = document->song() && audioPlayer() && document->openOnSave && item;
bool playAnimation = document->isAnimation() && document->openOnSave > 0 && item && item->getMedia();
if (document->openOnSave && (!already.isEmpty() || (!document->data.isEmpty() && (playMusic || playAnimation)))) {
if (playMusic) {
SongMsgId playing;
AudioPlayerState playingState = AudioPlayerStopped;
audioPlayer()->currentState(&playing, &playingState);
if (playing.msgId == item->fullId() && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
audioPlayer()->pauseresume(OverviewDocuments);
} else {
SongMsgId song(document, item->fullId());
audioPlayer()->play(song);
if (App::main()) App::main()->documentPlayProgress(song);
}
songPlayActivated = true;
} else if (document->openOnSave > 0 && document->size < MediaViewImageSizeLimit) {
if (!document->data.isEmpty() && playAnimation) {
if (document->openOnSave > 1) {
item->getMedia()->playInline(item);
} else {
App::wnd()->showDocument(document, item);
}
} else {
const FileLocation &location(document->location(true));
if (location.accessEnable()) {
if (document->openOnSave > 1) {
if (playAnimation) {
item->getMedia()->playInline(item);
} else {
psOpenFile(already);
}
} else {
if (playAnimation || (item && QImageReader(location.name()).canRead())) {
App::wnd()->showDocument(document, item);
} else {
psOpenFile(already);
}
}
location.accessDisable();
} else {
psOpenFile(already);
}
}
} else {
QPoint pos(QCursor::pos());
if (document->openOnSave < 0 && !psShowOpenWithMenu(pos.x(), pos.y(), already)) {
psOpenFile(already, true);
} else {
psOpenFile(already, document->openOnSave < 0);
}
}
}
}
} }
const DocumentItems &items(App::documentItems()); const DocumentItems &items(App::documentItems());
DocumentItems::const_iterator i = items.constFind(document); DocumentItems::const_iterator i = items.constFind(document);
if (i != items.cend()) { if (i != items.cend()) {
@ -1917,18 +1829,14 @@ void MainWidget::documentLoadProgress(mtpFileLoader *loader) {
} }
App::wnd()->documentUpdated(document); App::wnd()->documentUpdated(document);
if (!songPlayActivated && audioPlayer()) { if (!document->loaded() && document->loading() && document->song() && audioPlayer()) {
SongMsgId playing; SongMsgId playing;
AudioPlayerState playingState = AudioPlayerStopped; AudioPlayerState playingState = AudioPlayerStopped;
int64 playingPosition = 0, playingDuration = 0; int64 playingPosition = 0, playingDuration = 0;
int32 playingFrequency = 0; int32 playingFrequency = 0;
audioPlayer()->currentState(&playing, &playingState, &playingPosition, &playingDuration, &playingFrequency); audioPlayer()->currentState(&playing, &playingState, &playingPosition, &playingDuration, &playingFrequency);
if (playing.song == document && !_player.isHidden()) { if (playing.song == document && !_player.isHidden()) {
if (document->loader) { _player.updateState(playing, playingState, playingPosition, playingDuration, playingFrequency);
_player.updateState(playing, playingState, playingPosition, playingDuration, playingFrequency);
} else {
audioPlayer()->play(playing);
}
} }
} }
} }
@ -1937,7 +1845,7 @@ void MainWidget::documentLoadFailed(mtpFileLoader *loader, bool started) {
loadFailed(loader, started, SLOT(documentLoadRetry())); loadFailed(loader, started, SLOT(documentLoadRetry()));
DocumentData *document = App::document(loader->objId()); DocumentData *document = App::document(loader->objId());
if (document) { if (document) {
if (document->loader) document->finish(); if (document->loading()) document->cancel();
document->status = FileDownloadFailed; document->status = FileDownloadFailed;
} }
} }
@ -2124,7 +2032,7 @@ void MainWidget::updateScrollColors() {
void MainWidget::setChatBackground(const App::WallPaper &wp) { void MainWidget::setChatBackground(const App::WallPaper &wp) {
_background = new App::WallPaper(wp); _background = new App::WallPaper(wp);
_background->full->load(); _background->full->loadEvenCancelled();
checkChatBackground(); checkChatBackground();
} }

View File

@ -88,11 +88,7 @@ MediaView::MediaView() : TWidget(App::wnd())
, _docThumbx(0) , _docThumbx(0)
, _docThumby(0) , _docThumby(0)
, _docThumbw(0) , _docThumbw(0)
, _docRadialFirst(0) , _docRadial(animation(this, &MediaView::step_radial))
, _docRadialStart(0)
, _docRadialLast(0)
, _docRadialOpacity(1)
, a_docRadialStart(0, 1)
, _docDownload(this, lang(lng_media_download), st::mvDocLink) , _docDownload(this, lang(lng_media_download), st::mvDocLink)
, _docSaveAs(this, lang(lng_mediaview_save_as), st::mvDocLink) , _docSaveAs(this, lang(lng_mediaview_save_as), st::mvDocLink)
, _docCancel(this, lang(lng_cancel), st::mvDocLink) , _docCancel(this, lang(lng_cancel), st::mvDocLink)
@ -130,8 +126,6 @@ MediaView::MediaView() : TWidget(App::wnd())
_saveMsgText.setLink(1, TextLinkPtr(new SaveMsgLink(this))); _saveMsgText.setLink(1, TextLinkPtr(new SaveMsgLink(this)));
_transparentBrush = QBrush(App::sprite().copy(st::mvTransparentBrush)); _transparentBrush = QBrush(App::sprite().copy(st::mvTransparentBrush));
_docRadialPen = QPen(st::white->p);
_docRadialPen.setWidth(st::radialLine);
setWindowFlags(Qt::FramelessWindowHint | Qt::BypassWindowManagerHint | Qt::Tool | Qt::NoDropShadowWindowHint); setWindowFlags(Qt::FramelessWindowHint | Qt::BypassWindowManagerHint | Qt::Tool | Qt::NoDropShadowWindowHint);
moveToScreen(); moveToScreen();
@ -259,9 +253,9 @@ void MediaView::stopGif() {
void MediaView::documentUpdated(DocumentData *doc) { void MediaView::documentUpdated(DocumentData *doc) {
if (_doc && _doc == doc && !fileShown()) { if (_doc && _doc == doc && !fileShown()) {
if ((_doc->loader && _docCancel.isHidden()) || (!_doc->loader && !_docCancel.isHidden())) { if ((_doc->loading() && _docCancel.isHidden()) || (!_doc->loading() && !_docCancel.isHidden())) {
updateControls(); updateControls();
} else if (_doc->loader) { } else if (_doc->loading()) {
updateDocSize(); updateDocSize();
update(_docRect); update(_docRect);
} }
@ -278,8 +272,8 @@ void MediaView::changingMsgId(HistoryItem *row, MsgId newId) {
void MediaView::updateDocSize() { void MediaView::updateDocSize() {
if (!_doc || fileShown()) return; if (!_doc || fileShown()) return;
if (_doc->loader) { if (_doc->loading()) {
quint64 ready = _doc->loader->currentOffset(), total = _doc->size; quint64 ready = _doc->loadOffset(), total = _doc->size;
QString readyStr, totalStr, mb; QString readyStr, totalStr, mb;
if (total >= 1024 * 1024) { // more than 1 mb if (total >= 1024 * 1024) { // more than 1 mb
qint64 readyTenthMb = (ready * 10 / (1024 * 1024)), totalTenthMb = (total * 10 / (1024 * 1024)); qint64 readyTenthMb = (ready * 10 / (1024 * 1024)), totalTenthMb = (total * 10 / (1024 * 1024));
@ -310,14 +304,14 @@ void MediaView::updateDocSize() {
void MediaView::updateControls() { void MediaView::updateControls() {
if (_doc && !fileShown()) { if (_doc && !fileShown()) {
if (_doc->loader) { if (_doc->loading()) {
_docDownload.hide(); _docDownload.hide();
_docSaveAs.hide(); _docSaveAs.hide();
_docCancel.moveToLeft(_docRect.x() + 2 * st::mvDocPadding + st::mvDocIconSize, _docRect.y() + st::mvDocPadding + st::mvDocLinksTop); _docCancel.moveToLeft(_docRect.x() + 2 * st::mvDocPadding + st::mvDocIconSize, _docRect.y() + st::mvDocPadding + st::mvDocLinksTop);
_docCancel.show(); _docCancel.show();
if (!_docRadialFirst) _docRadialFirst = _docRadialLast = _docRadialStart = getms(); if (!_docRadial.animating()) {
if (!_a_state.animating()) _a_state.start(); _docRadial.start(_doc->progress());
_a_state.step(); }
} else { } else {
if (_doc->loaded(true)) { if (_doc->loaded(true)) {
_docDownload.hide(); _docDownload.hide();
@ -398,7 +392,7 @@ void MediaView::updateControls() {
} }
void MediaView::updateDropdown() { void MediaView::updateDropdown() {
_btnSaveCancel->setVisible(_doc && _doc->loader); _btnSaveCancel->setVisible(_doc && _doc->loading());
_btnToMessage->setVisible(_msgid > 0); _btnToMessage->setVisible(_msgid > 0);
_btnShowInFolder->setVisible(_doc && !_doc->already(true).isEmpty()); _btnShowInFolder->setVisible(_doc && !_doc->already(true).isEmpty());
_btnSaveAs->setVisible(true); _btnSaveAs->setVisible(true);
@ -449,52 +443,36 @@ void MediaView::step_state(uint64 ms, bool timer) {
update(toUpdate); update(toUpdate);
if (dt < 1) result = true; if (dt < 1) result = true;
} }
if (_doc && _docRadialStart > 0) {
float64 prg = _doc->loader ? qMax(_doc->loader->currentProgress(), 0.0001) : (_doc->status == FileDownloadFailed ? 0 : (_doc->loaded() ? 1 : 0));
if (prg != a_docRadial.to()) {
a_docRadial.start(prg);
_docRadialStart = _docRadialLast;
}
_docRadialLast = ms;
float64 dt = float64(ms - _docRadialStart), fulldt = float64(ms - _docRadialFirst);
_docRadialOpacity = qMin(fulldt / st::radialDuration, 1.);
if (_doc->loader) {
a_docRadial.update(1. - (st::radialDuration / (st::radialDuration + dt)), anim::linear);
result = true;
} else if (dt >= st::radialDuration || (_doc->loaded() && _doc->size < MediaViewImageSizeLimit && _doc->isAnimation())) {
a_docRadial.update(1, anim::linear);
result = true;
_docRadialFirst = _docRadialLast = _docRadialStart = 0;
a_docRadial = anim::fvalue(0, 0);
if (_doc->loaded() && _doc->size < MediaViewImageSizeLimit) {
if (!_doc->data.isEmpty() && _doc->isAnimation()) {
displayDocument(_doc, App::histItemById(_msgmigrated ? 0 : _channel, _msgid));
} else {
const FileLocation &location(_doc->location(true));
if (location.accessEnable()) {
if (QImageReader(location.name()).canRead()) {
displayDocument(_doc, App::histItemById(_msgmigrated ? 0 : _channel, _msgid));
}
location.accessDisable();
}
}
}
} else {
float64 r = dt / st::radialDuration;
a_docRadial.update(r, anim::linear);
result = true;
_docRadialOpacity *= 1 - r;
}
float64 fromstart = fulldt / st::radialPeriod;
a_docRadialStart.update(fromstart - qFloor(fromstart), anim::linear);
update(_docIconRect);
}
if (!result && _animations.isEmpty()) { if (!result && _animations.isEmpty()) {
_a_state.stop(); _a_state.stop();
} }
} }
void MediaView::step_radial(uint64 ms, bool timer) {
if (!_doc) {
_docRadial.stop();
return;
}
_docRadial.update(_doc->progress(), !_doc->loading(), ms);
if (timer && _docRadial.animating()) {
update(_docIconRect);
}
if (_doc->loaded() && _doc->size < MediaViewImageSizeLimit && (!_docRadial.animating() || _doc->isAnimation())) {
if (!_doc->data().isEmpty() && _doc->isAnimation()) {
displayDocument(_doc, App::histItemById(_msgmigrated ? 0 : _channel, _msgid));
} else {
const FileLocation &location(_doc->location(true));
if (location.accessEnable()) {
if (_doc->isAnimation() || QImageReader(location.name()).canRead()) {
displayDocument(_doc, App::histItemById(_msgmigrated ? 0 : _channel, _msgid));
}
location.accessDisable();
}
}
}
}
MediaView::~MediaView() { MediaView::~MediaView() {
delete _gif; delete _gif;
setBadPointer(_gif); setBadPointer(_gif);
@ -556,7 +534,7 @@ void MediaView::onSaveAs() {
QString file; QString file;
if (_doc) { if (_doc) {
const FileLocation &location(_doc->location(true)); const FileLocation &location(_doc->location(true));
if (!_doc->data.isEmpty() || location.accessEnable()) { if (!_doc->data().isEmpty() || location.accessEnable()) {
QFileInfo alreadyInfo(location.name()); QFileInfo alreadyInfo(location.name());
QDir alreadyDir(alreadyInfo.dir()); QDir alreadyDir(alreadyInfo.dir());
QString name = alreadyInfo.fileName(), filter; QString name = alreadyInfo.fileName(), filter;
@ -577,16 +555,16 @@ void MediaView::onSaveAs() {
file = saveFileName(lang(lng_save_file), filter, qsl("doc"), name, true, alreadyDir); file = saveFileName(lang(lng_save_file), filter, qsl("doc"), name, true, alreadyDir);
psShowOverAll(this); psShowOverAll(this);
if (!file.isEmpty() && file != location.name()) { if (!file.isEmpty() && file != location.name()) {
if (_doc->data.isEmpty()) { if (_doc->data().isEmpty()) {
QFile(location.name()).copy(file); QFile(location.name()).copy(file);
} else { } else {
QFile f(file); QFile f(file);
f.open(QIODevice::WriteOnly); f.open(QIODevice::WriteOnly);
f.write(_doc->data); f.write(_doc->data());
} }
} }
if (_doc->data.isEmpty()) location.accessDisable(); if (_doc->data().isEmpty()) location.accessDisable();
} else { } else {
if (!fileShown()) { if (!fileShown()) {
DocumentSaveLink::doSave(_doc, true); DocumentSaveLink::doSave(_doc, true);
@ -615,10 +593,13 @@ void MediaView::onSaveAs() {
} }
void MediaView::onDocClick() { void MediaView::onDocClick() {
if (_doc->loader && _doc->loader->started()) { if (_doc->loading()) {
onSaveCancel(); onSaveCancel();
} else { } else {
DocumentOpenLink::doOpen(_doc); DocumentOpenLink::doOpen(_doc, ActionOnLoadNone);
if (_doc->loading() && !_docRadial.animating()) {
_docRadial.start(_doc->progress());
}
} }
} }
@ -695,8 +676,8 @@ void MediaView::onDownload() {
} }
void MediaView::onSaveCancel() { void MediaView::onSaveCancel() {
if (_doc && _doc->loader) { if (_doc && _doc->loading()) {
_doc->loader->cancel(); _doc->cancel();
} }
} }
@ -935,7 +916,7 @@ void MediaView::displayPhoto(PhotoData *photo, HistoryItem *item) {
_from = _user; _from = _user;
} }
updateControls(); updateControls();
_photo->full->load(); _photo->full->loadEvenCancelled();
if (isHidden()) { if (isHidden()) {
psUpdateOverlayed(this); psUpdateOverlayed(this);
show(); show();
@ -956,35 +937,39 @@ void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) { // empty
_caption = Text(); _caption = Text();
if (_doc) { if (_doc) {
if (_doc->isAnimation() && !_doc->loaded() && _doc->status == FileReady && _doc->loader && !_doc->loadingStarted()) { if (_doc->sticker()) {
_doc->openOnSave = 0; _doc->checkSticker();
_doc->save(QString()); if (!_doc->sticker()->img->isNull()) {
} _current = _doc->sticker()->img->pix();
} else {
const FileLocation &location(_doc->location(true)); _current = _doc->thumb->pixBlurred(_doc->dimensions.width(), _doc->dimensions.height());
if (_doc->sticker() && !_doc->sticker()->img->isNull() && _doc->sticker()->img->loaded()) {
_current = _doc->sticker()->img->pix();
} else if (!_doc->data.isEmpty() && _doc->isAnimation()) {
if (!_gif) {
if (_doc->dimensions.width() && _doc->dimensions.height()) {
_current = _doc->thumb->pixNoCache(_doc->dimensions.width(), _doc->dimensions.height(), true, true, false, _doc->dimensions.width(), _doc->dimensions.height());
}
_gif = new ClipReader(location, _doc->data);
} }
} else if (location.accessEnable()) { } else {
if (_doc->isAnimation()) { _doc->automaticLoad(item);
const FileLocation &location(_doc->location(true));
if (!_doc->data().isEmpty() && _doc->isAnimation()) {
if (!_gif) { if (!_gif) {
if (_doc->dimensions.width() && _doc->dimensions.height()) { if (_doc->dimensions.width() && _doc->dimensions.height()) {
_current = _doc->thumb->pixNoCache(_doc->dimensions.width(), _doc->dimensions.height(), true, true, false, _doc->dimensions.width(), _doc->dimensions.height()); _current = _doc->thumb->pixNoCache(_doc->dimensions.width(), _doc->dimensions.height(), true, true, false, _doc->dimensions.width(), _doc->dimensions.height());
} }
_gif = new ClipReader(location, _doc->data); _gif = new ClipReader(location, _doc->data());
} }
} else { } else if (location.accessEnable()) {
if (QImageReader(location.name()).canRead()) { if (_doc->isAnimation()) {
_current = QPixmap::fromImage(App::readImage(location.name(), 0, false), Qt::ColorOnly); if (!_gif) {
if (_doc->dimensions.width() && _doc->dimensions.height()) {
_current = _doc->thumb->pixNoCache(_doc->dimensions.width(), _doc->dimensions.height(), true, true, false, _doc->dimensions.width(), _doc->dimensions.height());
}
_gif = new ClipReader(location, _doc->data());
}
} else {
if (QImageReader(location.name()).canRead()) {
_current = QPixmap::fromImage(App::readImage(location.name(), 0, false), Qt::ColorOnly);
}
} }
location.accessDisable();
} }
location.accessDisable();
} }
} }
@ -1030,10 +1015,7 @@ void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) { // empty
_docNameWidth = st::mvDocNameFont->width(_docName); _docNameWidth = st::mvDocNameFont->width(_docName);
} }
_docRadialFirst = _docRadialLast = _docRadialStart = 0; _docRadial.stop();
float64 prg = (_doc && _doc->loader) ? _doc->loader->currentProgress() : 0;
a_docRadial = anim::fvalue(prg, qMax(prg, 0.0001));
// _docSize is updated in updateControls() // _docSize is updated in updateControls()
_docRect = QRect((width() - st::mvDocSize.width()) / 2, (height() - st::mvDocSize.height()) / 2, st::mvDocSize.width(), st::mvDocSize.height()); _docRect = QRect((width() - st::mvDocSize.width()) / 2, (height() - st::mvDocSize.height()) / 2, st::mvDocSize.width(), st::mvDocSize.height());
@ -1134,6 +1116,8 @@ void MediaView::paintEvent(QPaintEvent *e) {
int32 h = int((_photo->full->height() * (qreal(w) / qreal(_photo->full->width()))) + 0.9999); int32 h = int((_photo->full->height() * (qreal(w) / qreal(_photo->full->width()))) + 0.9999);
_current = _photo->thumb->pixNoCache(w, h, true, true); _current = _photo->thumb->pixNoCache(w, h, true, true);
if (cRetina()) _current.setDevicePixelRatio(cRetinaFactor()); if (cRetina()) _current.setDevicePixelRatio(cRetinaFactor());
} else if (_current.isNull()) {
_current = _photo->thumb->pix();
} }
} }
p.setOpacity(1); p.setOpacity(1);
@ -1211,10 +1195,17 @@ void MediaView::paintEvent(QPaintEvent *e) {
if (_docRect.intersects(r)) { if (_docRect.intersects(r)) {
p.fillRect(_docRect, st::mvDocBg->b); p.fillRect(_docRect, st::mvDocBg->b);
if (_docIconRect.intersects(r)) { if (_docIconRect.intersects(r)) {
bool radial = false;
float64 radialOpacity = 0;
if (_docRadial.animating()) {
_docRadial.step(ms);
radial = _docRadial.animating();
radialOpacity = _docRadial.opacity();
}
icon = true; icon = true;
if (!_doc || _doc->thumb->isNull()) { if (!_doc || _doc->thumb->isNull()) {
p.fillRect(_docIconRect, _docIconColor->b); p.fillRect(_docIconRect, _docIconColor->b);
if ((!_doc || _doc->loaded()) && (!_docRadialStart || _docRadialOpacity < 1)) { if ((!_doc || _doc->loaded()) && (!radial || radialOpacity < 1)) {
p.drawSprite(_docIconRect.topLeft() + QPoint(rtl() ? 0 : (_docIconRect.width() - _docIcon.pxWidth()), 0), _docIcon); p.drawSprite(_docIconRect.topLeft() + QPoint(rtl() ? 0 : (_docIconRect.width() - _docIcon.pxWidth()), 0), _docIcon);
p.setPen(st::mvDocExtColor->p); p.setPen(st::mvDocExtColor->p);
p.setFont(st::mvDocExtFont->f); p.setFont(st::mvDocExtFont->f);
@ -1228,33 +1219,27 @@ void MediaView::paintEvent(QPaintEvent *e) {
} }
float64 o = overLevel(OverIcon); float64 o = overLevel(OverIcon);
if (_doc && _docRadialStart > 0) { if (radial) {
if (!_doc->loaded() && _docRadialOpacity < 1) { if (!_doc->loaded() && radialOpacity < 1) {
p.setOpacity((o * 1. + (1 - o) * st::radialDownloadOpacity) * (1 - _docRadialOpacity)); p.setOpacity((o * 1. + (1 - o) * st::radialDownloadOpacity) * (1 - radialOpacity));
p.drawSpriteCenter(_docIconRect, st::radialDownload); p.drawSpriteCenter(_docIconRect, st::radialDownload);
} }
p.setRenderHint(QPainter::HighQualityAntialiasing);
QRect inner(QPoint(_docIconRect.x() + ((_docIconRect.width() - st::radialSize.width()) / 2), _docIconRect.y() + ((_docIconRect.height() - st::radialSize.height()) / 2)), st::radialSize); QRect inner(QPoint(_docIconRect.x() + ((_docIconRect.width() - st::radialSize.width()) / 2), _docIconRect.y() + ((_docIconRect.height() - st::radialSize.height()) / 2)), st::radialSize);
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
p.setBrush(st::black->b); p.setBrush(st::black);
p.setOpacity(_docRadialOpacity * st::radialBgOpacity); p.setOpacity(radialOpacity * st::radialBgOpacity);
p.drawEllipse(inner);
p.setOpacity((o * 1. + (1 - o) * st::radialCancelOpacity) * _docRadialOpacity); p.setRenderHint(QPainter::HighQualityAntialiasing);
p.drawEllipse(inner);
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
p.setOpacity((o * 1. + (1 - o) * st::radialCancelOpacity) * radialOpacity);
p.drawSpriteCenter(_docIconRect, st::radialCancel); p.drawSpriteCenter(_docIconRect, st::radialCancel);
p.setOpacity(1);
QRect arc(inner.marginsRemoved(QMargins(st::radialLine, st::radialLine, st::radialLine, st::radialLine))); QRect arc(inner.marginsRemoved(QMargins(st::radialLine, st::radialLine, st::radialLine, st::radialLine)));
_docRadial.draw(p, arc, st::radialLine, st::white);
p.setOpacity(_docRadialOpacity);
p.setPen(_docRadialPen);
int len = 16 + a_docRadial.current() * 5744;
p.drawArc(arc, 1440 - a_docRadialStart.current() * 5760 - len, len);
p.setOpacity(1);
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
} else if (_doc && !_doc->loaded()) { } else if (_doc && !_doc->loaded()) {
p.setOpacity((o * 1. + (1 - o) * st::radialDownloadOpacity)); p.setOpacity((o * 1. + (1 - o) * st::radialDownloadOpacity));
p.drawSpriteCenter(_docIconRect, st::radialDownload); p.drawSpriteCenter(_docIconRect, st::radialDownload);
@ -1406,7 +1391,7 @@ void MediaView::keyPressEvent(QKeyEvent *e) {
} else if (e->key() == Qt::Key_Copy || (e->key() == Qt::Key_C && e->modifiers().testFlag(Qt::ControlModifier))) { } else if (e->key() == Qt::Key_Copy || (e->key() == Qt::Key_C && e->modifiers().testFlag(Qt::ControlModifier))) {
onCopy(); onCopy();
} else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return || e->key() == Qt::Key_Space) { } else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return || e->key() == Qt::Key_Space) {
if (_doc && !_doc->loader && !fileShown()) { if (_doc && !_doc->loading() && !fileShown()) {
onDocClick(); onDocClick();
} }
} else if (e->key() == Qt::Key_Left) { } else if (e->key() == Qt::Key_Left) {
@ -1577,13 +1562,7 @@ void MediaView::preloadData(int32 delta) {
case MediaTypePhoto: static_cast<HistoryPhoto*>(media)->photo()->forget(); break; case MediaTypePhoto: static_cast<HistoryPhoto*>(media)->photo()->forget(); break;
case MediaTypeDocument: case MediaTypeDocument:
case MediaTypeGif: case MediaTypeGif:
case MediaTypeSticker: case MediaTypeSticker: media->getDocument()->forget(); break;
DocumentData *doc = media->getDocument();
doc->forget();
if (!doc->data.isEmpty() && doc->prepareAutoLoader(item)) {
doc->data.clear();
}
break;
} }
} }
} }
@ -1605,15 +1584,12 @@ void MediaView::preloadData(int32 delta) {
if (HistoryItem *item = App::histItemById(previewHistory->channelId(), previewHistory->overview[_overview][previewIndex])) { if (HistoryItem *item = App::histItemById(previewHistory->channelId(), previewHistory->overview[_overview][previewIndex])) {
if (HistoryMedia *media = item->getMedia()) { if (HistoryMedia *media = item->getMedia()) {
switch (media->type()) { switch (media->type()) {
case MediaTypePhoto: static_cast<HistoryPhoto*>(media)->photo()->full->load(); break; case MediaTypePhoto: static_cast<HistoryPhoto*>(media)->photo()->full->loadEvenCancelled(); break;
case MediaTypeDocument: case MediaTypeDocument:
case MediaTypeGif: { case MediaTypeGif: {
DocumentData *doc = media->getDocument(); DocumentData *doc = media->getDocument();
doc->thumb->load(); doc->thumb->load();
if (doc->isAnimation() && !doc->loaded() && doc->status == FileReady && doc->loader && !doc->loadingStarted()) { doc->automaticLoad(item);
doc->openOnSave = 0;
doc->save(QString());
}
} break; } break;
case MediaTypeSticker: media->getDocument()->sticker()->img->load(); break; case MediaTypeSticker: media->getDocument()->sticker()->img->load(); break;
} }
@ -1629,7 +1605,7 @@ void MediaView::preloadData(int32 delta) {
} }
for (int32 i = from; i <= to; ++i) { for (int32 i = from; i <= to; ++i) {
if (i >= 0 && i < _user->photos.size() && i != _index) { if (i >= 0 && i < _user->photos.size() && i != _index) {
_user->photos[i]->full->load(); _user->photos[i]->full->loadEvenCancelled();
} }
} }
int32 forgetIndex = _index - delta * 2; int32 forgetIndex = _index - delta * 2;

View File

@ -65,8 +65,6 @@ public:
void updateControls(); void updateControls();
void updateDropdown(); void updateDropdown();
void step_state(uint64 ms, bool timer);
void showSaveMsgFile(); void showSaveMsgFile();
void close(); void close();
@ -116,6 +114,9 @@ private:
void updateHeader(); void updateHeader();
void snapXY(); void snapXY();
void step_state(uint64 ms, bool timer);
void step_radial(uint64 ms, bool timer);
QBrush _transparentBrush; QBrush _transparentBrush;
PhotoData *_photo; PhotoData *_photo;
@ -154,10 +155,7 @@ private:
int32 _docNameWidth, _docSizeWidth, _docExtWidth; int32 _docNameWidth, _docSizeWidth, _docExtWidth;
QRect _docRect, _docIconRect; QRect _docRect, _docIconRect;
int32 _docThumbx, _docThumby, _docThumbw; int32 _docThumbx, _docThumby, _docThumbw;
uint64 _docRadialFirst, _docRadialStart, _docRadialLast; RadialAnimation _docRadial;
float64 _docRadialOpacity;
QPen _docRadialPen;
anim::fvalue a_docRadial, a_docRadialStart;
LinkButton _docDownload, _docSaveAs, _docCancel; LinkButton _docDownload, _docSaveAs, _docCancel;
History *_migrated, *_history; // if conversation photos or files overview History *_migrated, *_history; // if conversation photos or files overview

View File

@ -26,14 +26,14 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include "localstorage.h" #include "localstorage.h"
namespace { namespace {
int32 _priority = 1; int32 GlobalPriority = 1;
struct DataRequested { struct DataRequested {
DataRequested() { DataRequested() {
memset(v, 0, sizeof(v)); memset(v, 0, sizeof(v));
} }
int64 v[MTPDownloadSessionsCount]; int64 v[MTPDownloadSessionsCount];
}; };
QMap<int32, DataRequested> _dataRequested; QMap<int32, DataRequested> DataRequestedMap;
} }
struct mtpFileLoaderQueue { struct mtpFileLoaderQueue {
mtpFileLoaderQueue() : queries(0), start(0), end(0) { mtpFileLoaderQueue() : queries(0), start(0), end(0) {
@ -47,63 +47,64 @@ namespace {
LoaderQueues queues; LoaderQueues queues;
} }
mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &volume, int32 local, const uint64 &secret, int32 size) mtpFileLoader::mtpFileLoader(const StorageImageLocation *location, int32 size, LoadFromCloudSetting fromCloud, bool autoLoading)
: prev(0) : prev(0)
, next(0) , next(0)
, priority(0) , priority(0)
, _paused(false) , _paused(false)
, inQueue(false) , _autoLoading(autoLoading)
, complete(false) , _inQueue(false)
, _complete(false)
, _localStatus(LocalNotTried) , _localStatus(LocalNotTried)
, skippedBytes(0) , _skippedBytes(0)
, nextRequestOffset(0) , _nextRequestOffset(0)
, lastComplete(false) , _lastComplete(false)
, dc(dc) , _dc(location->dc())
, _locationType(UnknownFileLocation) , _locationType(UnknownFileLocation)
, volume(volume) , _location(location)
, local(local) , _id(0)
, secret(secret) , _access(0)
, id(0) , _fileIsOpen(false)
, access(0) , _toCache(LoadToCacheAsWell)
, fileIsOpen(false) , _fromCloud(fromCloud)
, size(size) , _size(size)
, type(mtpc_storage_fileUnknown) , _type(mtpc_storage_fileUnknown)
, _localTaskId(0) { , _localTaskId(0) {
LoaderQueues::iterator i = queues.find(dc); LoaderQueues::iterator i = queues.find(_dc);
if (i == queues.cend()) { if (i == queues.cend()) {
i = queues.insert(dc, mtpFileLoaderQueue()); i = queues.insert(_dc, mtpFileLoaderQueue());
} }
queue = &i.value(); queue = &i.value();
} }
mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, LocationType type, const QString &to, int32 size, bool todata) mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, LocationType type, const QString &to, int32 size, LoadToCacheSetting toCache, LoadFromCloudSetting fromCloud, bool autoLoading)
: prev(0) : prev(0)
, next(0) , next(0)
, priority(0) , priority(0)
, _paused(false) , _paused(false)
, inQueue(false) , _autoLoading(autoLoading)
, complete(false) , _inQueue(false)
, _complete(false)
, _localStatus(LocalNotTried) , _localStatus(LocalNotTried)
, skippedBytes(0) , _skippedBytes(0)
, nextRequestOffset(0) , _nextRequestOffset(0)
, lastComplete(false) , _lastComplete(false)
, dc(dc) , _dc(dc)
, _locationType(type) , _locationType(type)
, volume(0) , _location(0)
, local(0) , _id(id)
, secret(0) , _access(access)
, id(id) , _file(to)
, access(access) , _fname(to)
, file(to) , _fileIsOpen(false)
, fname(to) , _toCache(toCache)
, fileIsOpen(false) , _fromCloud(fromCloud)
, duplicateInData(todata) , _size(size)
, size(size) , _type(mtpc_storage_fileUnknown)
, type(mtpc_storage_fileUnknown)
, _localTaskId(0) { , _localTaskId(0) {
LoaderQueues::iterator i = queues.find(MTP::dld[0] + dc); LoaderQueues::iterator i = queues.find(MTP::dld[0] + _dc);
if (i == queues.cend()) { if (i == queues.cend()) {
i = queues.insert(MTP::dld[0] + dc, mtpFileLoaderQueue()); i = queues.insert(MTP::dld[0] + _dc, mtpFileLoaderQueue());
} }
queue = &i.value(); queue = &i.value();
} }
@ -124,40 +125,45 @@ QPixmap mtpFileLoader::imagePixmap() const {
void mtpFileLoader::readImage() const { void mtpFileLoader::readImage() const {
QByteArray format; QByteArray format;
switch (type) { switch (_type) {
case mtpc_storage_fileGif: format = "GIF"; break; case mtpc_storage_fileGif: format = "GIF"; break;
case mtpc_storage_fileJpeg: format = "JPG"; break; case mtpc_storage_fileJpeg: format = "JPG"; break;
case mtpc_storage_filePng: format = "PNG"; break; case mtpc_storage_filePng: format = "PNG"; break;
default: format = QByteArray(); break; default: format = QByteArray(); break;
} }
_imagePixmap = QPixmap::fromImage(App::readImage(data, &format, false), Qt::ColorOnly); _imagePixmap = QPixmap::fromImage(App::readImage(_data, &format, false), Qt::ColorOnly);
if (!_imagePixmap.isNull()) { if (!_imagePixmap.isNull()) {
_imageFormat = format; _imageFormat = format;
} }
} }
float64 mtpFileLoader::currentProgress() const { float64 mtpFileLoader::currentProgress() const {
if (complete) return 1; if (_complete) return 1;
if (!fullSize()) return 0; if (!fullSize()) return 0;
return float64(currentOffset()) / fullSize(); return float64(currentOffset()) / fullSize();
} }
int32 mtpFileLoader::currentOffset(bool includeSkipped) const { int32 mtpFileLoader::currentOffset(bool includeSkipped) const {
return (fileIsOpen ? file.size() : data.size()) - (includeSkipped ? 0 : skippedBytes); return (_fileIsOpen ? _file.size() : _data.size()) - (includeSkipped ? 0 : _skippedBytes);
} }
int32 mtpFileLoader::fullSize() const { int32 mtpFileLoader::fullSize() const {
return size; return _size;
} }
void mtpFileLoader::setFileName(const QString &fileName) { bool mtpFileLoader::setFileName(const QString &fileName) {
if (duplicateInData && fname.isEmpty() && !fileName.isEmpty()) { if (_toCache != LoadToCacheAsWell || !_fname.isEmpty()) return fileName.isEmpty();
file.setFileName(fname = fileName); _fname = fileName;
} _file.setFileName(_fname);
return true;
}
void mtpFileLoader::permitLoadFromCloud() {
_fromCloud = LoadFromCloudOrLocal;
} }
uint64 mtpFileLoader::objId() const { uint64 mtpFileLoader::objId() const {
return id; return _id;
} }
void mtpFileLoader::loadNext() { void mtpFileLoader::loadNext() {
@ -171,51 +177,35 @@ void mtpFileLoader::loadNext() {
} }
} }
void mtpFileLoader::finishFail() {
bool started = currentOffset(true) > 0;
cancelRequests();
type = mtpc_storage_fileUnknown;
complete = true;
if (fileIsOpen) {
file.close();
fileIsOpen = false;
file.remove();
}
data = QByteArray();
emit failed(this, started);
file.setFileName(fname = QString());
loadNext();
}
bool mtpFileLoader::loadPart() { bool mtpFileLoader::loadPart() {
if (complete || lastComplete || (!requests.isEmpty() && !size)) return false; if (_complete || _lastComplete || (!_requests.isEmpty() && !_size)) return false;
if (size && nextRequestOffset >= size) return false; if (_size && _nextRequestOffset >= _size) return false;
int32 limit = DocumentDownloadPartSize; int32 limit = DocumentDownloadPartSize;
MTPInputFileLocation loc; MTPInputFileLocation loc;
switch (_locationType) { if (_location) {
case UnknownFileLocation: loc = MTP_inputFileLocation(MTP_long(_location->volume()), MTP_int(_location->local()), MTP_long(_location->secret()));
loc = MTP_inputFileLocation(MTP_long(volume), MTP_int(local), MTP_long(secret));
limit = DownloadPartSize; limit = DownloadPartSize;
break; } else {
case VideoFileLocation: switch (_locationType) {
loc = MTP_inputVideoFileLocation(MTP_long(id), MTP_long(access)); case VideoFileLocation:
break; loc = MTP_inputVideoFileLocation(MTP_long(_id), MTP_long(_access));
case AudioFileLocation: break;
loc = MTP_inputAudioFileLocation(MTP_long(id), MTP_long(access)); case AudioFileLocation:
break; loc = MTP_inputAudioFileLocation(MTP_long(_id), MTP_long(_access));
case DocumentFileLocation: break;
loc = MTP_inputDocumentFileLocation(MTP_long(id), MTP_long(access)); case DocumentFileLocation:
break; loc = MTP_inputDocumentFileLocation(MTP_long(_id), MTP_long(_access));
default: break;
finishFail(); default:
return false; cancel(true);
break; return false;
break;
}
} }
int32 offset = _nextRequestOffset, dcIndex = 0;
int32 offset = nextRequestOffset, dcIndex = 0; DataRequested &dr(DataRequestedMap[_dc]);
DataRequested &dr(_dataRequested[dc]); if (_size) {
if (size) {
for (int32 i = 1; i < MTPDownloadSessionsCount; ++i) { for (int32 i = 1; i < MTPDownloadSessionsCount; ++i) {
if (dr.v[i] < dr.v[dcIndex]) { if (dr.v[i] < dr.v[dcIndex]) {
dcIndex = i; dcIndex = i;
@ -223,104 +213,104 @@ bool mtpFileLoader::loadPart() {
} }
} }
App::app()->killDownloadSessionsStop(dc); App::app()->killDownloadSessionsStop(_dc);
mtpRequestId reqId = MTP::send(MTPupload_GetFile(MTPupload_getFile(loc, MTP_int(offset), MTP_int(limit))), rpcDone(&mtpFileLoader::partLoaded, offset), rpcFail(&mtpFileLoader::partFailed), MTP::dld[dcIndex] + dc, 50); mtpRequestId reqId = MTP::send(MTPupload_GetFile(MTPupload_getFile(loc, MTP_int(offset), MTP_int(limit))), rpcDone(&mtpFileLoader::partLoaded, offset), rpcFail(&mtpFileLoader::partFailed), MTP::dld[dcIndex] + _dc, 50);
++queue->queries; ++queue->queries;
dr.v[dcIndex] += limit; dr.v[dcIndex] += limit;
requests.insert(reqId, dcIndex); _requests.insert(reqId, dcIndex);
nextRequestOffset += limit; _nextRequestOffset += limit;
return true; return true;
} }
void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRequestId req) { void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRequestId req) {
// uint64 ms = getms(); // uint64 ms = getms();
Requests::iterator i = requests.find(req); Requests::iterator i = _requests.find(req);
if (i == requests.cend()) return loadNext(); if (i == _requests.cend()) return loadNext();
int32 limit = (_locationType == UnknownFileLocation) ? DownloadPartSize : DocumentDownloadPartSize; int32 limit = (_locationType == UnknownFileLocation) ? DownloadPartSize : DocumentDownloadPartSize;
int32 dcIndex = i.value(); int32 dcIndex = i.value();
_dataRequested[dc].v[dcIndex] -= limit; DataRequestedMap[_dc].v[dcIndex] -= limit;
--queue->queries; --queue->queries;
requests.erase(i); _requests.erase(i);
const MTPDupload_file &d(result.c_upload_file()); const MTPDupload_file &d(result.c_upload_file());
const string &bytes(d.vbytes.c_string().v); const string &bytes(d.vbytes.c_string().v);
if (bytes.size()) { if (bytes.size()) {
if (fileIsOpen) { if (_fileIsOpen) {
int64 fsize = file.size(); int64 fsize = _file.size();
if (offset < fsize) { if (offset < fsize) {
skippedBytes -= bytes.size(); _skippedBytes -= bytes.size();
} else if (offset > fsize) { } else if (offset > fsize) {
skippedBytes += offset - fsize; _skippedBytes += offset - fsize;
} }
file.seek(offset); _file.seek(offset);
if (file.write(bytes.data(), bytes.size()) != qint64(bytes.size())) { if (_file.write(bytes.data(), bytes.size()) != qint64(bytes.size())) {
return finishFail(); return cancel(true);
} }
} else { } else {
data.reserve(offset + bytes.size()); _data.reserve(offset + bytes.size());
if (offset > data.size()) { if (offset > _data.size()) {
skippedBytes += offset - data.size(); _skippedBytes += offset - _data.size();
data.resize(offset); _data.resize(offset);
} }
if (offset == data.size()) { if (offset == _data.size()) {
data.append(bytes.data(), bytes.size()); _data.append(bytes.data(), bytes.size());
} else { } else {
skippedBytes -= bytes.size(); _skippedBytes -= bytes.size();
if (int64(offset + bytes.size()) > data.size()) { if (int64(offset + bytes.size()) > _data.size()) {
data.resize(offset + bytes.size()); _data.resize(offset + bytes.size());
} }
memcpy(data.data() + offset, bytes.data(), bytes.size()); memcpy(_data.data() + offset, bytes.data(), bytes.size());
} }
} }
} }
if (!bytes.size() || (bytes.size() % 1024)) { // bad next offset if (!bytes.size() || (bytes.size() % 1024)) { // bad next offset
lastComplete = true; _lastComplete = true;
} }
if (requests.isEmpty() && (lastComplete || (size && nextRequestOffset >= size))) { if (_requests.isEmpty() && (_lastComplete || (_size && _nextRequestOffset >= _size))) {
if (!fname.isEmpty() && duplicateInData) { if (!_fname.isEmpty() && (_toCache == LoadToCacheAsWell)) {
if (!fileIsOpen) fileIsOpen = file.open(QIODevice::WriteOnly); if (!_fileIsOpen) _fileIsOpen = _file.open(QIODevice::WriteOnly);
if (!fileIsOpen) { if (!_fileIsOpen) {
return finishFail(); return cancel(true);
} }
if (file.write(data) != qint64(data.size())) { if (_file.write(_data) != qint64(_data.size())) {
return finishFail(); return cancel(true);
} }
} }
type = d.vtype.type(); _type = d.vtype.type();
complete = true; _complete = true;
if (fileIsOpen) { if (_fileIsOpen) {
file.close(); _file.close();
fileIsOpen = false; _fileIsOpen = false;
psPostprocessFile(QFileInfo(file).absoluteFilePath()); psPostprocessFile(QFileInfo(_file).absoluteFilePath());
} }
removeFromQueue(); removeFromQueue();
emit App::wnd()->imageLoaded(); emit App::wnd()->imageLoaded();
if (!queue->queries) { if (!queue->queries) {
App::app()->killDownloadSessionsStart(dc); App::app()->killDownloadSessionsStart(_dc);
} }
if (_localStatus == LocalNotFound || _localStatus == LocalFailed) { if (_localStatus == LocalNotFound || _localStatus == LocalFailed) {
if (_locationType != UnknownFileLocation) { // audio, video, document if (_locationType != UnknownFileLocation) { // audio, video, document
MediaKey mkey = mediaKey(_locationType, dc, id); MediaKey mkey = mediaKey(_locationType, _dc, _id);
if (!fname.isEmpty()) { if (!_fname.isEmpty()) {
Local::writeFileLocation(mkey, FileLocation(mtpToStorageType(type), fname)); Local::writeFileLocation(mkey, FileLocation(mtpToStorageType(_type), _fname));
} }
if (duplicateInData) { if (_toCache == LoadToCacheAsWell) {
if (_locationType == DocumentFileLocation) { if (_locationType == DocumentFileLocation) {
Local::writeStickerImage(mkey, data); Local::writeStickerImage(mkey, _data);
} else if (_locationType == AudioFileLocation) { } else if (_locationType == AudioFileLocation) {
Local::writeAudio(mkey, data); Local::writeAudio(mkey, _data);
} }
} }
} else { } else {
Local::writeImage(storageKey(dc, volume, local), StorageImageSaved(mtpToStorageType(type), data)); Local::writeImage(storageKey(*_location), StorageImageSaved(mtpToStorageType(_type), _data));
} }
} }
} }
@ -331,12 +321,12 @@ void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRe
bool mtpFileLoader::partFailed(const RPCError &error) { bool mtpFileLoader::partFailed(const RPCError &error) {
if (mtpIsFlood(error)) return false; if (mtpIsFlood(error)) return false;
finishFail(); cancel(true);
return true; return true;
} }
void mtpFileLoader::removeFromQueue() { void mtpFileLoader::removeFromQueue() {
if (!inQueue) return; if (!_inQueue) return;
if (next) { if (next) {
next->prev = prev; next->prev = prev;
} }
@ -350,7 +340,7 @@ void mtpFileLoader::removeFromQueue() {
queue->start = next; queue->start = next;
} }
next = prev = 0; next = prev = 0;
inQueue = false; _inQueue = false;
} }
void mtpFileLoader::pause() { void mtpFileLoader::pause() {
@ -366,11 +356,11 @@ bool mtpFileLoader::tryLoadLocal() {
return true; return true;
} }
if (_locationType == UnknownFileLocation) { if (_location) {
_localTaskId = Local::startImageLoad(storageKey(dc, volume, local), this); _localTaskId = Local::startImageLoad(storageKey(*_location), this);
} else { } else {
if (duplicateInData) { if (_toCache == LoadToCacheAsWell) {
MediaKey mkey = mediaKey(_locationType, dc, id); MediaKey mkey = mediaKey(_locationType, _dc, _id);
if (_locationType == DocumentFileLocation) { if (_locationType == DocumentFileLocation) {
_localTaskId = Local::startStickerImageLoad(mkey, this); _localTaskId = Local::startStickerImageLoad(mkey, this);
} else if (_locationType == AudioFileLocation) { } else if (_locationType == AudioFileLocation) {
@ -379,37 +369,14 @@ bool mtpFileLoader::tryLoadLocal() {
} }
} }
if (data.isEmpty()) { if (_localStatus != LocalNotTried) {
if (_localTaskId) { return _complete;
_localStatus = LocalLoading; } else if (_localTaskId) {
return true; _localStatus = LocalLoading;
} return true;
_localStatus = LocalNotFound;
return false;
} }
_localStatus = LocalNotFound;
_localStatus = LocalLoaded; return false;
if (!fname.isEmpty() && duplicateInData) {
if (!fileIsOpen) fileIsOpen = file.open(QIODevice::WriteOnly);
if (!fileIsOpen) {
finishFail();
return true;
}
if (file.write(data) != qint64(data.size())) {
finishFail();
return true;
}
}
complete = true;
if (fileIsOpen) {
file.close();
fileIsOpen = false;
psPostprocessFile(QFileInfo(file).absoluteFilePath());
}
emit App::wnd()->imageLoaded();
emit progress(this);
loadNext();
return true;
} }
void mtpFileLoader::localLoaded(const StorageImageSaved &result, const QByteArray &imageFormat, const QPixmap &imagePixmap) { void mtpFileLoader::localLoaded(const StorageImageSaved &result, const QByteArray &imageFormat, const QPixmap &imagePixmap) {
@ -419,113 +386,93 @@ void mtpFileLoader::localLoaded(const StorageImageSaved &result, const QByteArra
start(true); start(true);
return; return;
} }
data = result.data; _data = result.data;
type = mtpFromStorageType(result.type); _type = mtpFromStorageType(result.type);
if (!imagePixmap.isNull()) { if (!imagePixmap.isNull()) {
_imageFormat = imageFormat; _imageFormat = imageFormat;
_imagePixmap = imagePixmap; _imagePixmap = imagePixmap;
} }
_localStatus = LocalLoaded; _localStatus = LocalLoaded;
if (!fname.isEmpty() && duplicateInData) { if (!_fname.isEmpty() && _toCache == LoadToCacheAsWell) {
if (!fileIsOpen) fileIsOpen = file.open(QIODevice::WriteOnly); if (!_fileIsOpen) _fileIsOpen = _file.open(QIODevice::WriteOnly);
if (!fileIsOpen) { if (!_fileIsOpen) {
finishFail(); cancel(true);
return; return;
} }
if (file.write(data) != qint64(data.size())) { if (_file.write(_data) != qint64(_data.size())) {
finishFail(); cancel(true);
return; return;
} }
} }
complete = true;
if (fileIsOpen) { _complete = true;
file.close(); if (_fileIsOpen) {
fileIsOpen = false; _file.close();
psPostprocessFile(QFileInfo(file).absoluteFilePath()); _fileIsOpen = false;
psPostprocessFile(QFileInfo(_file).absoluteFilePath());
} }
emit App::wnd()->imageLoaded(); emit App::wnd()->imageLoaded();
emit progress(this); emit progress(this);
loadNext(); loadNext();
} }
bool mtpFileLoader::localAvailable() const {
if (_localStatus == LocalLoading || _localStatus == LocalLoaded || _localStatus == LocalNeedsTry) {
return true;
}
if (_localStatus == LocalNotFound || _localStatus == LocalFailed) {
return false;
}
bool result = false;
if (_locationType == UnknownFileLocation) {
result = Local::willImageLoad(storageKey(dc, volume, local));
} else {
if (duplicateInData) {
MediaKey mkey = mediaKey(_locationType, dc, id);
if (_locationType == DocumentFileLocation) {
result = Local::willStickerImageLoad(mkey);
} else if (_locationType == AudioFileLocation) {
result = Local::willAudioLoad(mkey);
}
}
}
_localStatus = result ? LocalNeedsTry : LocalNotFound;
return result;
}
void mtpFileLoader::start(bool loadFirst, bool prior) { void mtpFileLoader::start(bool loadFirst, bool prior) {
if (_paused) { if (_paused) {
_paused = false; _paused = false;
} }
if (complete || tryLoadLocal()) return; if (_complete || tryLoadLocal()) return;
if (!fname.isEmpty() && !duplicateInData && !fileIsOpen) { if (_fromCloud == LoadFromLocalOnly) {
fileIsOpen = file.open(QIODevice::WriteOnly); cancel();
if (!fileIsOpen) { return;
return finishFail(); }
if (!_fname.isEmpty() && _toCache == LoadToFileOnly && !_fileIsOpen) {
_fileIsOpen = _file.open(QIODevice::WriteOnly);
if (!_fileIsOpen) {
return cancel(true);
} }
} }
mtpFileLoader *before = 0, *after = 0; mtpFileLoader *before = 0, *after = 0;
if (prior) { if (prior) {
if (inQueue && priority == _priority) { if (_inQueue && priority == GlobalPriority) {
if (loadFirst) { if (loadFirst) {
if (!prev) return startLoading(loadFirst, prior); if (!prev) return startLoading(loadFirst, prior);
before = queue->start; before = queue->start;
} else { } else {
if (!next || next->priority < _priority) return startLoading(loadFirst, prior); if (!next || next->priority < GlobalPriority) return startLoading(loadFirst, prior);
after = next; after = next;
while (after->next && after->next->priority == _priority) { while (after->next && after->next->priority == GlobalPriority) {
after = after->next; after = after->next;
} }
} }
} else { } else {
priority = _priority; priority = GlobalPriority;
if (loadFirst) { if (loadFirst) {
if (inQueue && !prev) return startLoading(loadFirst, prior); if (_inQueue && !prev) return startLoading(loadFirst, prior);
before = queue->start; before = queue->start;
} else { } else {
if (inQueue) { if (_inQueue) {
if (next && next->priority == _priority) { if (next && next->priority == GlobalPriority) {
after = next; after = next;
} else if (prev && prev->priority < _priority) { } else if (prev && prev->priority < GlobalPriority) {
before = prev; before = prev;
while (before->prev && before->prev->priority < _priority) { while (before->prev && before->prev->priority < GlobalPriority) {
before = before->prev; before = before->prev;
} }
} else { } else {
return startLoading(loadFirst, prior); return startLoading(loadFirst, prior);
} }
} else { } else {
if (queue->start && queue->start->priority == _priority) { if (queue->start && queue->start->priority == GlobalPriority) {
after = queue->start; after = queue->start;
} else { } else {
before = queue->start; before = queue->start;
} }
} }
if (after) { if (after) {
while (after->next && after->next->priority == _priority) { while (after->next && after->next->priority == GlobalPriority) {
after = after->next; after = after->next;
} }
} }
@ -533,20 +480,20 @@ void mtpFileLoader::start(bool loadFirst, bool prior) {
} }
} else { } else {
if (loadFirst) { if (loadFirst) {
if (inQueue && (!prev || prev->priority == _priority)) return startLoading(loadFirst, prior); if (_inQueue && (!prev || prev->priority == GlobalPriority)) return startLoading(loadFirst, prior);
before = prev; before = prev;
while (before->prev && before->prev->priority != _priority) { while (before->prev && before->prev->priority != GlobalPriority) {
before = before->prev; before = before->prev;
} }
} else { } else {
if (inQueue && !next) return startLoading(loadFirst, prior); if (_inQueue && !next) return startLoading(loadFirst, prior);
after = queue->end; after = queue->end;
} }
} }
removeFromQueue(); removeFromQueue();
inQueue = true; _inQueue = true;
if (!queue->start) { if (!queue->start) {
queue->start = queue->end = this; queue->start = queue->end = this;
} else if (before) { } else if (before) {
@ -576,40 +523,50 @@ void mtpFileLoader::start(bool loadFirst, bool prior) {
} }
void mtpFileLoader::cancel() { void mtpFileLoader::cancel() {
cancel(false);
}
void mtpFileLoader::cancel(bool fail) {
bool started = currentOffset(true) > 0;
cancelRequests(); cancelRequests();
type = mtpc_storage_fileUnknown; _type = mtpc_storage_fileUnknown;
complete = true; _complete = true;
if (fileIsOpen) { if (_fileIsOpen) {
file.close(); _file.close();
fileIsOpen = false; _fileIsOpen = false;
file.remove(); _file.remove();
} }
data = QByteArray(); _data = QByteArray();
file.setFileName(QString()); if (fail) {
emit progress(this); emit failed(this, started);
} else {
emit progress(this);
}
_fname = QString();
_file.setFileName(_fname);
loadNext(); loadNext();
} }
void mtpFileLoader::cancelRequests() { void mtpFileLoader::cancelRequests() {
if (requests.isEmpty()) return; if (_requests.isEmpty()) return;
int32 limit = (_locationType == UnknownFileLocation) ? DownloadPartSize : DocumentDownloadPartSize; int32 limit = (_locationType == UnknownFileLocation) ? DownloadPartSize : DocumentDownloadPartSize;
DataRequested &dr(_dataRequested[dc]); DataRequested &dr(DataRequestedMap[_dc]);
for (Requests::const_iterator i = requests.cbegin(), e = requests.cend(); i != e; ++i) { for (Requests::const_iterator i = _requests.cbegin(), e = _requests.cend(); i != e; ++i) {
MTP::cancel(i.key()); MTP::cancel(i.key());
int32 dcIndex = i.value(); int32 dcIndex = i.value();
dr.v[dcIndex] -= limit; dr.v[dcIndex] -= limit;
} }
queue->queries -= requests.size(); queue->queries -= _requests.size();
requests.clear(); _requests.clear();
if (!queue->queries) { if (!queue->queries) {
App::app()->killDownloadSessionsStart(dc); App::app()->killDownloadSessionsStart(_dc);
} }
} }
void mtpFileLoader::startLoading(bool loadFirst, bool prior) { void mtpFileLoader::startLoading(bool loadFirst, bool prior) {
if ((queue->queries >= MaxFileQueries && (!loadFirst || !prior)) || complete) return; if ((queue->queries >= MaxFileQueries && (!loadFirst || !prior)) || _complete) return;
loadPart(); loadPart();
} }
@ -623,6 +580,6 @@ mtpFileLoader::~mtpFileLoader() {
namespace MTP { namespace MTP {
void clearLoaderPriorities() { void clearLoaderPriorities() {
++_priority; ++GlobalPriority;
} }
} }

View File

@ -100,7 +100,6 @@ struct StorageImageSaved {
enum LocalLoadStatus { enum LocalLoadStatus {
LocalNotTried, LocalNotTried,
LocalNeedsTry,
LocalNotFound, LocalNotFound,
LocalLoading, LocalLoading,
LocalLoaded, LocalLoaded,
@ -109,55 +108,64 @@ enum LocalLoadStatus {
typedef void *TaskId; // no interface, just id typedef void *TaskId; // no interface, just id
enum LoadFromCloudSetting {
LoadFromCloudOrLocal,
LoadFromLocalOnly,
};
enum LoadToCacheSetting {
LoadToFileOnly,
LoadToCacheAsWell,
};
struct mtpFileLoaderQueue; struct mtpFileLoaderQueue;
class StorageImageLocation;
class mtpFileLoader : public QObject, public RPCSender { class mtpFileLoader : public QObject, public RPCSender {
Q_OBJECT Q_OBJECT
public: public:
mtpFileLoader(int32 dc, const uint64 &volume, int32 local, const uint64 &secret, int32 size = 0); mtpFileLoader(const StorageImageLocation *location, int32 size, LoadFromCloudSetting fromCloud, bool autoLoading);
mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, LocationType type, const QString &to, int32 size, bool todata = false); mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, LocationType type, const QString &toFile, int32 size, LoadToCacheSetting toCache, LoadFromCloudSetting fromCloud, bool autoLoading);
bool done() const { bool done() const {
return complete; return _complete;
} }
mtpTypeId fileType() const { mtpTypeId fileType() const {
return type; return _type;
} }
const QByteArray &bytes() const { const QByteArray &bytes() const {
return data; return _data;
} }
QByteArray imageFormat() const; QByteArray imageFormat() const;
QPixmap imagePixmap() const; QPixmap imagePixmap() const;
QString fileName() const { QString fileName() const {
return fname; return _fname;
} }
float64 currentProgress() const; float64 currentProgress() const;
int32 currentOffset(bool includeSkipped = false) const; int32 currentOffset(bool includeSkipped = false) const;
int32 fullSize() const; int32 fullSize() const;
void setFileName(const QString &filename); // set filename for duplicateInData loader bool setFileName(const QString &filename); // set filename for loaders to cache
void permitLoadFromCloud();
void pause(); void pause();
void start(bool loadFirst = false, bool prior = true); void start(bool loadFirst = false, bool prior = true);
void cancel(); void cancel();
bool loading() const { bool loading() const {
return inQueue; return _inQueue;
} }
bool paused() const { bool paused() const {
return _paused; return _paused;
} }
bool started() const { bool started() const {
return inQueue || _paused; return _inQueue || _paused;
} }
bool loadingLocal() const { bool loadingLocal() const {
return (_localStatus == LocalLoading); return (_localStatus == LocalLoading);
} }
bool autoLoading() const {
bool localAvailable() const; return _autoLoading;
}
uint64 objId() const; uint64 objId() const;
@ -176,45 +184,44 @@ signals:
private: private:
mtpFileLoaderQueue *queue; mtpFileLoaderQueue *queue;
bool _paused, inQueue, complete; bool _paused, _autoLoading, _inQueue, _complete;
mutable LocalLoadStatus _localStatus; mutable LocalLoadStatus _localStatus;
bool tryLoadLocal(); bool tryLoadLocal();
void cancelRequests(); void cancelRequests();
typedef QMap<mtpRequestId, int32> Requests; typedef QMap<mtpRequestId, int32> Requests;
Requests requests; Requests _requests;
int32 skippedBytes; int32 _skippedBytes;
int32 nextRequestOffset; int32 _nextRequestOffset;
bool lastComplete; bool _lastComplete;
void startLoading(bool loadFirst, bool prior); void startLoading(bool loadFirst, bool prior);
void removeFromQueue(); void removeFromQueue();
void loadNext(); void loadNext();
void finishFail(); void cancel(bool failed);
bool loadPart(); bool loadPart();
void partLoaded(int32 offset, const MTPupload_File &result, mtpRequestId req); void partLoaded(int32 offset, const MTPupload_File &result, mtpRequestId req);
bool partFailed(const RPCError &error); bool partFailed(const RPCError &error);
int32 dc; int32 _dc;
LocationType _locationType; LocationType _locationType;
const StorageImageLocation *_location;
uint64 volume; // for photo locations uint64 _id; // for other locations
int32 local; uint64 _access;
uint64 secret; QFile _file;
QString _fname;
bool _fileIsOpen;
uint64 id; // for other locations LoadToCacheSetting _toCache;
uint64 access; LoadFromCloudSetting _fromCloud;
QFile file;
QString fname;
bool fileIsOpen;
bool duplicateInData;
QByteArray data; QByteArray _data;
int32 size; int32 _size;
mtpTypeId type; mtpTypeId _type;
TaskId _localTaskId; TaskId _localTaskId;
mutable QByteArray _imageFormat; mutable QByteArray _imageFormat;
@ -222,3 +229,5 @@ private:
void readImage() const; void readImage() const;
}; };
static mtpFileLoader * const CancelledFileLoader = reinterpret_cast<mtpFileLoader * const>(&SharedMemoryLocation0);

View File

@ -1271,7 +1271,7 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
if (lnkPhoto) { if (lnkPhoto) {
_menu->addAction(lang(lng_context_open_image), this, SLOT(openContextUrl()))->setEnabled(true); _menu->addAction(lang(lng_context_open_image), this, SLOT(openContextUrl()))->setEnabled(true);
} else { } else {
if ((lnkVideo && lnkVideo->video()->loader) || (lnkAudio && lnkAudio->audio()->loadingStarted()) || (lnkDocument && lnkDocument->document()->loadingStarted())) { if ((lnkVideo && lnkVideo->video()->loading()) || (lnkAudio && lnkAudio->audio()->loading()) || (lnkDocument && lnkDocument->document()->loading())) {
_menu->addAction(lang(lng_context_cancel_download), this, SLOT(cancelContextDownload()))->setEnabled(true); _menu->addAction(lang(lng_context_cancel_download), this, SLOT(cancelContextDownload()))->setEnabled(true);
} else { } else {
if ((lnkVideo && !lnkVideo->video()->already(true).isEmpty()) || (lnkAudio && !lnkAudio->audio()->already(true).isEmpty()) || (lnkDocument && !lnkDocument->document()->already(true).isEmpty())) { if ((lnkVideo && !lnkVideo->video()->already(true).isEmpty()) || (lnkAudio && !lnkAudio->audio()->already(true).isEmpty()) || (lnkDocument && !lnkDocument->document()->already(true).isEmpty())) {
@ -1504,8 +1504,13 @@ void OverviewInner::cancelContextDownload() {
VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data()); VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data());
AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_contextMenuLnk.data()); AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_contextMenuLnk.data());
DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data()); DocumentLink *lnkDocument = dynamic_cast<DocumentLink*>(_contextMenuLnk.data());
mtpFileLoader *loader = lnkVideo ? lnkVideo->video()->loader : (lnkAudio ? lnkAudio->audio()->loader : (lnkDocument ? lnkDocument->document()->loader : 0)); if (lnkVideo) {
if (loader) loader->cancel(); lnkVideo->video()->cancel();
} else if (lnkAudio) {
lnkAudio->audio()->cancel();
} else if (lnkDocument) {
lnkDocument->document()->cancel();
}
} }
void OverviewInner::showContextInFolder() { void OverviewInner::showContextInFolder() {

View File

@ -324,12 +324,8 @@ void PlayerWidget::preloadNext() {
if (next) { if (next) {
if (HistoryDocument *document = static_cast<HistoryDocument*>(next->getMedia())) { if (HistoryDocument *document = static_cast<HistoryDocument*>(next->getMedia())) {
DocumentData *d = document->getDocument(); DocumentData *d = document->getDocument();
if (d->location(true).isEmpty() && d->data.isEmpty()) { if (!d->loaded(true)) {
if (!d->loader) { DocumentOpenLink::doOpen(d, ActionOnLoadNone);
DocumentOpenLink::doOpen(d);
d->openOnSave = 0;
d->openOnSaveMsgId = FullMsgId();
}
} }
} }
} }
@ -648,12 +644,12 @@ void PlayerWidget::updateState(SongMsgId playing, AudioPlayerState playingState,
float64 progress = 0.; float64 progress = 0.;
int32 loaded; int32 loaded;
float64 loadProgress = 1.; float64 loadProgress = 1.;
if (duration || !_song || !_song.song || !_song.song->loader) { if (duration || !_song || !_song.song || !_song.song->loading()) {
time = (_down == OverPlayback) ? _time : formatDurationText(display); time = (_down == OverPlayback) ? _time : formatDurationText(display);
progress = duration ? snap(float64(position) / duration, 0., 1.) : 0.; progress = duration ? snap(float64(position) / duration, 0., 1.) : 0.;
loaded = duration ? _song.song->size : 0; loaded = duration ? _song.song->size : 0;
} else { } else {
loaded = _song.song->loader ? _song.song->loader->currentOffset() : 0; loaded = _song.song->loading() ? _song.song->loadOffset() : 0;
time = formatDownloadText(loaded, _song.song->size); time = formatDownloadText(loaded, _song.song->size);
loadProgress = snap(float64(loaded) / qMax(_song.song->size, 1), 0., 1.); loadProgress = snap(float64(loaded) / qMax(_song.song->size, 1), 0., 1.);
} }

View File

@ -195,7 +195,7 @@ DeclareRefSetting(EmojiColorVariants, EmojiVariants);
RecentEmojiPack &cGetRecentEmojis(); RecentEmojiPack &cGetRecentEmojis();
struct DocumentData; class DocumentData;
typedef QVector<DocumentData*> StickerPack; typedef QVector<DocumentData*> StickerPack;
DeclareSetting(int32, StickersHash); DeclareSetting(int32, StickersHash);

View File

@ -176,12 +176,6 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : TWidget(parent)
, _autoDownload(this, lang(lng_media_auto_settings)) , _autoDownload(this, lang(lng_media_auto_settings))
// chat background
, _backFromGallery(this, lang(lng_settings_bg_from_gallery))
, _backFromFile(this, lang(lng_settings_bg_from_file))
, _tileBackground(this, lang(lng_settings_bg_tile), cTileBackground())
, _needBackgroundUpdate(false)
// local storage // local storage
, _localStorageClear(this, lang(lng_local_storage_clear)) , _localStorageClear(this, lang(lng_local_storage_clear))
, _localStorageHeight(1) , _localStorageHeight(1)
@ -189,6 +183,12 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : TWidget(parent)
, _storageClearedWidth(st::linkFont->width(lang(lng_local_storage_cleared))) , _storageClearedWidth(st::linkFont->width(lang(lng_local_storage_cleared)))
, _storageClearFailedWidth(st::linkFont->width(lang(lng_local_storage_clear_failed))) , _storageClearFailedWidth(st::linkFont->width(lang(lng_local_storage_clear_failed)))
// chat background
, _backFromGallery(this, lang(lng_settings_bg_from_gallery))
, _backFromFile(this, lang(lng_settings_bg_from_file))
, _tileBackground(this, lang(lng_settings_bg_tile), cTileBackground())
, _needBackgroundUpdate(false)
// advanced // advanced
, _passcodeEdit(this, lang(cHasPasscode() ? lng_passcode_change : lng_passcode_turn_on)) , _passcodeEdit(this, lang(cHasPasscode() ? lng_passcode_change : lng_passcode_turn_on))
, _passcodeTurnOff(this, lang(lng_passcode_turn_off)) , _passcodeTurnOff(this, lang(lng_passcode_turn_off))
@ -207,6 +207,8 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : TWidget(parent)
, _logOut(this, lang(lng_settings_logout), st::btnLogout) , _logOut(this, lang(lng_settings_logout), st::btnLogout)
, _supportGetRequest(0) { , _supportGetRequest(0) {
if (self()) { if (self()) {
self()->photo->load();
connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
connect(App::api(), SIGNAL(fullPeerUpdated(PeerData*)), this, SLOT(onFullPeerUpdated(PeerData*))); connect(App::api(), SIGNAL(fullPeerUpdated(PeerData*)), this, SLOT(onFullPeerUpdated(PeerData*)));
@ -294,13 +296,6 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : TWidget(parent)
connect(App::wnd(), SIGNAL(tempDirClearFailed(int)), this, SLOT(onTempDirClearFailed(int))); connect(App::wnd(), SIGNAL(tempDirClearFailed(int)), this, SLOT(onTempDirClearFailed(int)));
connect(&_autoDownload, SIGNAL(clicked()), this, SLOT(onAutoDownload())); connect(&_autoDownload, SIGNAL(clicked()), this, SLOT(onAutoDownload()));
// chat background
if (!cChatBackground()) App::initBackground();
updateChatBackground();
connect(&_backFromGallery, SIGNAL(clicked()), this, SLOT(onBackFromGallery()));
connect(&_backFromFile, SIGNAL(clicked()), this, SLOT(onBackFromFile()));
connect(&_tileBackground, SIGNAL(changed()), this, SLOT(onTileBackground()));
// local storage // local storage
connect(&_localStorageClear, SIGNAL(clicked()), this, SLOT(onLocalStorageClear())); connect(&_localStorageClear, SIGNAL(clicked()), this, SLOT(onLocalStorageClear()));
switch (App::wnd()->localStorageState()) { switch (App::wnd()->localStorageState()) {
@ -309,6 +304,13 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : TWidget(parent)
case Window::TempDirRemoving: _storageClearState = TempDirClearing; break; case Window::TempDirRemoving: _storageClearState = TempDirClearing; break;
} }
// chat background
if (!cChatBackground()) App::initBackground();
updateChatBackground();
connect(&_backFromGallery, SIGNAL(clicked()), this, SLOT(onBackFromGallery()));
connect(&_backFromFile, SIGNAL(clicked()), this, SLOT(onBackFromFile()));
connect(&_tileBackground, SIGNAL(changed()), this, SLOT(onTileBackground()));
// advanced // advanced
connect(&_passcodeEdit, SIGNAL(clicked()), this, SLOT(onPasscode())); connect(&_passcodeEdit, SIGNAL(clicked()), this, SLOT(onPasscode()));
connect(&_passcodeTurnOff, SIGNAL(clicked()), this, SLOT(onPasscodeOff())); connect(&_passcodeTurnOff, SIGNAL(clicked()), this, SLOT(onPasscodeOff()));
@ -553,45 +555,6 @@ void SettingsInner::paintEvent(QPaintEvent *e) {
top += st::setLittleSkip; top += st::setLittleSkip;
top += _autoDownload.height(); top += _autoDownload.height();
// chat background
p.setFont(st::setHeaderFont->f);
p.setPen(st::setHeaderColor->p);
p.drawText(_left + st::setHeaderLeft, top + st::setHeaderTop + st::setHeaderFont->ascent, lang(lng_settings_section_background));
top += st::setHeaderSkip;
if (animateBackground) {
const QPixmap &pix = App::main()->newBackgroundThumb()->pixBlurred(st::setBackgroundSize);
p.drawPixmap(_left, top, st::setBackgroundSize, st::setBackgroundSize, pix, 0, (pix.height() - st::setBackgroundSize) / 2, st::setBackgroundSize, st::setBackgroundSize);
uint64 dt = getms();
int32 cnt = int32(st::photoLoaderCnt), period = int32(st::photoLoaderPeriod), t = dt % period, delta = int32(st::photoLoaderDelta);
int32 x = _left + (st::setBackgroundSize - st::mediaviewLoader.width()) / 2;
int32 y = top + (st::setBackgroundSize - st::mediaviewLoader.height()) / 2;
p.fillRect(x, y, st::mediaviewLoader.width(), st::mediaviewLoader.height(), st::photoLoaderBg->b);
x += (st::mediaviewLoader.width() - cnt * st::mediaviewLoaderPoint.width() - (cnt - 1) * st::mediaviewLoaderSkip) / 2;
y += (st::mediaviewLoader.height() - st::mediaviewLoaderPoint.height()) / 2;
QColor c(st::white->c);
QBrush b(c);
for (int32 i = 0; i < cnt; ++i) {
t -= delta;
while (t < 0) t += period;
float64 alpha = (t >= st::photoLoaderDuration1 + st::photoLoaderDuration2) ? 0 : ((t > st::photoLoaderDuration1 ? ((st::photoLoaderDuration1 + st::photoLoaderDuration2 - t) / st::photoLoaderDuration2) : (t / st::photoLoaderDuration1)));
c.setAlphaF(st::photoLoaderAlphaMin + alpha * (1 - st::photoLoaderAlphaMin));
b.setColor(c);
p.fillRect(x + i * (st::mediaviewLoaderPoint.width() + st::mediaviewLoaderSkip), y, st::mediaviewLoaderPoint.width(), st::mediaviewLoaderPoint.height(), b);
}
QTimer::singleShot(AnimationTimerDelta, this, SLOT(updateBackgroundRect()));
} else {
p.drawPixmap(_left, top, _background);
}
top += st::setBackgroundSize;
top += st::setLittleSkip;
top += _tileBackground.height();
// local storage // local storage
p.setFont(st::setHeaderFont->f); p.setFont(st::setHeaderFont->f);
p.setPen(st::setHeaderColor->p); p.setPen(st::setHeaderColor->p);
@ -635,6 +598,45 @@ void SettingsInner::paintEvent(QPaintEvent *e) {
p.drawText(_left + st::setHeaderLeft, top + st::linkFont->ascent, lang(lng_settings_no_data_cached)); p.drawText(_left + st::setHeaderLeft, top + st::linkFont->ascent, lang(lng_settings_no_data_cached));
} }
top += _localStorageClear.height(); top += _localStorageClear.height();
// chat background
p.setFont(st::setHeaderFont->f);
p.setPen(st::setHeaderColor->p);
p.drawText(_left + st::setHeaderLeft, top + st::setHeaderTop + st::setHeaderFont->ascent, lang(lng_settings_section_background));
top += st::setHeaderSkip;
if (animateBackground) {
const QPixmap &pix = App::main()->newBackgroundThumb()->pixBlurred(st::setBackgroundSize);
p.drawPixmap(_left, top, st::setBackgroundSize, st::setBackgroundSize, pix, 0, (pix.height() - st::setBackgroundSize) / 2, st::setBackgroundSize, st::setBackgroundSize);
uint64 dt = getms();
int32 cnt = int32(st::photoLoaderCnt), period = int32(st::photoLoaderPeriod), t = dt % period, delta = int32(st::photoLoaderDelta);
int32 x = _left + (st::setBackgroundSize - st::mediaviewLoader.width()) / 2;
int32 y = top + (st::setBackgroundSize - st::mediaviewLoader.height()) / 2;
p.fillRect(x, y, st::mediaviewLoader.width(), st::mediaviewLoader.height(), st::photoLoaderBg->b);
x += (st::mediaviewLoader.width() - cnt * st::mediaviewLoaderPoint.width() - (cnt - 1) * st::mediaviewLoaderSkip) / 2;
y += (st::mediaviewLoader.height() - st::mediaviewLoaderPoint.height()) / 2;
QColor c(st::white->c);
QBrush b(c);
for (int32 i = 0; i < cnt; ++i) {
t -= delta;
while (t < 0) t += period;
float64 alpha = (t >= st::photoLoaderDuration1 + st::photoLoaderDuration2) ? 0 : ((t > st::photoLoaderDuration1 ? ((st::photoLoaderDuration1 + st::photoLoaderDuration2 - t) / st::photoLoaderDuration2) : (t / st::photoLoaderDuration1)));
c.setAlphaF(st::photoLoaderAlphaMin + alpha * (1 - st::photoLoaderAlphaMin));
b.setColor(c);
p.fillRect(x + i * (st::mediaviewLoaderPoint.width() + st::mediaviewLoaderSkip), y, st::mediaviewLoaderPoint.width(), st::mediaviewLoaderPoint.height(), b);
}
QTimer::singleShot(AnimationTimerDelta, this, SLOT(updateBackgroundRect()));
} else {
p.drawPixmap(_left, top, _background);
}
top += st::setBackgroundSize;
top += st::setLittleSkip;
top += _tileBackground.height();
} }
// advanced // advanced
@ -734,15 +736,6 @@ void SettingsInner::resizeEvent(QResizeEvent *e) {
top += st::setLittleSkip; top += st::setLittleSkip;
_autoDownload.move(_left + st::cbDefFlat.textLeft, top); top += _autoDownload.height(); _autoDownload.move(_left + st::cbDefFlat.textLeft, top); top += _autoDownload.height();
// chat background
top += st::setHeaderSkip;
_backFromGallery.move(_left + st::setBackgroundSize + st::setLittleSkip, top);
_backFromFile.move(_left + st::setBackgroundSize + st::setLittleSkip, top + _backFromGallery.height() + st::setLittleSkip);
top += st::setBackgroundSize;
top += st::setLittleSkip;
_tileBackground.move(_left, top); top += _tileBackground.height();
// local storage // local storage
_localStorageClear.move(_left + st::setWidth - _localStorageClear.width(), top + st::setHeaderTop + st::setHeaderFont->ascent - st::linkFont->ascent); _localStorageClear.move(_left + st::setWidth - _localStorageClear.width(), top + st::setHeaderTop + st::setHeaderFont->ascent - st::linkFont->ascent);
top += st::setHeaderSkip; top += st::setHeaderSkip;
@ -753,6 +746,15 @@ void SettingsInner::resizeEvent(QResizeEvent *e) {
_localStorageHeight = 1; _localStorageHeight = 1;
} }
top += _localStorageClear.height(); top += _localStorageClear.height();
// chat background
top += st::setHeaderSkip;
_backFromGallery.move(_left + st::setBackgroundSize + st::setLittleSkip, top);
_backFromFile.move(_left + st::setBackgroundSize + st::setLittleSkip, top + _backFromGallery.height() + st::setLittleSkip);
top += st::setBackgroundSize;
top += st::setLittleSkip;
_tileBackground.move(_left, top); top += _tileBackground.height();
} }
// advanced // advanced
@ -1079,6 +1081,13 @@ void SettingsInner::showAll() {
_autoDownload.hide(); _autoDownload.hide();
} }
// local storage
if (self() && _storageClearState == TempDirExists) {
_localStorageClear.show();
} else {
_localStorageClear.hide();
}
// chat background // chat background
if (self()) { if (self()) {
_backFromGallery.show(); _backFromGallery.show();
@ -1090,13 +1099,6 @@ void SettingsInner::showAll() {
_tileBackground.hide(); _tileBackground.hide();
} }
// local storage
if (self() && _storageClearState == TempDirExists) {
_localStorageClear.show();
} else {
_localStorageClear.hide();
}
// advanced // advanced
if (self()) { if (self()) {
_passcodeEdit.show(); _passcodeEdit.show();

View File

@ -262,18 +262,18 @@ private:
TempDirClearState _tempDirClearState; TempDirClearState _tempDirClearState;
LinkButton _autoDownload; LinkButton _autoDownload;
// chat background
QPixmap _background;
LinkButton _backFromGallery, _backFromFile;
FlatCheckbox _tileBackground;
bool _needBackgroundUpdate;
// local storage // local storage
LinkButton _localStorageClear; LinkButton _localStorageClear;
int32 _localStorageHeight; int32 _localStorageHeight;
int32 _storageClearingWidth, _storageClearedWidth, _storageClearFailedWidth; int32 _storageClearingWidth, _storageClearedWidth, _storageClearFailedWidth;
TempDirClearState _storageClearState; TempDirClearState _storageClearState;
// chat background
QPixmap _background;
LinkButton _backFromGallery, _backFromFile;
FlatCheckbox _tileBackground;
bool _needBackgroundUpdate;
// advanced // advanced
LinkButton _passcodeEdit, _passcodeTurnOff, _autoLock; LinkButton _passcodeEdit, _passcodeTurnOff, _autoLock;
QString _autoLockText; QString _autoLockText;

File diff suppressed because it is too large Load Diff

View File

@ -340,7 +340,7 @@ enum UserBlockedStatus {
UserIsNotBlocked, UserIsNotBlocked,
}; };
struct PhotoData; class PhotoData;
class UserData : public PeerData { class UserData : public PeerData {
public: public:
@ -720,30 +720,33 @@ inline int32 newMessageFlags(PeerData *p) {
return p->isSelf() ? 0 : (((p->isChat() || (p->isUser() && !p->asUser()->botInfo)) ? MTPDmessage::flag_unread : 0) | MTPDmessage::flag_out); return p->isSelf() ? 0 : (((p->isChat() || (p->isUser() && !p->asUser()->botInfo)) ? MTPDmessage::flag_unread : 0) | MTPDmessage::flag_out);
} }
enum ActionOnLoad {
ActionOnLoadNone,
ActionOnLoadOpen,
ActionOnLoadOpenWith,
ActionOnLoadPlayInline
};
typedef QMap<char, QPixmap> PreparedPhotoThumbs; typedef QMap<char, QPixmap> PreparedPhotoThumbs;
struct PhotoData { class PhotoData {
PhotoData(const PhotoId &id, const uint64 &access = 0, int32 date = 0, const ImagePtr &thumb = ImagePtr(), const ImagePtr &medium = ImagePtr(), const ImagePtr &full = ImagePtr()) : public:
id(id), access(access), date(date), thumb(thumb), medium(medium), full(full), peer(0) { PhotoData(const PhotoId &id, const uint64 &access = 0, int32 date = 0, const ImagePtr &thumb = ImagePtr(), const ImagePtr &medium = ImagePtr(), const ImagePtr &full = ImagePtr());
}
void forget() { void automaticLoad(const HistoryItem *item);
thumb->forget();
replyPreview->forget(); bool loaded() const;
medium->forget(); bool loading() const;
full->forget(); bool displayLoading() const;
} void cancel();
ImagePtr makeReplyPreview() { float64 progress() const;
if (replyPreview->isNull() && !thumb->isNull()) { int32 loadOffset() const;
if (thumb->loaded()) { bool uploading() const;
int w = thumb->width(), h = thumb->height();
if (w <= 0) w = 1; void forget();
if (h <= 0) h = 1; ImagePtr makeReplyPreview();
replyPreview = ImagePtr(w > h ? thumb->pix(w * st::msgReplyBarSize.height() / h, st::msgReplyBarSize.height()) : thumb->pix(st::msgReplyBarSize.height()), "PNG");
} else { ~PhotoData();
thumb->load();
}
}
return replyPreview;
}
PhotoId id; PhotoId id;
uint64 access; uint64 access;
int32 date; int32 date;
@ -754,17 +757,22 @@ struct PhotoData {
PeerData *peer; // for chat and channel photos connection PeerData *peer; // for chat and channel photos connection
// geo, caption // geo, caption
int32 cachew; struct UploadingData {
QPixmap cache; UploadingData(int32 size) : offset(0), size(size) {
}
int32 offset, size;
};
UploadingData *uploadingData;
// int32 cachew;
// QPixmap cache;
}; };
class PhotoLink : public ITextLink { class PhotoLink : public ITextLink {
TEXT_LINK_CLASS(PhotoLink) TEXT_LINK_CLASS(PhotoLink)
public: public:
PhotoLink(PhotoData *photo) : _photo(photo), _peer(0) { PhotoLink(PhotoData *photo, PeerData *peer = 0) : _photo(photo), _peer(peer) {
}
PhotoLink(PhotoData *photo, PeerData *peer) : _photo(photo), _peer(peer) {
} }
void onClick(Qt::MouseButton button) const; void onClick(Qt::MouseButton button) const;
PhotoData *photo() const { PhotoData *photo() const {
@ -777,6 +785,17 @@ public:
private: private:
PhotoData *_photo; PhotoData *_photo;
PeerData *_peer; PeerData *_peer;
};
class PhotoCancelLink : public PhotoLink {
TEXT_LINK_CLASS(PhotoCancelLink)
public:
PhotoCancelLink(PhotoData *photo, PeerData *peer = 0) : PhotoLink(photo, peer) {
}
void onClick(Qt::MouseButton button) const;
}; };
enum FileStatus { enum FileStatus {
@ -786,52 +805,34 @@ enum FileStatus {
FileReady = 1, FileReady = 1,
}; };
struct VideoData { class VideoData {
public:
VideoData(const VideoId &id, const uint64 &access = 0, int32 date = 0, int32 duration = 0, int32 w = 0, int32 h = 0, const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0); VideoData(const VideoId &id, const uint64 &access = 0, int32 date = 0, int32 duration = 0, int32 w = 0, int32 h = 0, const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0);
void forget() { void automaticLoad(const HistoryItem *item) {
thumb->forget();
replyPreview->forget();
} }
void save(const QString &toFile); bool loaded(bool check = false) const;
bool loading() const;
bool displayLoading() const;
void save(const QString &toFile, ActionOnLoad action = ActionOnLoadNone, const FullMsgId &actionMsgId = FullMsgId(), LoadFromCloudSetting fromCloud = LoadFromCloudOrLocal, bool autoLoading = false);
void cancel();
float64 progress() const;
int32 loadOffset() const;
bool uploading() const;
void cancel(bool beforeDownload = false) { QString already(bool check = false) const;
mtpFileLoader *l = loader; QByteArray data() const;
loader = 0; const FileLocation &location(bool check = false) const;
if (l) { void setLocation(const FileLocation &loc);
l->cancel();
l->deleteLater();
l->rpcInvalidate();
notifyLayoutChanged(); bool saveToCache() const {
} return false;
_location = FileLocation();
if (!beforeDownload) {
openOnSave = 0;
openOnSaveMsgId = FullMsgId();
}
} }
void finish() { void performActionOnLoad();
if (loader->done()) {
_location = FileLocation(mtpToStorageType(loader->fileType()), loader->fileName());
}
loader->deleteLater();
loader->rpcInvalidate();
loader = 0;
notifyLayoutChanged(); void forget();
}
void notifyLayoutChanged() const;
QString already(bool check = false);
const FileLocation &location(bool check = false);
float64 progress() const {
return loader ? loader->currentProgress() : ((status == FileDownloadFailed || _location.name().isEmpty()) ? 0 : 1);
}
VideoId id; VideoId id;
uint64 access; uint64 access;
@ -845,14 +846,15 @@ struct VideoData {
FileStatus status; FileStatus status;
int32 uploadOffset; int32 uploadOffset;
mtpTypeId fileType;
int32 openOnSave;
FullMsgId openOnSaveMsgId;
mtpFileLoader *loader;
private: private:
FileLocation _location; FileLocation _location;
ActionOnLoad _actionOnLoad;
FullMsgId _actionOnLoadMsgId;
mutable mtpFileLoader *_loader;
void notifyLayoutChanged() const;
}; };
class VideoLink : public ITextLink { class VideoLink : public ITextLink {
@ -867,6 +869,7 @@ public:
private: private:
VideoData *_video; VideoData *_video;
}; };
class VideoSaveLink : public VideoLink { class VideoSaveLink : public VideoLink {
@ -886,6 +889,7 @@ public:
VideoOpenLink(VideoData *video) : VideoLink(video) { VideoOpenLink(VideoData *video) : VideoLink(video) {
} }
void onClick(Qt::MouseButton button) const; void onClick(Qt::MouseButton button) const;
}; };
class VideoCancelLink : public VideoLink { class VideoCancelLink : public VideoLink {
@ -895,63 +899,36 @@ public:
VideoCancelLink(VideoData *video) : VideoLink(video) { VideoCancelLink(VideoData *video) : VideoLink(video) {
} }
void onClick(Qt::MouseButton button) const; void onClick(Qt::MouseButton button) const;
}; };
struct AudioData { class AudioData {
public:
AudioData(const AudioId &id, const uint64 &access = 0, int32 date = 0, const QString &mime = QString(), int32 duration = 0, int32 dc = 0, int32 size = 0); AudioData(const AudioId &id, const uint64 &access = 0, int32 date = 0, const QString &mime = QString(), int32 duration = 0, int32 dc = 0, int32 size = 0);
void forget() { void automaticLoad(const HistoryItem *item); // auto load voice message
}
bool prepareAutoLoader(const HistoryItem *item, bool force = false); bool loaded(bool check = false) const;
void save(const QString &toFile); bool loading() const;
bool displayLoading() const;
void save(const QString &toFile, ActionOnLoad action = ActionOnLoadNone, const FullMsgId &actionMsgId = FullMsgId(), LoadFromCloudSetting fromCloud = LoadFromCloudOrLocal, bool autoLoading = false);
void cancel();
float64 progress() const;
int32 loadOffset() const;
bool uploading() const;
void cancel(bool beforeDownload = false) { QString already(bool check = false) const;
mtpFileLoader *l = loader; QByteArray data() const;
loader = 0; const FileLocation &location(bool check = false) const;
if (l) { void setLocation(const FileLocation &loc);
l->cancel();
l->deleteLater();
l->rpcInvalidate();
notifyLayoutChanged(); bool saveToCache() const;
}
_location = FileLocation();
if (!beforeDownload) {
openOnSave = 0;
openOnSaveMsgId = FullMsgId();
}
}
void finish() { void performActionOnLoad();
if (loader->done()) {
_location = FileLocation(mtpToStorageType(loader->fileType()), loader->fileName());
data = loader->bytes();
}
loader->deleteLater();
loader->rpcInvalidate();
loader = 0;
notifyLayoutChanged(); void forget();
} void setData(const QByteArray &data) {
void notifyLayoutChanged() const; _data = data;
QString already(bool check = false);
const FileLocation &location(bool check = false);
void setLocation(const FileLocation &loc) {
if (loc.check()) {
_location = loc;
}
}
bool loaded(bool check = false) {
return !data.isEmpty() || !already(check).isEmpty();
}
bool loadingStarted() {
return loader && loader->started();
}
float64 progress() const {
return loader ? loader->currentProgress() : ((status == FileDownloadFailed || (_location.name().isEmpty() && data.isEmpty())) ? 0 : 1);
} }
AudioId id; AudioId id;
@ -965,14 +942,17 @@ struct AudioData {
FileStatus status; FileStatus status;
int32 uploadOffset; int32 uploadOffset;
int32 openOnSave;
FullMsgId openOnSaveMsgId;
mtpFileLoader *loader;
QByteArray data;
int32 md5[8]; int32 md5[8];
private: private:
FileLocation _location; FileLocation _location;
QByteArray _data;
ActionOnLoad _actionOnLoad;
FullMsgId _actionOnLoadMsgId;
mutable mtpFileLoader *_loader;
void notifyLayoutChanged() const;
}; };
@ -988,7 +968,9 @@ struct AudioMsgId {
} }
AudioData *audio; AudioData *audio;
FullMsgId msgId; FullMsgId msgId;
}; };
inline bool operator<(const AudioMsgId &a, const AudioMsgId &b) { inline bool operator<(const AudioMsgId &a, const AudioMsgId &b) {
return quintptr(a.audio) < quintptr(b.audio) || (quintptr(a.audio) == quintptr(b.audio) && a.msgId < b.msgId); return quintptr(a.audio) < quintptr(b.audio) || (quintptr(a.audio) == quintptr(b.audio) && a.msgId < b.msgId);
} }
@ -1011,6 +993,7 @@ public:
private: private:
AudioData *_audio; AudioData *_audio;
}; };
class AudioSaveLink : public AudioLink { class AudioSaveLink : public AudioLink {
@ -1021,6 +1004,7 @@ public:
} }
static void doSave(AudioData *audio, bool forceSavingAs = false); static void doSave(AudioData *audio, bool forceSavingAs = false);
void onClick(Qt::MouseButton button) const; void onClick(Qt::MouseButton button) const;
}; };
class AudioOpenLink : public AudioLink { class AudioOpenLink : public AudioLink {
@ -1030,6 +1014,7 @@ public:
AudioOpenLink(AudioData *audio) : AudioLink(audio) { AudioOpenLink(AudioData *audio) : AudioLink(audio) {
} }
void onClick(Qt::MouseButton button) const; void onClick(Qt::MouseButton button) const;
}; };
class AudioCancelLink : public AudioLink { class AudioCancelLink : public AudioLink {
@ -1039,6 +1024,7 @@ public:
AudioCancelLink(AudioData *audio) : AudioLink(audio) { AudioCancelLink(AudioData *audio) : AudioLink(audio) {
} }
void onClick(Qt::MouseButton button) const; void onClick(Qt::MouseButton button) const;
}; };
enum DocumentType { enum DocumentType {
@ -1062,6 +1048,7 @@ struct StickerData : public DocumentAdditionalData {
bool setInstalled() const; bool setInstalled() const;
StorageImageLocation loc; // doc thumb location StorageImageLocation loc; // doc thumb location
}; };
struct SongData : public DocumentAdditionalData { struct SongData : public DocumentAdditionalData {
@ -1069,93 +1056,63 @@ struct SongData : public DocumentAdditionalData {
} }
int32 duration; int32 duration;
QString title, performer; QString title, performer;
}; };
bool fileIsImage(const QString &name, const QString &mime); bool fileIsImage(const QString &name, const QString &mime);
struct DocumentData { class DocumentData {
public:
DocumentData(const DocumentId &id, const uint64 &access = 0, int32 date = 0, const QVector<MTPDocumentAttribute> &attributes = QVector<MTPDocumentAttribute>(), const QString &mime = QString(), const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0); DocumentData(const DocumentId &id, const uint64 &access = 0, int32 date = 0, const QVector<MTPDocumentAttribute> &attributes = QVector<MTPDocumentAttribute>(), const QString &mime = QString(), const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0);
void setattributes(const QVector<MTPDocumentAttribute> &attributes); void setattributes(const QVector<MTPDocumentAttribute> &attributes);
void forget() { void automaticLoad(const HistoryItem *item); // auto load sticker or video
thumb->forget();
if (sticker()) sticker()->img->forget();
replyPreview->forget();
}
ImagePtr makeReplyPreview() {
if (replyPreview->isNull() && !thumb->isNull()) {
if (thumb->loaded()) {
int w = thumb->width(), h = thumb->height();
if (w <= 0) w = 1;
if (h <= 0) h = 1;
replyPreview = ImagePtr(w > h ? thumb->pix(w * st::msgReplyBarSize.height() / h, st::msgReplyBarSize.height()) : thumb->pix(st::msgReplyBarSize.height()), "PNG");
} else {
thumb->load();
}
}
return replyPreview;
}
void save(const QString &toFile); bool loaded(bool check = false) const;
bool loading() const;
bool displayLoading() const;
void save(const QString &toFile, ActionOnLoad action = ActionOnLoadNone, const FullMsgId &actionMsgId = FullMsgId(), LoadFromCloudSetting fromCloud = LoadFromCloudOrLocal, bool autoLoading = false);
void cancel();
float64 progress() const;
int32 loadOffset() const;
bool uploading() const;
void cancel(bool beforeDownload = false) { QString already(bool check = false) const;
mtpFileLoader *l = loader; QByteArray data() const;
loader = 0; const FileLocation &location(bool check = false) const;
if (l) { void setLocation(const FileLocation &loc);
l->cancel();
l->deleteLater();
l->rpcInvalidate();
notifyLayoutChanged(); bool saveToCache() const;
}
_location = FileLocation();
if (!beforeDownload) {
openOnSave = 0;
openOnSaveMsgId = FullMsgId();
}
}
void finish() { void performActionOnLoad();
if (loader->done()) {
_location = FileLocation(mtpToStorageType(loader->fileType()), loader->fileName());
data = loader->bytes();
if (sticker() && !loader->imagePixmap().isNull()) {
sticker()->img = ImagePtr(data, loader->imageFormat(), loader->imagePixmap());
}
}
loader->deleteLater();
loader->rpcInvalidate();
loader = 0;
notifyLayoutChanged(); void forget();
} ImagePtr makeReplyPreview();
void notifyLayoutChanged() const;
~DocumentData() {
delete _additional;
}
QString already(bool check = false);
const FileLocation &location(bool check = false);
void setLocation(const FileLocation &loc) {
if (loc.check()) {
_location = loc;
}
}
bool loaded(bool check = false) {
return !data.isEmpty() || !already(check).isEmpty();
}
bool loadingStarted() {
return loader && loader->started();
}
bool prepareAutoLoader(const HistoryItem *item, bool force = false);
StickerData *sticker() { StickerData *sticker() {
return (type == StickerDocument) ? static_cast<StickerData*>(_additional) : 0; return (type == StickerDocument) ? static_cast<StickerData*>(_additional) : 0;
} }
void checkSticker() {
StickerData *s = sticker();
if (!s) return;
automaticLoad(0);
if (s->img->isNull() && loaded()) {
if (_data.isEmpty()) {
const FileLocation &location(location(true));
if (location.accessEnable()) {
s->img = ImagePtr(location.name());
location.accessDisable();
}
} else {
s->img = ImagePtr(_data);
}
}
}
SongData *song() { SongData *song() {
return (type == SongDocument) ? static_cast<SongData*>(_additional) : 0; return (type == SongDocument) ? static_cast<SongData*>(_additional) : 0;
} }
bool isAnimation() { bool isAnimation() const {
return (type == AnimatedDocument) || !mime.compare(qstr("image/gif"), Qt::CaseInsensitive); return (type == AnimatedDocument) || !mime.compare(qstr("image/gif"), Qt::CaseInsensitive);
} }
bool isImage() const { bool isImage() const {
@ -1163,9 +1120,7 @@ struct DocumentData {
} }
void recountIsImage(); void recountIsImage();
float64 progress() const { ~DocumentData();
return loader ? loader->currentProgress() : ((status == FileDownloadFailed || (_location.name().isEmpty() && data.isEmpty())) ? 0 : 1);
}
DocumentId id; DocumentId id;
DocumentType type; DocumentType type;
@ -1180,20 +1135,21 @@ struct DocumentData {
FileStatus status; FileStatus status;
int32 uploadOffset; int32 uploadOffset;
int32 openOnSave;
FullMsgId openOnSaveMsgId;
mtpFileLoader *loader;
QByteArray data;
DocumentAdditionalData *_additional;
int32 md5[8]; int32 md5[8];
private: private:
FileLocation _location; FileLocation _location;
QByteArray _data;
DocumentAdditionalData *_additional;
bool _isImage; bool _isImage;
ActionOnLoad _actionOnLoad;
FullMsgId _actionOnLoadMsgId;
mutable mtpFileLoader *_loader;
void notifyLayoutChanged() const;
}; };
struct SongMsgId { struct SongMsgId {
@ -1208,6 +1164,7 @@ struct SongMsgId {
} }
DocumentData *song; DocumentData *song;
FullMsgId msgId; FullMsgId msgId;
}; };
inline bool operator<(const SongMsgId &a, const SongMsgId &b) { inline bool operator<(const SongMsgId &a, const SongMsgId &b) {
return quintptr(a.song) < quintptr(b.song) || (quintptr(a.song) == quintptr(b.song) && a.msgId < b.msgId); return quintptr(a.song) < quintptr(b.song) || (quintptr(a.song) == quintptr(b.song) && a.msgId < b.msgId);
@ -1231,6 +1188,7 @@ public:
private: private:
DocumentData *_document; DocumentData *_document;
}; };
class DocumentSaveLink : public DocumentLink { class DocumentSaveLink : public DocumentLink {
@ -1241,6 +1199,7 @@ public:
} }
static void doSave(DocumentData *document, bool forceSavingAs = false); static void doSave(DocumentData *document, bool forceSavingAs = false);
void onClick(Qt::MouseButton button) const; void onClick(Qt::MouseButton button) const;
}; };
class DocumentOpenLink : public DocumentLink { class DocumentOpenLink : public DocumentLink {
@ -1249,8 +1208,9 @@ class DocumentOpenLink : public DocumentLink {
public: public:
DocumentOpenLink(DocumentData *document) : DocumentLink(document) { DocumentOpenLink(DocumentData *document) : DocumentLink(document) {
} }
static void doOpen(DocumentData *document, int32 openOnSave = 1); static void doOpen(DocumentData *document, ActionOnLoad action = ActionOnLoadOpen);
void onClick(Qt::MouseButton button) const; void onClick(Qt::MouseButton button) const;
}; };
class GifOpenLink : public DocumentOpenLink { class GifOpenLink : public DocumentOpenLink {
@ -1261,6 +1221,7 @@ public:
} }
static void doOpen(DocumentData *document); static void doOpen(DocumentData *document);
void onClick(Qt::MouseButton button) const; void onClick(Qt::MouseButton button) const;
}; };
class DocumentCancelLink : public DocumentLink { class DocumentCancelLink : public DocumentLink {
@ -1270,6 +1231,7 @@ public:
DocumentCancelLink(DocumentData *document) : DocumentLink(document) { DocumentCancelLink(DocumentData *document) : DocumentLink(document) {
} }
void onClick(Qt::MouseButton button) const; void onClick(Qt::MouseButton button) const;
}; };
enum WebPageType { enum WebPageType {
@ -1300,6 +1262,7 @@ struct WebPageData {
PhotoData *photo; PhotoData *photo;
DocumentData *doc; DocumentData *doc;
int32 pendingTill; int32 pendingTill;
}; };
QString saveFileName(const QString &title, const QString &filter, const QString &prefix, QString name, bool savingAs, const QDir &dir = QDir()); QString saveFileName(const QString &title, const QString &filter, const QString &prefix, QString name, bool savingAs, const QDir &dir = QDir());

View File

@ -38,6 +38,11 @@ typedef quint64 uint64;
static const int32 ScrollMax = INT_MAX; static const int32 ScrollMax = INT_MAX;
static uint64 SharedMemoryLocation0 = 0x00;
static uint64 SharedMemoryLocation1 = 0x01;
static uint64 SharedMemoryLocation2 = 0x02;
static uint64 SharedMemoryLocation3 = 0x03;
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
typedef float float32; typedef float float32;
typedef double float64; typedef double float64;