mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 10:11:41 -05:00
upload radial progress and upload cancel done, photo / file / audio autodownload settings respected
This commit is contained in:
parent
7c7d517b34
commit
4ed2d75c74
32 changed files with 2011 additions and 1558 deletions
|
@ -593,6 +593,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
"lng_emoji_category7" = "Symbols & Flags";
|
||||
|
||||
"lng_switch_stickers" = "Stickers";
|
||||
"lng_switch_stickers_gifs" = "GIFs & Stickers";
|
||||
"lng_switch_emoji" = "Emoji";
|
||||
|
||||
"lng_box_remove" = "Remove";
|
||||
|
|
|
@ -1176,7 +1176,7 @@ namespace App {
|
|||
case 'm': newThumbLevel = 2; newMediumLevel = 0; newFullLevel = 3; break; // box 320x320
|
||||
case 'x': newThumbLevel = 5; newMediumLevel = 3; newFullLevel = 1; break; // box 800x800
|
||||
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 'b': newThumbLevel = 3; newMediumLevel = 1; newFullLevel = 7; break; // crop 320x320
|
||||
case 'c': newThumbLevel = 4; newMediumLevel = 2; newFullLevel = 6; break; // crop 640x640
|
||||
|
@ -1431,6 +1431,8 @@ namespace App {
|
|||
photosData.erase(i);
|
||||
}
|
||||
convert->id = photo;
|
||||
delete convert->uploadingData;
|
||||
convert->uploadingData = 0;
|
||||
}
|
||||
convert->access = access;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -455,7 +455,7 @@ void AudioPlayer::play(const AudioMsgId &audio, int64 position) {
|
|||
}
|
||||
current->audio = audio;
|
||||
current->file = audio.audio->location(true);
|
||||
current->data = audio.audio->data;
|
||||
current->data = audio.audio->data();
|
||||
if (current->file.isEmpty() && current->data.isEmpty()) {
|
||||
setStoppedState(current, AudioPlayerStoppedAtError);
|
||||
onError(audio);
|
||||
|
@ -499,14 +499,11 @@ void AudioPlayer::play(const SongMsgId &song, int64 position) {
|
|||
}
|
||||
current->song = song;
|
||||
current->file = song.song->location(true);
|
||||
current->data = song.song->data;
|
||||
current->data = song.song->data();
|
||||
if (current->file.isEmpty() && current->data.isEmpty()) {
|
||||
setStoppedState(current);
|
||||
if (!song.song->loader) {
|
||||
if (!song.song->loading()) {
|
||||
DocumentOpenLink::doOpen(song.song);
|
||||
song.song->openOnSave = 0;
|
||||
song.song->openOnSaveMsgId = FullMsgId();
|
||||
if (song.song->loader) song.song->loader->start(true, true);
|
||||
}
|
||||
} else {
|
||||
current->state = fadedStart ? AudioPlayerStarting : AudioPlayerPlaying;
|
||||
|
|
|
@ -147,16 +147,14 @@ void StickerSetInner::paintEvent(QPaintEvent *e) {
|
|||
if (goodThumb) {
|
||||
doc->thumb->load();
|
||||
} else {
|
||||
bool already = !doc->already().isEmpty(), hasdata = !doc->data.isEmpty();
|
||||
if (!already && !hasdata && !doc->loader && doc->status == FileReady) {
|
||||
doc->openOnSave = 0;
|
||||
doc->save(QString());
|
||||
if (doc->status == FileReady) {
|
||||
doc->automaticLoad(0);
|
||||
}
|
||||
if (doc->sticker()->img->isNull() && (already || hasdata)) {
|
||||
if (already) {
|
||||
if (doc->sticker()->img->isNull() && doc->loaded() && doc->loaded(true)) {
|
||||
if (doc->data().isEmpty()) {
|
||||
doc->sticker()->img = ImagePtr(doc->already());
|
||||
} else {
|
||||
doc->sticker()->img = ImagePtr(doc->data);
|
||||
doc->sticker()->img = ImagePtr(doc->data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1331,18 +1331,7 @@ void StickerPanInner::paintEvent(QPaintEvent *e) {
|
|||
if (goodThumb) {
|
||||
sticker->thumb->load();
|
||||
} else {
|
||||
bool already = !sticker->already().isEmpty(), hasdata = !sticker->data.isEmpty();
|
||||
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);
|
||||
}
|
||||
}
|
||||
sticker->checkSticker();
|
||||
}
|
||||
|
||||
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) {
|
||||
sticker->thumb->load();
|
||||
} else {
|
||||
bool already = !sticker->already().isEmpty(), hasdata = !sticker->data.isEmpty();
|
||||
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);
|
||||
// }
|
||||
//}
|
||||
sticker->automaticLoad(0);
|
||||
}
|
||||
}
|
||||
if (k > StickerPanPerRow * (StickerPanPerRow + 1)) break;
|
||||
|
|
|
@ -154,9 +154,7 @@ namespace Notify {
|
|||
if (HistoryMedia *media = item->getMedia()) {
|
||||
media->stopInline(item);
|
||||
if (DocumentData *document = media->getDocument()) { // forget data from memory
|
||||
if (!document->data.isEmpty() && document->prepareAutoLoader(item)) {
|
||||
document->data.clear();
|
||||
}
|
||||
document->forget();
|
||||
}
|
||||
stopped = true;
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ void FileUploader::uploadMedia(const FullMsgId &msgId, const ReadyLocalMedia &me
|
|||
} else if (media.type == PrepareAudio) {
|
||||
AudioData *audio = App::feedAudio(media.audio);
|
||||
audio->status = FileUploading;
|
||||
audio->data = media.data;
|
||||
audio->setData(media.data);
|
||||
}
|
||||
queue.insert(msgId, File(media));
|
||||
sendNext();
|
||||
|
@ -54,7 +54,8 @@ void FileUploader::uploadMedia(const FullMsgId &msgId, const ReadyLocalMedia &me
|
|||
|
||||
void FileUploader::upload(const FullMsgId &msgId, const FileLoadResultPtr &file) {
|
||||
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) {
|
||||
DocumentData *document;
|
||||
if (file->thumb.isNull()) {
|
||||
|
@ -69,7 +70,7 @@ void FileUploader::upload(const FullMsgId &msgId, const FileLoadResultPtr &file)
|
|||
} else if (file->type == PrepareAudio) {
|
||||
AudioData *audio = App::feedAudio(file->audio);
|
||||
audio->status = FileUploading;
|
||||
audio->data = file->content;
|
||||
audio->setData(file->content);
|
||||
}
|
||||
queue.insert(msgId, File(file));
|
||||
sendNext();
|
||||
|
@ -115,7 +116,7 @@ void FileUploader::killSessions() {
|
|||
}
|
||||
|
||||
void FileUploader::sendNext() {
|
||||
if (sentSize >= MaxUploadFileParallelSize) return;
|
||||
if (sentSize >= MaxUploadFileParallelSize || _paused.msg) return;
|
||||
|
||||
bool killing = killSessionsTimer.isActive();
|
||||
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) {
|
||||
}
|
||||
|
||||
|
@ -274,21 +284,28 @@ void FileUploader::partLoaded(const MTPBool &result, mtpRequestId requestId) {
|
|||
int32 dc = dcIt.value();
|
||||
dcMap.erase(dcIt);
|
||||
|
||||
int32 sentPartSize = 0;
|
||||
Queue::const_iterator k = queue.constFind(uploading);
|
||||
if (i != requestsSent.cend()) {
|
||||
sentSize -= i.value().size();
|
||||
sentSizes[dc] -= i.value().size();
|
||||
sentPartSize = i.value().size();
|
||||
requestsSent.erase(i);
|
||||
} else {
|
||||
sentSize -= k->docPartSize;
|
||||
sentSizes[dc] -= k->docPartSize;
|
||||
sentPartSize = k->docPartSize;
|
||||
docRequestsSent.erase(j);
|
||||
}
|
||||
sentSize -= sentPartSize;
|
||||
sentSizes[dc] -= sentPartSize;
|
||||
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());
|
||||
} else if (k->type() == PrepareDocument) {
|
||||
DocumentData *doc = App::document(k->id());
|
||||
if (doc->status == FileUploading) {
|
||||
if (doc->uploading()) {
|
||||
doc->uploadOffset = (k->docSentParts - docRequestsSent.size()) * k->docPartSize;
|
||||
if (doc->uploadOffset > doc->size) {
|
||||
doc->uploadOffset = doc->size;
|
||||
|
@ -297,7 +314,7 @@ void FileUploader::partLoaded(const MTPBool &result, mtpRequestId requestId) {
|
|||
emit documentProgress(k.key());
|
||||
} else if (k->type() == PrepareAudio) {
|
||||
AudioData *audio = App::audio(k->id());
|
||||
if (audio->status == FileUploading) {
|
||||
if (audio->uploading()) {
|
||||
audio->uploadOffset = (k->docSentParts - docRequestsSent.size()) * k->docPartSize;
|
||||
if (audio->uploadOffset > audio->size) {
|
||||
audio->uploadOffset = audio->size;
|
||||
|
|
|
@ -35,12 +35,14 @@ public:
|
|||
int32 fullSize(const FullMsgId &msgId) const;
|
||||
|
||||
void cancel(const FullMsgId &msgId);
|
||||
void pause(const FullMsgId &msgId);
|
||||
void confirm(const FullMsgId &msgId);
|
||||
|
||||
void clear();
|
||||
|
||||
public slots:
|
||||
|
||||
void unpause();
|
||||
void sendNext();
|
||||
void killSessions();
|
||||
|
||||
|
@ -101,6 +103,7 @@ private:
|
|||
FileLoadResultPtr file;
|
||||
ReadyLocalMedia media;
|
||||
int32 partsCount;
|
||||
mutable int32 fileSentSize;
|
||||
|
||||
uint64 id() const {
|
||||
return file ? file->id : media.id;
|
||||
|
@ -136,7 +139,7 @@ private:
|
|||
uint32 sentSize;
|
||||
uint32 sentSizes[MTPUploadSessionsCount];
|
||||
|
||||
FullMsgId uploading;
|
||||
FullMsgId uploading, _paused;
|
||||
Queue queue;
|
||||
Queue uploaded;
|
||||
QTimer nextTimer, killSessionsTimer;
|
||||
|
|
|
@ -619,97 +619,165 @@ int64 imageCacheSize() {
|
|||
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);
|
||||
if (location.dc) {
|
||||
Local::writeImage(storageKey(location.dc, location.volume, location.local), StorageImageSaved(mtpToStorageType(mtpc_storage_filePartial), bytes));
|
||||
if (!_location.isNull()) {
|
||||
Local::writeImage(storageKey(_location), StorageImageSaved(mtpToStorageType(mtpc_storage_filePartial), bytes));
|
||||
}
|
||||
}
|
||||
|
||||
const QPixmap &StorageImage::pixData() const {
|
||||
return data;
|
||||
return _data;
|
||||
}
|
||||
|
||||
int32 StorageImage::width() const {
|
||||
return w;
|
||||
return _location.width();
|
||||
}
|
||||
|
||||
int32 StorageImage::height() const {
|
||||
return h;
|
||||
return _location.height();
|
||||
}
|
||||
|
||||
bool StorageImage::check() const {
|
||||
if (loader->done()) {
|
||||
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;
|
||||
}
|
||||
void StorageImage::checkload() const {
|
||||
if (!amLoading() || !_loader->done()) return;
|
||||
|
||||
w = data.width();
|
||||
h = data.height();
|
||||
invalidateSizeCache();
|
||||
loader->deleteLater();
|
||||
loader->rpcInvalidate();
|
||||
loader = 0;
|
||||
|
||||
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;
|
||||
QPixmap data = _loader->imagePixmap();
|
||||
if (data.isNull()) {
|
||||
_loader->deleteLater();
|
||||
_loader->rpcInvalidate();
|
||||
_loader = CancelledFileLoader;
|
||||
return;
|
||||
}
|
||||
|
||||
w = data.width();
|
||||
h = data.height();
|
||||
if (!_data.isNull()) {
|
||||
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();
|
||||
if (loader) {
|
||||
loader->deleteLater();
|
||||
loader->rpcInvalidate();
|
||||
loader = 0;
|
||||
}
|
||||
this->saved = bytes;
|
||||
this->format = fmt;
|
||||
|
||||
_loader->deleteLater();
|
||||
_loader->rpcInvalidate();
|
||||
_loader = 0;
|
||||
|
||||
forgot = false;
|
||||
}
|
||||
|
||||
StorageImage::~StorageImage() {
|
||||
if (!data.isNull()) {
|
||||
globalAquiredSize -= int64(data.width()) * data.height() * 4;
|
||||
void StorageImage::setData(QByteArray &bytes, const QByteArray &bytesFormat) {
|
||||
QBuffer buffer(&bytes);
|
||||
|
||||
if (!_data.isNull()) {
|
||||
globalAquiredSize -= int64(_data.width()) * _data.height() * 4;
|
||||
}
|
||||
if (loader) {
|
||||
loader->deleteLater();
|
||||
loader->rpcInvalidate();
|
||||
loader = 0;
|
||||
QByteArray fmt(bytesFormat);
|
||||
_data = QPixmap::fromImage(App::readImage(bytes, &fmt, false), Qt::ColorOnly);
|
||||
if (!_data.isNull()) {
|
||||
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 {
|
||||
if (!loader) return true;
|
||||
return check();
|
||||
checkload();
|
||||
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) {
|
||||
StorageKey key(storageKey(location.dc, location.volume, location.local));
|
||||
StorageKey key(storageKey(location));
|
||||
StorageImages::const_iterator i = storageImages.constFind(key);
|
||||
if (i == storageImages.cend()) {
|
||||
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) {
|
||||
StorageKey key(storageKey(location.dc, location.volume, location.local));
|
||||
StorageKey key(storageKey(location));
|
||||
StorageImages::const_iterator i = storageImages.constFind(key);
|
||||
if (i == storageImages.cend()) {
|
||||
QByteArray bytesArr(bytes);
|
||||
|
@ -726,8 +794,8 @@ StorageImage *getImage(const StorageImageLocation &location, const QByteArray &b
|
|||
} else if (!i.value()->loaded()) {
|
||||
QByteArray bytesArr(bytes);
|
||||
i.value()->setData(bytesArr);
|
||||
if (location.dc) {
|
||||
Local::writeImage(storageKey(location.dc, location.volume, location.local), StorageImageSaved(mtpToStorageType(mtpc_storage_filePartial), bytes));
|
||||
if (!location.isNull()) {
|
||||
Local::writeImage(key, StorageImageSaved(mtpToStorageType(mtpc_storage_filePartial), bytes));
|
||||
}
|
||||
}
|
||||
return i.value();
|
||||
|
|
|
@ -25,43 +25,116 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
QImage imageBlur(QImage img);
|
||||
void imageRound(QImage &img);
|
||||
|
||||
struct StorageImageLocation {
|
||||
StorageImageLocation() : width(0), height(0), dc(0), volume(0), local(0), secret(0) {
|
||||
inline uint32 packInt(int32 a) {
|
||||
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 {
|
||||
return !dc;
|
||||
return !_dclocal;
|
||||
}
|
||||
int32 width, height;
|
||||
int32 dc;
|
||||
uint64 volume;
|
||||
int32 local;
|
||||
uint64 secret;
|
||||
int32 width() const {
|
||||
return unpackIntFirst(_widthheight);
|
||||
}
|
||||
int32 height() const {
|
||||
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) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
QPixmap imagePix(QImage img, int32 w, int32 h, bool smooth, bool blurred, bool rounded, int32 outerw, int32 outerh);
|
||||
|
||||
class HistoryItem;
|
||||
class Image {
|
||||
public:
|
||||
|
||||
Image(QByteArray format = "PNG") : format(format), forgot(false) {
|
||||
}
|
||||
|
||||
virtual void automaticLoad(const HistoryItem *item) { // auto load photo
|
||||
}
|
||||
|
||||
virtual bool loaded() const {
|
||||
return true;
|
||||
}
|
||||
virtual bool loading() const {
|
||||
return false;
|
||||
}
|
||||
virtual bool displayLoading() const {
|
||||
return false;
|
||||
}
|
||||
virtual void cancel() {
|
||||
}
|
||||
virtual float64 progress() const {
|
||||
return 1;
|
||||
}
|
||||
virtual int32 loadOffset() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const QPixmap &pix(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;
|
||||
|
@ -76,10 +149,9 @@ public:
|
|||
virtual int32 width() 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 checkload() const {
|
||||
virtual void loadEvenCancelled(bool loadFirst = false, bool prior = true) {
|
||||
}
|
||||
|
||||
bool isNull() const;
|
||||
|
@ -100,6 +172,9 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
virtual void checkload() const {
|
||||
}
|
||||
|
||||
virtual const QPixmap &pixData() const = 0;
|
||||
virtual void doForget() 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);
|
||||
}
|
||||
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 {
|
||||
|
@ -176,35 +251,29 @@ public:
|
|||
|
||||
int32 width() const;
|
||||
int32 height() const;
|
||||
|
||||
void automaticLoad(const HistoryItem *item); // auto load photo
|
||||
|
||||
bool loaded() const;
|
||||
bool loading() const {
|
||||
return loader ? loader->loading() : false;
|
||||
}
|
||||
bool loading() const;
|
||||
bool displayLoading() const;
|
||||
void cancel();
|
||||
float64 progress() const;
|
||||
int32 loadOffset() const;
|
||||
|
||||
void setData(QByteArray &bytes, const QByteArray &format = QByteArray());
|
||||
|
||||
void load(bool loadFirst = false, bool prior = true) {
|
||||
if (loader) {
|
||||
loader->start(loadFirst, prior);
|
||||
if (loader) check();
|
||||
}
|
||||
}
|
||||
void checkload() const {
|
||||
if (loader) {
|
||||
if (!loader->loading()) {
|
||||
loader->start(true);
|
||||
}
|
||||
if (loader) check();
|
||||
}
|
||||
}
|
||||
void load(bool loadFirst = false, bool prior = true);
|
||||
void loadEvenCancelled(bool loadFirst = false, bool prior = true);
|
||||
|
||||
~StorageImage();
|
||||
|
||||
protected:
|
||||
|
||||
const QPixmap &pixData() const;
|
||||
bool check() const;
|
||||
void checkload() const;
|
||||
void doForget() const {
|
||||
data = QPixmap();
|
||||
_data = QPixmap();
|
||||
}
|
||||
void doRestore() const {
|
||||
QBuffer buffer(&saved);
|
||||
|
@ -212,14 +281,19 @@ protected:
|
|||
#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
|
||||
reader.setAutoTransform(true);
|
||||
#endif
|
||||
data = QPixmap::fromImageReader(&reader, Qt::ColorOnly);
|
||||
_data = QPixmap::fromImageReader(&reader, Qt::ColorOnly);
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -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)
|
||||
, id(msgId)
|
||||
, date(msgDate)
|
||||
|
@ -2989,7 +2951,6 @@ void HistoryItem::setId(MsgId newId) {
|
|||
}
|
||||
|
||||
HistoryItem::~HistoryItem() {
|
||||
itemAnimations().remove(this);
|
||||
App::historyUnregItem(this);
|
||||
if (id < 0) {
|
||||
App::app()->uploader()->cancel(fullId());
|
||||
|
@ -3079,35 +3040,49 @@ void RadialAnimation::draw(Painter &p, const QRect &inner, int32 thickness, cons
|
|||
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))
|
||||
, _openl(new PhotoLink(_data))
|
||||
, _pixw(1)
|
||||
, _pixh(1)
|
||||
, _caption(st::minPhotoSize - st::msgPadding.left() - st::msgPadding.right()) {
|
||||
setLinks(new PhotoLink(_data), new PhotoLink(_data), new PhotoCancelLink(_data));
|
||||
|
||||
if (!caption.isEmpty()) {
|
||||
_caption.setText(st::msgFont, caption + parent->skipBlock(), itemTextNoMonoOptions(parent));
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
HistoryPhoto::HistoryPhoto(PhotoData *photo) : HistoryMedia()
|
||||
HistoryPhoto::HistoryPhoto(PhotoData *photo) : HistoryFileMedia()
|
||||
, _data(photo)
|
||||
, _openl(new PhotoLink(_data))
|
||||
, _pixw(1)
|
||||
, _pixh(1) {
|
||||
setLinks(new PhotoLink(_data), new PhotoLink(_data), new PhotoCancelLink(_data));
|
||||
|
||||
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))
|
||||
, _openl(new PhotoLink(_data, chat))
|
||||
, _pixw(1)
|
||||
, _pixh(1) {
|
||||
setLinks(new PhotoLink(_data, chat), new PhotoLink(_data, chat), new PhotoCancelLink(_data));
|
||||
|
||||
_width = width;
|
||||
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() {
|
||||
_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 {
|
||||
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;
|
||||
bool bubble = parent->hasBubble();
|
||||
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel;
|
||||
|
||||
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) {
|
||||
skipx = st::mediaPadding.left();
|
||||
skipy = st::mediaPadding.top();
|
||||
|
@ -3214,45 +3202,61 @@ void HistoryPhoto::draw(Painter &p, const HistoryItem *parent, const QRect &r, b
|
|||
} else {
|
||||
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;
|
||||
if (full) {
|
||||
if (loaded) {
|
||||
pix = _data->full->pixSingle(_pixw, _pixh, width, height);
|
||||
} else {
|
||||
pix = _data->thumb->pixBlurredSingle(_pixw, _pixh, width, height);
|
||||
}
|
||||
|
||||
p.drawPixmapLeft(skipx, skipy, _width, pix);
|
||||
if (!full) {
|
||||
uint64 dt = itemAnimations().animate(parent, ms);
|
||||
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);
|
||||
}
|
||||
QRect rthumb(rtlrect(skipx, skipy, width, height, _width));
|
||||
p.drawPixmap(rthumb.topLeft(), pix);
|
||||
if (selected) {
|
||||
App::roundRect(p, rthumb, textstyleCurrent()->selectOverlay, SelectedOverlayCorners);
|
||||
}
|
||||
|
||||
if (selected) {
|
||||
App::roundRect(p, rtlrect(skipx, skipy, width, height, _width), textstyleCurrent()->selectOverlay, SelectedOverlayCorners);
|
||||
if (notChild && (radial || (!loaded && !_data->loading()))) {
|
||||
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
|
||||
if (_caption.isEmpty()) {
|
||||
if (parent->getMedia() == this) {
|
||||
if (notChild) {
|
||||
int32 fullRight = skipx + width, fullBottom = skipy + height;
|
||||
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();
|
||||
}
|
||||
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) {
|
||||
int32 fullRight = skipx + width, fullBottom = skipy + height;
|
||||
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) {
|
||||
if (media.type() == mtpc_messageMediaPhoto) {
|
||||
const MTPPhoto &photo(media.c_messageMediaPhoto().vphoto);
|
||||
App::feedPhoto(photo, _data);
|
||||
|
||||
if (photo.type() == mtpc_photo) {
|
||||
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;
|
||||
const MTPFileLocation *loc = 0;
|
||||
switch (i->type()) {
|
||||
switch (sizes.at(i).type()) {
|
||||
case mtpc_photoSize: {
|
||||
const string &s(i->c_photoSize().vtype.c_string().v);
|
||||
loc = &i->c_photoSize().vlocation;
|
||||
const string &s(sizes.at(i).c_photoSize().vtype.c_string().v);
|
||||
loc = &sizes.at(i).c_photoSize().vlocation;
|
||||
if (s.size()) size = s[0];
|
||||
} break;
|
||||
|
||||
case mtpc_photoCachedSize: {
|
||||
const string &s(i->c_photoCachedSize().vtype.c_string().v);
|
||||
loc = &i->c_photoCachedSize().vlocation;
|
||||
const string &s(sizes.at(i).c_photoCachedSize().vtype.c_string().v);
|
||||
loc = &sizes.at(i).c_photoCachedSize().vlocation;
|
||||
if (s.size()) size = s[0];
|
||||
} break;
|
||||
}
|
||||
|
@ -3322,10 +3334,20 @@ void HistoryPhoto::updateFrom(const MTPMessageMedia &media, HistoryItem *parent,
|
|||
Local::writeImage(storageKey(loc->c_fileLocation()), _data->thumb);
|
||||
} else if (size == 'm') {
|
||||
Local::writeImage(storageKey(loc->c_fileLocation()), _data->medium);
|
||||
} else if (size == 'x') {
|
||||
Local::writeImage(storageKey(loc->c_fileLocation()), _data->full);
|
||||
} else if (size == 'x' && max < 1) {
|
||||
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);
|
||||
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()));
|
||||
_maxw = qMax(_thumbw, minWidth);
|
||||
_maxw = qMax(_thumbw, int16(minWidth));
|
||||
_minh = qMax(th, int32(st::minPhotoSize));
|
||||
if (bubble) {
|
||||
_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()));
|
||||
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));
|
||||
if (bubble) {
|
||||
_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 {
|
||||
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;
|
||||
bool bubble = parent->hasBubble();
|
||||
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel;
|
||||
|
||||
int32 captionw = width - st::msgPadding.left() - st::msgPadding.right();
|
||||
|
||||
if (_data->loader) {
|
||||
if (displayLoading) {
|
||||
ensureAnimation(parent);
|
||||
if (!_animation->radial.animating()) {
|
||||
_animation->radial.start(_data->progress());
|
||||
|
@ -3586,7 +3612,6 @@ void HistoryVideo::draw(Painter &p, const HistoryItem *parent, const QRect &r, b
|
|||
} else {
|
||||
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));
|
||||
|
||||
|
@ -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.setBrush(st::black);
|
||||
} else {
|
||||
bool over = textlnkDrawOver(_data->loader ? _cancell : _savel);
|
||||
bool over = textlnkDrawOver(_data->loading() ? _cancell : _savel);
|
||||
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;
|
||||
if (!_data->already().isEmpty()) {
|
||||
if (loaded) {
|
||||
icon = (selected ? st::msgFileInPlaySelected : st::msgFileInPlay);
|
||||
} else if (_data->loader) {
|
||||
} else if (radial || _data->loading()) {
|
||||
icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
|
||||
} else {
|
||||
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 {
|
||||
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||
|
||||
bool loaded = _data->loaded();
|
||||
|
||||
int32 skipx = 0, skipy = 0, width = _width, height = _height;
|
||||
bool bubble = parent->hasBubble();
|
||||
|
||||
|
@ -3674,7 +3702,7 @@ void HistoryVideo::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x
|
|||
height -= skipy + st::mediaPadding.bottom();
|
||||
}
|
||||
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) {
|
||||
int32 fullRight = skipx + width, fullBottom = skipy + height;
|
||||
bool inDate = parent->pointInTime(fullRight, fullBottom, x, y, InfoDisplayOverImage);
|
||||
|
@ -3705,8 +3733,8 @@ void HistoryVideo::updateStatusText(const HistoryItem *parent) const {
|
|||
statusSize = FileStatusSizeFailed;
|
||||
} else if (_data->status == FileUploading) {
|
||||
statusSize = _data->uploadOffset;
|
||||
} else if (_data->loader) {
|
||||
statusSize = _data->loader->currentOffset();
|
||||
} else if (_data->loading()) {
|
||||
statusSize = _data->progress();
|
||||
} else if (!_data->already().isEmpty()) {
|
||||
statusSize = FileStatusSizeLoaded;
|
||||
} else {
|
||||
|
@ -3754,8 +3782,6 @@ HistoryAudio::HistoryAudio(const HistoryAudio &other) : HistoryFileMedia()
|
|||
}
|
||||
|
||||
void HistoryAudio::initDimensions(const HistoryItem *parent) {
|
||||
_data->prepareAutoLoader(parent);
|
||||
|
||||
_maxw = st::msgFileMinWidth;
|
||||
|
||||
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 {
|
||||
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||
|
||||
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel;
|
||||
bool loaded = _data->loaded();
|
||||
if (!loaded && _data->status == FileReady && _data->loader && !_data->loadingStarted()) {
|
||||
_data->openOnSave = 0;
|
||||
_data->save(QString());
|
||||
}
|
||||
_data->automaticLoad(parent);
|
||||
bool loaded = _data->loaded(), displayLoading = _data->displayLoading();
|
||||
|
||||
if (_data->loadingStarted() && !_data->loader->loadingLocal()) {
|
||||
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel;
|
||||
|
||||
if (displayLoading) {
|
||||
ensureAnimation(parent);
|
||||
if (!_animation->radial.animating()) {
|
||||
_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();
|
||||
p.setBrush(style::interpolate(outbg ? st::msgFileOutBg : st::msgFileInBg, outbg ? st::msgFileOutBgOver : st::msgFileInBgOver, over));
|
||||
} 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));
|
||||
}
|
||||
|
||||
|
@ -3822,10 +3846,10 @@ void HistoryAudio::draw(Painter &p, const HistoryItem *parent, const QRect &r, b
|
|||
style::sprite icon;
|
||||
if (showPause) {
|
||||
icon = outbg ? (selected ? st::msgFileOutPauseSelected : st::msgFileOutPause) : (selected ? st::msgFileInPauseSelected : st::msgFileInPause);
|
||||
} else if (_statusSize < 0 || _statusSize == FileStatusSizeLoaded) {
|
||||
icon = outbg ? (selected ? st::msgFileOutPlaySelected : st::msgFileOutPlay) : (selected ? st::msgFileInPlaySelected : st::msgFileInPlay);
|
||||
} else if (_data->loadingStarted()) {
|
||||
} else if (radial || _data->loading()) {
|
||||
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 {
|
||||
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;
|
||||
|
||||
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)) {
|
||||
lnk = (_data->loadingStarted() || _data->status == FileUploading) ? _cancell : _savel;
|
||||
if ((_data->loading() || _data->status == FileUploading || !loaded) && inner.contains(x, y)) {
|
||||
lnk = (_data->loading() || _data->status == FileUploading) ? _cancell : _savel;
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
@ -3896,8 +3920,8 @@ void HistoryAudio::unregItem(HistoryItem *item) {
|
|||
void HistoryAudio::updateFrom(const MTPMessageMedia &media, HistoryItem *parent, bool allowEmitResize) {
|
||||
if (media.type() == mtpc_messageMediaAudio) {
|
||||
App::feedAudio(media.c_messageMediaAudio().vaudio, _data);
|
||||
if (!_data->data.isEmpty()) {
|
||||
Local::writeAudio(mediaKey(mtpToLocationType(mtpc_inputAudioFileLocation), _data->dc, _data->id), _data->data);
|
||||
if (!_data->data().isEmpty()) {
|
||||
Local::writeAudio(mediaKey(AudioFileLocation, _data->dc, _data->id), _data->data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3913,8 +3937,8 @@ bool HistoryAudio::updateStatusText(const HistoryItem *parent) const {
|
|||
statusSize = FileStatusSizeFailed;
|
||||
} else if (_data->status == FileUploading) {
|
||||
statusSize = _data->uploadOffset;
|
||||
} else if (_data->loadingStarted()) {
|
||||
statusSize = _data->loader->currentOffset();
|
||||
} else if (_data->loading()) {
|
||||
statusSize = _data->loadOffset();
|
||||
} else if (_data->loaded()) {
|
||||
AudioMsgId playing;
|
||||
AudioPlayerState playingState = AudioPlayerStopped;
|
||||
|
@ -3976,8 +4000,6 @@ HistoryDocument::HistoryDocument(const HistoryDocument &other) : HistoryFileMedi
|
|||
}
|
||||
|
||||
void HistoryDocument::initDimensions(const HistoryItem *parent) {
|
||||
_data->prepareAutoLoader(parent);
|
||||
|
||||
_maxw = st::msgFileMinWidth;
|
||||
|
||||
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 {
|
||||
if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||
|
||||
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel;
|
||||
bool loaded = _data->loaded();
|
||||
_data->automaticLoad(parent);
|
||||
bool loaded = _data->loaded(), displayLoading = _data->displayLoading();
|
||||
|
||||
if (_data->loadingStarted()) {
|
||||
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel;
|
||||
|
||||
if (displayLoading) {
|
||||
ensureAnimation(parent);
|
||||
if (!_animation->radial.animating()) {
|
||||
_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);
|
||||
}
|
||||
|
||||
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);
|
||||
p.setPen(Qt::NoPen);
|
||||
if (selected) {
|
||||
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()) {
|
||||
_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->loadingStarted() ? _cancell : _savel);
|
||||
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(radialOpacity);
|
||||
style::sprite icon;
|
||||
if (loaded || _data->loadingStarted()) {
|
||||
if (radial || _data->loading()) {
|
||||
icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
|
||||
} else {
|
||||
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);
|
||||
if (radial) {
|
||||
p.setOpacity(1);
|
||||
|
@ -4077,7 +4101,7 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r
|
|||
}
|
||||
|
||||
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);
|
||||
p.setFont(over ? st::semiboldFont->underline() : st::semiboldFont);
|
||||
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();
|
||||
p.setBrush(style::interpolate(outbg ? st::msgFileOutBg : st::msgFileInBg, outbg ? st::msgFileOutBgOver : st::msgFileInBgOver, over));
|
||||
} 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));
|
||||
}
|
||||
|
||||
|
@ -4114,7 +4138,9 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r
|
|||
style::sprite icon;
|
||||
if (showPause) {
|
||||
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()) {
|
||||
icon = outbg ? (selected ? st::msgFileOutPlaySelected : st::msgFileOutPlay) : (selected ? st::msgFileInPlaySelected : st::msgFileInPlay);
|
||||
} else if (_data->isImage()) {
|
||||
|
@ -4122,8 +4148,6 @@ void HistoryDocument::draw(Painter &p, const HistoryItem *parent, const QRect &r
|
|||
} else {
|
||||
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 {
|
||||
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));
|
||||
|
||||
if (loaded) {
|
||||
} else {
|
||||
if (rthumb.contains(x, y)) {
|
||||
lnk = (_data->loadingStarted() || _data->status == FileUploading) ? _cancell : _savel;
|
||||
return;
|
||||
}
|
||||
if ((_data->loading() || _data->uploading() || !loaded) && rthumb.contains(x, y)) {
|
||||
lnk = (_data->loading() || _data->uploading()) ? _cancell : _savel;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_data->status != FileUploadFailed) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
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)) {
|
||||
lnk = (_data->loadingStarted() || _data->status == FileUploading) ? _cancell : _savel;
|
||||
if ((_data->loading() || _data->uploading() || !loaded) && inner.contains(x, y)) {
|
||||
lnk = (_data->loading() || _data->uploading()) ? _cancell : _savel;
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
@ -4220,8 +4241,8 @@ bool HistoryDocument::updateStatusText(const HistoryItem *parent) const {
|
|||
statusSize = FileStatusSizeFailed;
|
||||
} else if (_data->status == FileUploading) {
|
||||
statusSize = _data->uploadOffset;
|
||||
} else if (_data->loadingStarted()) {
|
||||
statusSize = _data->loader->currentOffset();
|
||||
} else if (_data->loading()) {
|
||||
statusSize = _data->loadOffset();
|
||||
} else if (_data->loaded()) {
|
||||
if (_data->song()) {
|
||||
SongMsgId playing;
|
||||
|
@ -4277,7 +4298,7 @@ HistoryGif::HistoryGif(DocumentData *document) : HistoryFileMedia()
|
|||
, _thumbw(1)
|
||||
, _thumbh(1)
|
||||
, _gif(0) {
|
||||
setLinks(new GifOpenLink(_data), new GifOpenLink(_data), new DocumentCancelLink(_data));
|
||||
setLinks(new DocumentOpenLink(_data), new GifOpenLink(_data), new DocumentCancelLink(_data));
|
||||
|
||||
setStatusSize(FileStatusSizeReady);
|
||||
|
||||
|
@ -4289,14 +4310,12 @@ HistoryGif::HistoryGif(const HistoryGif &other) : HistoryFileMedia()
|
|||
, _thumbw(other._thumbw)
|
||||
, _thumbh(other._thumbh)
|
||||
, _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);
|
||||
}
|
||||
|
||||
void HistoryGif::initDimensions(const HistoryItem *parent) {
|
||||
_data->prepareAutoLoader(parent);
|
||||
|
||||
bool bubble = parent->hasBubble();
|
||||
int32 tw = 0, th = 0;
|
||||
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 {
|
||||
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);
|
||||
if (!loaded && _data->status == FileReady && _data->loader && !_data->loadingStarted()) {
|
||||
_data->openOnSave = 0;
|
||||
_data->save(QString());
|
||||
}
|
||||
_data->automaticLoad(parent);
|
||||
bool loaded = _data->loaded(), displayLoading = _data->displayLoading();
|
||||
if (loaded && !_gif) {
|
||||
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());
|
||||
|
||||
if (!animating) {
|
||||
if (_data->loadingStarted() && !_data->loader->loadingLocal()) {
|
||||
if (!animating || _data->uploading()) {
|
||||
if (displayLoading) {
|
||||
ensureAnimation(parent);
|
||||
if (!_animation->radial.animating()) {
|
||||
_animation->radial.start(_data->progress());
|
||||
|
@ -4432,7 +4449,6 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, boo
|
|||
} else {
|
||||
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));
|
||||
|
||||
|
@ -4445,7 +4461,8 @@ void HistoryGif::draw(Painter &p, const HistoryItem *parent, const QRect &r, boo
|
|||
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);
|
||||
p.setPen(Qt::NoPen);
|
||||
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.setBrush(st::black);
|
||||
} else {
|
||||
bool over = textlnkDrawOver(_data->loadingStarted() ? _cancell : _savel);
|
||||
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);
|
||||
|
||||
if (!selected && _animation) {
|
||||
p.setOpacity(1);
|
||||
}
|
||||
|
||||
p.setOpacity(radialOpacity);
|
||||
style::sprite icon;
|
||||
if (_data->loaded() && !radial) {
|
||||
icon = (selected ? st::msgFileInPlaySelected : st::msgFileInPlay);
|
||||
} else if (_data->loadingStarted() || radial) {
|
||||
} else 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);
|
||||
}
|
||||
|
||||
if (!animating) {
|
||||
if (!animating || _data->uploading()) {
|
||||
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 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();
|
||||
}
|
||||
if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height) {
|
||||
if (_gif && _gif->started()) {
|
||||
} else {
|
||||
lnk = _data->loaded() ? _savel : (_data->loadingStarted() ? _cancell : _savel);
|
||||
if (_data->uploading()) {
|
||||
lnk = _cancell;
|
||||
} else if (!_gif) {
|
||||
lnk = _data->loaded() ? _openl : (_data->loading() ? _cancell : _savel);
|
||||
}
|
||||
|
||||
if (parent->getMedia() == this) {
|
||||
int32 fullRight = skipx + width, fullBottom = skipy + height;
|
||||
bool inDate = parent->pointInTime(fullRight, fullBottom, x, y, InfoDisplayOverImage);
|
||||
|
@ -4547,8 +4563,8 @@ void HistoryGif::updateStatusText(const HistoryItem *parent) const {
|
|||
statusSize = FileStatusSizeFailed;
|
||||
} else if (_data->status == FileUploading) {
|
||||
statusSize = _data->uploadOffset;
|
||||
} else if (_data->loadingStarted()) {
|
||||
statusSize = _data->loader->currentOffset();
|
||||
} else if (_data->loading()) {
|
||||
statusSize = _data->loadOffset();
|
||||
} else if (_data->loaded()) {
|
||||
statusSize = FileStatusSizeLoaded;
|
||||
} else {
|
||||
|
@ -4581,7 +4597,7 @@ bool HistoryGif::playInline(HistoryItem *parent) {
|
|||
if (_gif) {
|
||||
stopInline(parent);
|
||||
} else {
|
||||
_gif = new ClipReader(_data->location(), _data->data);
|
||||
_gif = new ClipReader(_data->location(), _data->data());
|
||||
App::regGifItem(_gif, parent);
|
||||
}
|
||||
return true;
|
||||
|
@ -4620,8 +4636,6 @@ HistorySticker::HistorySticker(DocumentData *document) : HistoryMedia()
|
|||
}
|
||||
|
||||
void HistorySticker::initDimensions(const HistoryItem *parent) {
|
||||
_data->prepareAutoLoader(parent);
|
||||
|
||||
_pixw = _data->dimensions.width();
|
||||
_pixh = _data->dimensions.height();
|
||||
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 {
|
||||
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();
|
||||
if (!loaded && _data->status == FileReady && _data->loader && !_data->loader->started()) {
|
||||
_data->openOnSave = 0;
|
||||
_data->save(QString());
|
||||
}
|
||||
|
||||
bool out = parent->out(), fromChannel = parent->fromChannel(), outbg = out && !fromChannel, hovered, pressed;
|
||||
|
||||
int32 usew = _maxw, usex = 0;
|
||||
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 (_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 (_data->sticker()->img->isNull()) {
|
||||
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) {
|
||||
if (media.type() == mtpc_messageMediaDocument) {
|
||||
App::feedDocument(media.c_messageMediaDocument().vdocument, _data);
|
||||
if (!_data->data.isEmpty()) {
|
||||
Local::writeStickerImage(mediaKey(mtpToLocationType(mtpc_inputDocumentFileLocation), _data->dc, _data->id), _data->data);
|
||||
if (!_data->data().isEmpty()) {
|
||||
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();
|
||||
if (rtl()) attachLeft = _width - attachLeft - _attach->currentWidth();
|
||||
_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) {
|
||||
lnk = _openl;
|
||||
} 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 {
|
||||
if (_media && selection == FullSelection) {
|
||||
QString text = _text.original(0, 0xFFFF, Text::ExpandLinksAll), mediaText = _media->inHistoryText();
|
||||
|
|
|
@ -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 HistoryMessage; // dynamic_cast optimize
|
||||
class HistoryForwarded; // dynamic_cast optimize
|
||||
|
@ -1014,10 +997,6 @@ public:
|
|||
return textcmdSkipBlock(skipBlockWidth(), skipBlockHeight());
|
||||
}
|
||||
|
||||
virtual bool animating() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual HistoryMessage *toHistoryMessage() { // dynamic_cast optimize
|
||||
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 {
|
||||
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 {
|
||||
public:
|
||||
|
||||
|
@ -1369,7 +1354,7 @@ public:
|
|||
}
|
||||
|
||||
bool uploading() const {
|
||||
return (_data->status == FileUploading);
|
||||
return _data->uploading();
|
||||
}
|
||||
|
||||
void regItem(HistoryItem *item);
|
||||
|
@ -1399,16 +1384,16 @@ protected:
|
|||
return _data->progress();
|
||||
}
|
||||
bool dataFinished() const {
|
||||
return !_data->loader;
|
||||
return !_data->loading() && !_data->uploading();
|
||||
}
|
||||
bool dataLoaded() const {
|
||||
return !_data->already().isEmpty();
|
||||
return _data->loaded();
|
||||
}
|
||||
|
||||
private:
|
||||
VideoData *_data;
|
||||
int16 _thumbw;
|
||||
Text _caption;
|
||||
int32 _thumbw;
|
||||
|
||||
void setStatusSize(int32 newSize) const;
|
||||
void updateStatusText(const HistoryItem *parent) const;
|
||||
|
@ -1436,7 +1421,7 @@ public:
|
|||
const QString inHistoryText() const;
|
||||
|
||||
bool uploading() const {
|
||||
return (_data->status == FileUploading);
|
||||
return _data->uploading();
|
||||
}
|
||||
|
||||
AudioData *audio() {
|
||||
|
@ -1464,7 +1449,7 @@ protected:
|
|||
return _data->progress();
|
||||
}
|
||||
bool dataFinished() const {
|
||||
return !_data->loader;
|
||||
return !_data->loading() && !_data->uploading();
|
||||
}
|
||||
bool dataLoaded() const {
|
||||
return _data->loaded();
|
||||
|
@ -1499,7 +1484,7 @@ public:
|
|||
const QString inHistoryText() const;
|
||||
|
||||
bool uploading() const {
|
||||
return (_data->status == FileUploading);
|
||||
return _data->uploading();
|
||||
}
|
||||
|
||||
bool withThumb() const {
|
||||
|
@ -1539,7 +1524,7 @@ protected:
|
|||
return _data->progress();
|
||||
}
|
||||
bool dataFinished() const {
|
||||
return !_data->loader;
|
||||
return !_data->loading() && !_data->uploading();
|
||||
}
|
||||
bool dataLoaded() const {
|
||||
return _data->loaded();
|
||||
|
@ -1584,7 +1569,7 @@ public:
|
|||
const QString inHistoryText() const;
|
||||
|
||||
bool uploading() const {
|
||||
return (_data->status == FileUploading);
|
||||
return _data->uploading();
|
||||
}
|
||||
|
||||
DocumentData *getDocument() {
|
||||
|
@ -1625,7 +1610,7 @@ protected:
|
|||
return _data->progress();
|
||||
}
|
||||
bool dataFinished() const {
|
||||
return !_data->loader;
|
||||
return !_data->loading() && !_data->uploading();
|
||||
}
|
||||
bool dataLoaded() const {
|
||||
return _data->loaded();
|
||||
|
@ -1807,10 +1792,6 @@ public:
|
|||
}
|
||||
ImagePtr replyPreview();
|
||||
|
||||
virtual bool animating() const {
|
||||
return _attach ? _attach->animating() : false;
|
||||
}
|
||||
|
||||
WebPageData *webpage() {
|
||||
return _data;
|
||||
}
|
||||
|
@ -1956,7 +1937,9 @@ public:
|
|||
bool displayFromName() const {
|
||||
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 setViewsCount(int32 count);
|
||||
|
@ -2034,9 +2017,6 @@ public:
|
|||
int32 viewsWidth() const {
|
||||
return _viewsWidth;
|
||||
}
|
||||
virtual bool animating() const {
|
||||
return _media ? _media->animating() : false;
|
||||
}
|
||||
|
||||
virtual QDateTime dateForwarded() const { // dynamic_cast optimize
|
||||
return date;
|
||||
|
@ -2201,10 +2181,6 @@ public:
|
|||
|
||||
HistoryMedia *getMedia(bool inOverview = false) const;
|
||||
|
||||
virtual bool animating() const {
|
||||
return _media ? _media->animating() : false;
|
||||
}
|
||||
|
||||
void setServiceText(const QString &text);
|
||||
|
||||
~HistoryServiceMsg();
|
||||
|
|
|
@ -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_copy_image), this, SLOT(copyContextImage()))->setEnabled(true);
|
||||
} 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);
|
||||
} else {
|
||||
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());
|
||||
AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_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 (loader) loader->cancel();
|
||||
if (lnkVideo) {
|
||||
lnkVideo->video()->cancel();
|
||||
} else if (lnkAudio) {
|
||||
lnkAudio->audio()->cancel();
|
||||
} else if (lnkDocument) {
|
||||
lnkDocument->document()->cancel();
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryInner::showContextInFolder() {
|
||||
|
@ -5436,7 +5441,7 @@ void HistoryWidget::onPhotoProgress(const FullMsgId &newId) {
|
|||
if (!item->fromChannel()) {
|
||||
updateSendAction(item->history(), SendActionUploadPhoto, 0);
|
||||
}
|
||||
// Ui::redrawHistoryItem(item);
|
||||
Ui::redrawHistoryItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -273,18 +273,7 @@ QSize StickerPreviewWidget::currentDimensions() const {
|
|||
|
||||
QPixmap StickerPreviewWidget::currentImage() const {
|
||||
if (_doc && _cacheStatus != CacheLoaded) {
|
||||
bool already = !_doc->already().isEmpty(), hasdata = !_doc->data.isEmpty();
|
||||
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);
|
||||
}
|
||||
}
|
||||
_doc->checkSticker();
|
||||
if (_doc->sticker()->img->isNull()) {
|
||||
if (_cacheStatus != CacheThumbLoaded) {
|
||||
QSize s = currentDimensions();
|
||||
|
|
|
@ -392,8 +392,10 @@ int32 LayoutOverviewVideo::resizeGetHeight(int32 width) {
|
|||
|
||||
void LayoutOverviewVideo::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
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();
|
||||
if (!_radial->animating()) {
|
||||
_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);
|
||||
}
|
||||
|
||||
if (!selected && !context->selecting && !already) {
|
||||
if (!selected && !context->selecting && !loaded) {
|
||||
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 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.setBrush(st::black);
|
||||
} 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);
|
||||
}
|
||||
|
||||
|
@ -478,19 +480,18 @@ void LayoutOverviewVideo::paint(Painter &p, const QRect &clip, uint32 selection,
|
|||
p.drawEllipse(inner);
|
||||
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
|
||||
|
||||
p.setOpacity(1);
|
||||
style::sprite icon;
|
||||
if (radial) {
|
||||
icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
|
||||
} else if (already) {
|
||||
} else if (loaded) {
|
||||
icon = (selected ? st::msgFileInPlaySelected : st::msgFileInPlay);
|
||||
} else {
|
||||
icon = (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload);
|
||||
}
|
||||
p.setOpacity(radial ? _radial->opacity() : 1);
|
||||
p.setOpacity((radial && loaded) ? _radial->opacity() : 1);
|
||||
p.drawSpriteCenter(inner, icon);
|
||||
if (radial) {
|
||||
p.setOpacity(1);
|
||||
|
||||
QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine)));
|
||||
_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 {
|
||||
bool loaded = _data->loaded();
|
||||
|
||||
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;
|
||||
} else if (_data->status == FileUploading) {
|
||||
statusSize = _data->uploadOffset;
|
||||
} else if (_data->loader) {
|
||||
statusSize = _data->loader->currentOffset();
|
||||
} else if (_data->loading()) {
|
||||
statusSize = _data->loadOffset();
|
||||
} else if (!_data->already().isEmpty()) {
|
||||
statusSize = FileStatusSizeLoaded;
|
||||
} else {
|
||||
|
@ -535,9 +538,8 @@ void LayoutOverviewVideo::updateStatusText() const {
|
|||
}
|
||||
|
||||
LayoutOverviewAudio::LayoutOverviewAudio(AudioData *audio, HistoryItem *parent) : LayoutAbstractFileItem(parent)
|
||||
, _data(audio) {
|
||||
_data->prepareAutoLoader(_parent);
|
||||
|
||||
, _data(audio)
|
||||
, _namel(new AudioOpenLink(_data)) {
|
||||
setLinks(new AudioOpenLink(_data), new AudioOpenLink(_data), new AudioCancelLink(_data));
|
||||
updateName();
|
||||
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 {
|
||||
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();
|
||||
if (!_radial->animating()) {
|
||||
_radial->start(_data->progress());
|
||||
|
@ -593,7 +593,7 @@ void LayoutOverviewAudio::paint(Painter &p, const QRect &clip, uint32 selection,
|
|||
float64 over = a_iconOver.current();
|
||||
p.setBrush(style::interpolate(st::msgFileInBg, st::msgFileInBgOver, over));
|
||||
} 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);
|
||||
}
|
||||
|
||||
|
@ -612,7 +612,7 @@ void LayoutOverviewAudio::paint(Painter &p, const QRect &clip, uint32 selection,
|
|||
icon = selected ? st::msgFileInPauseSelected : st::msgFileInPause;
|
||||
} else if (_statusSize < 0 || _statusSize == FileStatusSizeLoaded) {
|
||||
icon = selected ? st::msgFileInPlaySelected : st::msgFileInPlay;
|
||||
} else if (_data->loadingStarted()) {
|
||||
} else if (_data->loading()) {
|
||||
icon = selected ? st::msgFileInCancelSelected : st::msgFileInCancel;
|
||||
} else {
|
||||
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));
|
||||
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 (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;
|
||||
}
|
||||
}
|
||||
if (hasPoint(x, y) && !link && !_data->loading()) {
|
||||
link = _namel;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void LayoutOverviewAudio::updateName() const {
|
||||
|
@ -683,7 +687,7 @@ bool LayoutOverviewAudio::updateStatusText() const {
|
|||
int32 statusSize = 0, realDuration = 0;
|
||||
if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) {
|
||||
statusSize = FileStatusSizeFailed;
|
||||
} else if (!_data->already().isEmpty() || !_data->data.isEmpty()) {
|
||||
} else if (_data->loaded()) {
|
||||
AudioMsgId playing;
|
||||
AudioPlayerState playingState = AudioPlayerStopped;
|
||||
int64 playingPosition = 0, playingDuration = 0;
|
||||
|
@ -717,8 +721,6 @@ LayoutOverviewDocument::LayoutOverviewDocument(DocumentData *document, HistoryIt
|
|||
, _namew(st::semiboldFont->width(_name))
|
||||
, _datew(st::normalFont->width(_date))
|
||||
, _colorIndex(documentColorIndex(_data, _ext)) {
|
||||
_data->prepareAutoLoader(_parent);
|
||||
|
||||
setLinks(new DocumentOpenLink(_data), new DocumentSaveLink(_data), new DocumentCancelLink(_data));
|
||||
|
||||
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 {
|
||||
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();
|
||||
if (!_radial->animating()) {
|
||||
_radial->start(_data->progress());
|
||||
|
@ -785,7 +790,7 @@ void LayoutOverviewDocument::paint(Painter &p, const QRect &clip, uint32 selecti
|
|||
float64 over = a_iconOver.current();
|
||||
p.setBrush(style::interpolate(st::msgFileInBg, st::msgFileInBgOver, over));
|
||||
} 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);
|
||||
}
|
||||
|
||||
|
@ -802,9 +807,9 @@ void LayoutOverviewDocument::paint(Painter &p, const QRect &clip, uint32 selecti
|
|||
style::sprite icon;
|
||||
if (showPause) {
|
||||
icon = selected ? st::msgFileInPauseSelected : st::msgFileInPause;
|
||||
} else if (_statusSize < 0 || _statusSize == FileStatusSizeLoaded) {
|
||||
} else if (loaded) {
|
||||
icon = selected ? st::msgFileInPlaySelected : st::msgFileInPlay;
|
||||
} else if (_data->loadingStarted() && !_data->loader->loadingLocal()) {
|
||||
} else if (_data->loading()) {
|
||||
icon = selected ? st::msgFileInCancelSelected : st::msgFileInCancel;
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
if (clip.intersects(inner)) {
|
||||
float64 radialOpacity = (radial && loaded) ? _radial->opacity() : 1;
|
||||
p.setPen(Qt::NoPen);
|
||||
if (selected) {
|
||||
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()) {
|
||||
_a_iconOver.step(context->ms);
|
||||
float64 over = a_iconOver.current();
|
||||
p.setOpacity((st::msgDateImgBg->c.alphaF() * (1 - over)) + (st::msgDateImgBgOver->c.alphaF() * over));
|
||||
p.setBrush(st::black);
|
||||
} else {
|
||||
bool over = textlnkDrawOver(_data->loadingStarted() ? _cancell : _savel);
|
||||
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(radialOpacity);
|
||||
style::sprite icon;
|
||||
if (loaded || (_data->loadingStarted() && !_data->loader->loadingLocal())) {
|
||||
if (loaded || _data->loading()) {
|
||||
icon = (selected ? st::msgFileInCancelSelected : st::msgFileInCancel);
|
||||
} else {
|
||||
icon = (selected ? st::msgFileInDownloadSelected : st::msgFileInDownload);
|
||||
}
|
||||
p.setOpacity(radial ? _radial->opacity() : 1);
|
||||
p.drawSpriteCenter(inner, icon);
|
||||
if (radial) {
|
||||
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 {
|
||||
bool loaded = _data->loaded() || (_data->loader && _data->loader->localAvailable());
|
||||
bool loaded = _data->loaded() || Local::willStickerImageLoad(mediaKey(DocumentFileLocation, _data->dc, _data->id));
|
||||
|
||||
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));
|
||||
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;
|
||||
}
|
||||
} 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));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -956,7 +964,7 @@ void LayoutOverviewDocument::getState(TextLinkPtr &link, HistoryCursorState &cur
|
|||
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)) {
|
||||
link = _namel;
|
||||
return;
|
||||
|
@ -976,8 +984,8 @@ bool LayoutOverviewDocument::updateStatusText() const {
|
|||
statusSize = FileStatusSizeFailed;
|
||||
} else if (_data->status == FileUploading) {
|
||||
statusSize = _data->uploadOffset;
|
||||
} else if (_data->loadingStarted()) {
|
||||
statusSize = _data->loader->currentOffset();
|
||||
} else if (_data->loading()) {
|
||||
statusSize = _data->loadOffset();
|
||||
} else if (_data->loaded()) {
|
||||
if (_data->song()) {
|
||||
SongMsgId playing;
|
||||
|
|
|
@ -323,10 +323,10 @@ protected:
|
|||
return _data->progress();
|
||||
}
|
||||
virtual bool dataFinished() const {
|
||||
return !_data->loader;
|
||||
return !_data->loading();
|
||||
}
|
||||
virtual bool dataLoaded() const {
|
||||
return !_data->already().isEmpty();
|
||||
return _data->loaded();
|
||||
}
|
||||
virtual bool iconAnimated() const {
|
||||
return true;
|
||||
|
@ -363,10 +363,10 @@ protected:
|
|||
return _data->progress();
|
||||
}
|
||||
virtual bool dataFinished() const {
|
||||
return !_data->loader;
|
||||
return !_data->loading();
|
||||
}
|
||||
virtual bool dataLoaded() const {
|
||||
return !_data->already().isEmpty() || !_data->data.isEmpty();
|
||||
return _data->loaded();
|
||||
}
|
||||
virtual bool iconAnimated() const {
|
||||
return true;
|
||||
|
@ -375,6 +375,7 @@ protected:
|
|||
private:
|
||||
OverviewItemInfo _info;
|
||||
AudioData *_data;
|
||||
TextLinkPtr _namel;
|
||||
|
||||
mutable Text _name, _details;
|
||||
mutable int32 _nameVersion;
|
||||
|
@ -407,13 +408,13 @@ protected:
|
|||
return _data->progress();
|
||||
}
|
||||
virtual bool dataFinished() const {
|
||||
return !_data->loader;
|
||||
return !_data->loading();
|
||||
}
|
||||
virtual bool dataLoaded() const {
|
||||
return _data->loaded();
|
||||
}
|
||||
virtual bool iconAnimated() const {
|
||||
return _data->song() || !dataLoaded() || (_radial && _radial->animating());
|
||||
return _data->song() || !_data->loaded() || (_radial && _radial->animating());
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -194,6 +194,7 @@ struct FileLoadResult {
|
|||
int32 filesize;
|
||||
UploadFileParts fileparts;
|
||||
QByteArray filemd5;
|
||||
int32 partssize;
|
||||
|
||||
uint64 thumbId; // id is always file-id of media, thumbId is file-id of thumb ( == id for photos)
|
||||
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
|
||||
|
||||
void setFileData(const QByteArray &filedata) {
|
||||
if (!filedata.isEmpty()) {
|
||||
int32 size = filedata.size();
|
||||
for (int32 i = 0, part = 0; i < size; i += UploadPartSize, ++part) {
|
||||
if (filedata.isEmpty()) {
|
||||
partssize = 0;
|
||||
} else {
|
||||
partssize = filedata.size();
|
||||
for (int32 i = 0, part = 0; i < partssize; i += UploadPartSize, ++part) {
|
||||
fileparts.insert(part, filedata.mid(i, UploadPartSize));
|
||||
}
|
||||
filemd5.resize(32);
|
||||
|
|
|
@ -2469,13 +2469,6 @@ namespace Local {
|
|||
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() {
|
||||
return _imagesMap.size();
|
||||
}
|
||||
|
@ -2535,11 +2528,8 @@ namespace Local {
|
|||
return _localLoader->addTask(new StickerImageLoadTask(j->first, location, loader));
|
||||
}
|
||||
|
||||
bool willStickerImageLoad(const StorageKey &location, bool check) {
|
||||
StorageMap::const_iterator j = _stickerImagesMap.constFind(location);
|
||||
if (j == _stickerImagesMap.cend()) return false;
|
||||
if (check && !fileExists(j->first, UserPath)) return false;
|
||||
return true;
|
||||
bool willStickerImageLoad(const StorageKey &location) {
|
||||
return _stickerImagesMap.constFind(location) != _stickerImagesMap.cend();
|
||||
}
|
||||
|
||||
int32 hasStickers() {
|
||||
|
@ -2601,13 +2591,6 @@ namespace Local {
|
|||
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() {
|
||||
return _audiosMap.size();
|
||||
}
|
||||
|
@ -2623,8 +2606,8 @@ namespace Local {
|
|||
}
|
||||
|
||||
void _writeStorageImageLocation(QDataStream &stream, const StorageImageLocation &loc) {
|
||||
stream << qint32(loc.width) << qint32(loc.height);
|
||||
stream << qint32(loc.dc) << quint64(loc.volume) << qint32(loc.local) << quint64(loc.secret);
|
||||
stream << qint32(loc.width()) << qint32(loc.height());
|
||||
stream << qint32(loc.dc()) << quint64(loc.volume()) << qint32(loc.local()) << quint64(loc.secret());
|
||||
}
|
||||
|
||||
uint32 _storageImageLocationSize() {
|
||||
|
@ -2896,7 +2879,7 @@ namespace Local {
|
|||
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;
|
||||
|
||||
set.stickers.push_back(doc);
|
||||
|
|
|
@ -124,19 +124,17 @@ namespace Local {
|
|||
void writeImage(const StorageKey &location, const ImagePtr &img);
|
||||
void writeImage(const StorageKey &location, const StorageImageSaved &jpeg, bool overwrite = true);
|
||||
TaskId startImageLoad(const StorageKey &location, mtpFileLoader *loader);
|
||||
bool willImageLoad(const StorageKey &location, bool check = false);
|
||||
int32 hasImages();
|
||||
qint64 storageImagesSize();
|
||||
|
||||
void writeStickerImage(const StorageKey &location, const QByteArray &data, bool overwrite = true);
|
||||
TaskId startStickerImageLoad(const StorageKey &location, mtpFileLoader *loader);
|
||||
bool willStickerImageLoad(const StorageKey &location, bool check = false);
|
||||
bool willStickerImageLoad(const StorageKey &location);
|
||||
int32 hasStickers();
|
||||
qint64 storageStickersSize();
|
||||
|
||||
void writeAudio(const StorageKey &location, const QByteArray &data, bool overwrite = true);
|
||||
TaskId startAudioLoad(const StorageKey &location, mtpFileLoader *loader);
|
||||
bool willAudioLoad(const StorageKey &location, bool check = false);
|
||||
int32 hasAudios();
|
||||
qint64 storageAudiosSize();
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
#include "lang.h"
|
||||
|
||||
#include "boxes/addcontactbox.h"
|
||||
#include "fileuploader.h"
|
||||
#include "application.h"
|
||||
#include "window.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));
|
||||
ConfirmBox *box = new ConfirmBox((selectedCount < 0) ? str : str.arg(selectedCount), lang(lng_box_delete));
|
||||
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()));
|
||||
} else {
|
||||
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) {
|
||||
VideoData *video = App::video(loader->objId());
|
||||
if (video->loader) {
|
||||
video->status = FileReady;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (video->loaded()) {
|
||||
video->performActionOnLoad();
|
||||
}
|
||||
|
||||
const VideoItems &items(App::videoItems());
|
||||
VideoItems::const_iterator i = items.constFind(video);
|
||||
if (i != items.cend()) {
|
||||
|
@ -1673,7 +1669,7 @@ void MainWidget::videoLoadFailed(mtpFileLoader *loader, bool started) {
|
|||
loadFailed(loader, started, SLOT(videoLoadRetry()));
|
||||
VideoData *video = App::video(loader->objId());
|
||||
if (video) {
|
||||
if (video->loader) video->finish();
|
||||
if (video->loading()) video->cancel();
|
||||
video->status = FileDownloadFailed;
|
||||
}
|
||||
}
|
||||
|
@ -1686,35 +1682,10 @@ void MainWidget::videoLoadRetry() {
|
|||
|
||||
void MainWidget::audioLoadProgress(mtpFileLoader *loader) {
|
||||
AudioData *audio = App::audio(loader->objId());
|
||||
if (audio->loader) {
|
||||
audio->status = FileReady;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (audio->loaded()) {
|
||||
audio->performActionOnLoad();
|
||||
}
|
||||
|
||||
const AudioItems &items(App::audioItems());
|
||||
AudioItems::const_iterator i = items.constFind(audio);
|
||||
if (i != items.cend()) {
|
||||
|
@ -1733,13 +1704,13 @@ void MainWidget::audioPlayProgress(const AudioMsgId &audioId) {
|
|||
|
||||
AudioData *audio = audioId.audio;
|
||||
QString already = audio->already(true);
|
||||
if (already.isEmpty() && !audio->data.isEmpty()) {
|
||||
if (already.isEmpty() && !audio->data().isEmpty()) {
|
||||
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);
|
||||
if (!filename.isEmpty()) {
|
||||
QFile f(filename);
|
||||
if (f.open(QIODevice::WriteOnly)) {
|
||||
if (f.write(audio->data) == audio->data.size()) {
|
||||
if (f.write(audio->data()) == audio->data().size()) {
|
||||
f.close();
|
||||
already = filename;
|
||||
audio->setLocation(FileLocation(StorageFilePartial, filename));
|
||||
|
@ -1770,7 +1741,7 @@ void MainWidget::documentPlayProgress(const SongMsgId &songId) {
|
|||
|
||||
DocumentData *document = songId.song;
|
||||
QString already = document->already(true);
|
||||
if (already.isEmpty() && !document->data.isEmpty()) {
|
||||
if (already.isEmpty() && !document->data().isEmpty()) {
|
||||
QString name = document->name, filter;
|
||||
MimeType mimeType = mimeTypeForName(document->mime);
|
||||
QStringList p = mimeType.globPatterns();
|
||||
|
@ -1787,7 +1758,7 @@ void MainWidget::documentPlayProgress(const SongMsgId &songId) {
|
|||
if (!filename.isEmpty()) {
|
||||
QFile f(filename);
|
||||
if (f.open(QIODevice::WriteOnly)) {
|
||||
if (f.write(document->data) == document->data.size()) {
|
||||
if (f.write(document->data()) == document->data().size()) {
|
||||
f.close();
|
||||
already = filename;
|
||||
document->setLocation(FileLocation(StorageFilePartial, filename));
|
||||
|
@ -1832,8 +1803,8 @@ void MainWidget::audioLoadFailed(mtpFileLoader *loader, bool started) {
|
|||
loadFailed(loader, started, SLOT(audioLoadRetry()));
|
||||
AudioData *audio = App::audio(loader->objId());
|
||||
if (audio) {
|
||||
if (audio->loading()) audio->cancel();
|
||||
audio->status = FileDownloadFailed;
|
||||
if (audio->loader) audio->finish();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1844,70 +1815,11 @@ void MainWidget::audioLoadRetry() {
|
|||
}
|
||||
|
||||
void MainWidget::documentLoadProgress(mtpFileLoader *loader) {
|
||||
bool songPlayActivated = false;
|
||||
DocumentData *document = App::document(loader->objId());
|
||||
if (document->loader) {
|
||||
document->status = FileReady;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (document->loaded()) {
|
||||
document->performActionOnLoad();
|
||||
}
|
||||
|
||||
const DocumentItems &items(App::documentItems());
|
||||
DocumentItems::const_iterator i = items.constFind(document);
|
||||
if (i != items.cend()) {
|
||||
|
@ -1917,18 +1829,14 @@ void MainWidget::documentLoadProgress(mtpFileLoader *loader) {
|
|||
}
|
||||
App::wnd()->documentUpdated(document);
|
||||
|
||||
if (!songPlayActivated && audioPlayer()) {
|
||||
if (!document->loaded() && document->loading() && document->song() && audioPlayer()) {
|
||||
SongMsgId playing;
|
||||
AudioPlayerState playingState = AudioPlayerStopped;
|
||||
int64 playingPosition = 0, playingDuration = 0;
|
||||
int32 playingFrequency = 0;
|
||||
audioPlayer()->currentState(&playing, &playingState, &playingPosition, &playingDuration, &playingFrequency);
|
||||
if (playing.song == document && !_player.isHidden()) {
|
||||
if (document->loader) {
|
||||
_player.updateState(playing, playingState, playingPosition, playingDuration, playingFrequency);
|
||||
} else {
|
||||
audioPlayer()->play(playing);
|
||||
}
|
||||
_player.updateState(playing, playingState, playingPosition, playingDuration, playingFrequency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1937,7 +1845,7 @@ void MainWidget::documentLoadFailed(mtpFileLoader *loader, bool started) {
|
|||
loadFailed(loader, started, SLOT(documentLoadRetry()));
|
||||
DocumentData *document = App::document(loader->objId());
|
||||
if (document) {
|
||||
if (document->loader) document->finish();
|
||||
if (document->loading()) document->cancel();
|
||||
document->status = FileDownloadFailed;
|
||||
}
|
||||
}
|
||||
|
@ -2124,7 +2032,7 @@ void MainWidget::updateScrollColors() {
|
|||
|
||||
void MainWidget::setChatBackground(const App::WallPaper &wp) {
|
||||
_background = new App::WallPaper(wp);
|
||||
_background->full->load();
|
||||
_background->full->loadEvenCancelled();
|
||||
checkChatBackground();
|
||||
}
|
||||
|
||||
|
|
|
@ -88,11 +88,7 @@ MediaView::MediaView() : TWidget(App::wnd())
|
|||
, _docThumbx(0)
|
||||
, _docThumby(0)
|
||||
, _docThumbw(0)
|
||||
, _docRadialFirst(0)
|
||||
, _docRadialStart(0)
|
||||
, _docRadialLast(0)
|
||||
, _docRadialOpacity(1)
|
||||
, a_docRadialStart(0, 1)
|
||||
, _docRadial(animation(this, &MediaView::step_radial))
|
||||
, _docDownload(this, lang(lng_media_download), st::mvDocLink)
|
||||
, _docSaveAs(this, lang(lng_mediaview_save_as), 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)));
|
||||
|
||||
_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);
|
||||
moveToScreen();
|
||||
|
@ -259,9 +253,9 @@ void MediaView::stopGif() {
|
|||
|
||||
void MediaView::documentUpdated(DocumentData *doc) {
|
||||
if (_doc && _doc == doc && !fileShown()) {
|
||||
if ((_doc->loader && _docCancel.isHidden()) || (!_doc->loader && !_docCancel.isHidden())) {
|
||||
if ((_doc->loading() && _docCancel.isHidden()) || (!_doc->loading() && !_docCancel.isHidden())) {
|
||||
updateControls();
|
||||
} else if (_doc->loader) {
|
||||
} else if (_doc->loading()) {
|
||||
updateDocSize();
|
||||
update(_docRect);
|
||||
}
|
||||
|
@ -278,8 +272,8 @@ void MediaView::changingMsgId(HistoryItem *row, MsgId newId) {
|
|||
void MediaView::updateDocSize() {
|
||||
if (!_doc || fileShown()) return;
|
||||
|
||||
if (_doc->loader) {
|
||||
quint64 ready = _doc->loader->currentOffset(), total = _doc->size;
|
||||
if (_doc->loading()) {
|
||||
quint64 ready = _doc->loadOffset(), total = _doc->size;
|
||||
QString readyStr, totalStr, mb;
|
||||
if (total >= 1024 * 1024) { // more than 1 mb
|
||||
qint64 readyTenthMb = (ready * 10 / (1024 * 1024)), totalTenthMb = (total * 10 / (1024 * 1024));
|
||||
|
@ -310,14 +304,14 @@ void MediaView::updateDocSize() {
|
|||
|
||||
void MediaView::updateControls() {
|
||||
if (_doc && !fileShown()) {
|
||||
if (_doc->loader) {
|
||||
if (_doc->loading()) {
|
||||
_docDownload.hide();
|
||||
_docSaveAs.hide();
|
||||
_docCancel.moveToLeft(_docRect.x() + 2 * st::mvDocPadding + st::mvDocIconSize, _docRect.y() + st::mvDocPadding + st::mvDocLinksTop);
|
||||
_docCancel.show();
|
||||
if (!_docRadialFirst) _docRadialFirst = _docRadialLast = _docRadialStart = getms();
|
||||
if (!_a_state.animating()) _a_state.start();
|
||||
_a_state.step();
|
||||
if (!_docRadial.animating()) {
|
||||
_docRadial.start(_doc->progress());
|
||||
}
|
||||
} else {
|
||||
if (_doc->loaded(true)) {
|
||||
_docDownload.hide();
|
||||
|
@ -398,7 +392,7 @@ void MediaView::updateControls() {
|
|||
}
|
||||
|
||||
void MediaView::updateDropdown() {
|
||||
_btnSaveCancel->setVisible(_doc && _doc->loader);
|
||||
_btnSaveCancel->setVisible(_doc && _doc->loading());
|
||||
_btnToMessage->setVisible(_msgid > 0);
|
||||
_btnShowInFolder->setVisible(_doc && !_doc->already(true).isEmpty());
|
||||
_btnSaveAs->setVisible(true);
|
||||
|
@ -449,52 +443,36 @@ void MediaView::step_state(uint64 ms, bool timer) {
|
|||
update(toUpdate);
|
||||
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()) {
|
||||
_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() {
|
||||
delete _gif;
|
||||
setBadPointer(_gif);
|
||||
|
@ -556,7 +534,7 @@ void MediaView::onSaveAs() {
|
|||
QString file;
|
||||
if (_doc) {
|
||||
const FileLocation &location(_doc->location(true));
|
||||
if (!_doc->data.isEmpty() || location.accessEnable()) {
|
||||
if (!_doc->data().isEmpty() || location.accessEnable()) {
|
||||
QFileInfo alreadyInfo(location.name());
|
||||
QDir alreadyDir(alreadyInfo.dir());
|
||||
QString name = alreadyInfo.fileName(), filter;
|
||||
|
@ -577,16 +555,16 @@ void MediaView::onSaveAs() {
|
|||
file = saveFileName(lang(lng_save_file), filter, qsl("doc"), name, true, alreadyDir);
|
||||
psShowOverAll(this);
|
||||
if (!file.isEmpty() && file != location.name()) {
|
||||
if (_doc->data.isEmpty()) {
|
||||
if (_doc->data().isEmpty()) {
|
||||
QFile(location.name()).copy(file);
|
||||
} else {
|
||||
QFile f(file);
|
||||
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 {
|
||||
if (!fileShown()) {
|
||||
DocumentSaveLink::doSave(_doc, true);
|
||||
|
@ -615,10 +593,13 @@ void MediaView::onSaveAs() {
|
|||
}
|
||||
|
||||
void MediaView::onDocClick() {
|
||||
if (_doc->loader && _doc->loader->started()) {
|
||||
if (_doc->loading()) {
|
||||
onSaveCancel();
|
||||
} 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() {
|
||||
if (_doc && _doc->loader) {
|
||||
_doc->loader->cancel();
|
||||
if (_doc && _doc->loading()) {
|
||||
_doc->cancel();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -935,7 +916,7 @@ void MediaView::displayPhoto(PhotoData *photo, HistoryItem *item) {
|
|||
_from = _user;
|
||||
}
|
||||
updateControls();
|
||||
_photo->full->load();
|
||||
_photo->full->loadEvenCancelled();
|
||||
if (isHidden()) {
|
||||
psUpdateOverlayed(this);
|
||||
show();
|
||||
|
@ -956,35 +937,39 @@ void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) { // empty
|
|||
|
||||
_caption = Text();
|
||||
if (_doc) {
|
||||
if (_doc->isAnimation() && !_doc->loaded() && _doc->status == FileReady && _doc->loader && !_doc->loadingStarted()) {
|
||||
_doc->openOnSave = 0;
|
||||
_doc->save(QString());
|
||||
}
|
||||
|
||||
const FileLocation &location(_doc->location(true));
|
||||
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);
|
||||
if (_doc->sticker()) {
|
||||
_doc->checkSticker();
|
||||
if (!_doc->sticker()->img->isNull()) {
|
||||
_current = _doc->sticker()->img->pix();
|
||||
} else {
|
||||
_current = _doc->thumb->pixBlurred(_doc->dimensions.width(), _doc->dimensions.height());
|
||||
}
|
||||
} else if (location.accessEnable()) {
|
||||
if (_doc->isAnimation()) {
|
||||
} else {
|
||||
_doc->automaticLoad(item);
|
||||
|
||||
const FileLocation &location(_doc->location(true));
|
||||
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);
|
||||
_gif = new ClipReader(location, _doc->data());
|
||||
}
|
||||
} else {
|
||||
if (QImageReader(location.name()).canRead()) {
|
||||
_current = QPixmap::fromImage(App::readImage(location.name(), 0, false), Qt::ColorOnly);
|
||||
} else if (location.accessEnable()) {
|
||||
if (_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 (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);
|
||||
}
|
||||
|
||||
_docRadialFirst = _docRadialLast = _docRadialStart = 0;
|
||||
|
||||
float64 prg = (_doc && _doc->loader) ? _doc->loader->currentProgress() : 0;
|
||||
a_docRadial = anim::fvalue(prg, qMax(prg, 0.0001));
|
||||
_docRadial.stop();
|
||||
// _docSize is updated in updateControls()
|
||||
|
||||
_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);
|
||||
_current = _photo->thumb->pixNoCache(w, h, true, true);
|
||||
if (cRetina()) _current.setDevicePixelRatio(cRetinaFactor());
|
||||
} else if (_current.isNull()) {
|
||||
_current = _photo->thumb->pix();
|
||||
}
|
||||
}
|
||||
p.setOpacity(1);
|
||||
|
@ -1211,10 +1195,17 @@ void MediaView::paintEvent(QPaintEvent *e) {
|
|||
if (_docRect.intersects(r)) {
|
||||
p.fillRect(_docRect, st::mvDocBg->b);
|
||||
if (_docIconRect.intersects(r)) {
|
||||
bool radial = false;
|
||||
float64 radialOpacity = 0;
|
||||
if (_docRadial.animating()) {
|
||||
_docRadial.step(ms);
|
||||
radial = _docRadial.animating();
|
||||
radialOpacity = _docRadial.opacity();
|
||||
}
|
||||
icon = true;
|
||||
if (!_doc || _doc->thumb->isNull()) {
|
||||
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.setPen(st::mvDocExtColor->p);
|
||||
p.setFont(st::mvDocExtFont->f);
|
||||
|
@ -1228,33 +1219,27 @@ void MediaView::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
|
||||
float64 o = overLevel(OverIcon);
|
||||
if (_doc && _docRadialStart > 0) {
|
||||
if (!_doc->loaded() && _docRadialOpacity < 1) {
|
||||
p.setOpacity((o * 1. + (1 - o) * st::radialDownloadOpacity) * (1 - _docRadialOpacity));
|
||||
if (radial) {
|
||||
if (!_doc->loaded() && radialOpacity < 1) {
|
||||
p.setOpacity((o * 1. + (1 - o) * st::radialDownloadOpacity) * (1 - radialOpacity));
|
||||
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);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(st::black->b);
|
||||
p.setOpacity(_docRadialOpacity * st::radialBgOpacity);
|
||||
p.drawEllipse(inner);
|
||||
p.setBrush(st::black);
|
||||
p.setOpacity(radialOpacity * st::radialBgOpacity);
|
||||
|
||||
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.setOpacity(1);
|
||||
|
||||
QRect arc(inner.marginsRemoved(QMargins(st::radialLine, st::radialLine, st::radialLine, st::radialLine)));
|
||||
|
||||
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);
|
||||
_docRadial.draw(p, arc, st::radialLine, st::white);
|
||||
} else if (_doc && !_doc->loaded()) {
|
||||
p.setOpacity((o * 1. + (1 - o) * st::radialDownloadOpacity));
|
||||
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))) {
|
||||
onCopy();
|
||||
} 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();
|
||||
}
|
||||
} 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 MediaTypeDocument:
|
||||
case MediaTypeGif:
|
||||
case MediaTypeSticker:
|
||||
DocumentData *doc = media->getDocument();
|
||||
doc->forget();
|
||||
if (!doc->data.isEmpty() && doc->prepareAutoLoader(item)) {
|
||||
doc->data.clear();
|
||||
}
|
||||
break;
|
||||
case MediaTypeSticker: media->getDocument()->forget(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1605,15 +1584,12 @@ void MediaView::preloadData(int32 delta) {
|
|||
if (HistoryItem *item = App::histItemById(previewHistory->channelId(), previewHistory->overview[_overview][previewIndex])) {
|
||||
if (HistoryMedia *media = item->getMedia()) {
|
||||
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 MediaTypeGif: {
|
||||
DocumentData *doc = media->getDocument();
|
||||
doc->thumb->load();
|
||||
if (doc->isAnimation() && !doc->loaded() && doc->status == FileReady && doc->loader && !doc->loadingStarted()) {
|
||||
doc->openOnSave = 0;
|
||||
doc->save(QString());
|
||||
}
|
||||
doc->automaticLoad(item);
|
||||
} 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) {
|
||||
if (i >= 0 && i < _user->photos.size() && i != _index) {
|
||||
_user->photos[i]->full->load();
|
||||
_user->photos[i]->full->loadEvenCancelled();
|
||||
}
|
||||
}
|
||||
int32 forgetIndex = _index - delta * 2;
|
||||
|
|
|
@ -65,8 +65,6 @@ public:
|
|||
void updateControls();
|
||||
void updateDropdown();
|
||||
|
||||
void step_state(uint64 ms, bool timer);
|
||||
|
||||
void showSaveMsgFile();
|
||||
void close();
|
||||
|
||||
|
@ -116,6 +114,9 @@ private:
|
|||
void updateHeader();
|
||||
void snapXY();
|
||||
|
||||
void step_state(uint64 ms, bool timer);
|
||||
void step_radial(uint64 ms, bool timer);
|
||||
|
||||
QBrush _transparentBrush;
|
||||
|
||||
PhotoData *_photo;
|
||||
|
@ -154,10 +155,7 @@ private:
|
|||
int32 _docNameWidth, _docSizeWidth, _docExtWidth;
|
||||
QRect _docRect, _docIconRect;
|
||||
int32 _docThumbx, _docThumby, _docThumbw;
|
||||
uint64 _docRadialFirst, _docRadialStart, _docRadialLast;
|
||||
float64 _docRadialOpacity;
|
||||
QPen _docRadialPen;
|
||||
anim::fvalue a_docRadial, a_docRadialStart;
|
||||
RadialAnimation _docRadial;
|
||||
LinkButton _docDownload, _docSaveAs, _docCancel;
|
||||
|
||||
History *_migrated, *_history; // if conversation photos or files overview
|
||||
|
|
|
@ -26,14 +26,14 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
|||
#include "localstorage.h"
|
||||
|
||||
namespace {
|
||||
int32 _priority = 1;
|
||||
int32 GlobalPriority = 1;
|
||||
struct DataRequested {
|
||||
DataRequested() {
|
||||
memset(v, 0, sizeof(v));
|
||||
}
|
||||
int64 v[MTPDownloadSessionsCount];
|
||||
};
|
||||
QMap<int32, DataRequested> _dataRequested;
|
||||
QMap<int32, DataRequested> DataRequestedMap;
|
||||
}
|
||||
struct mtpFileLoaderQueue {
|
||||
mtpFileLoaderQueue() : queries(0), start(0), end(0) {
|
||||
|
@ -47,63 +47,64 @@ namespace {
|
|||
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)
|
||||
, next(0)
|
||||
, priority(0)
|
||||
, _paused(false)
|
||||
, inQueue(false)
|
||||
, complete(false)
|
||||
, _autoLoading(autoLoading)
|
||||
, _inQueue(false)
|
||||
, _complete(false)
|
||||
, _localStatus(LocalNotTried)
|
||||
, skippedBytes(0)
|
||||
, nextRequestOffset(0)
|
||||
, lastComplete(false)
|
||||
, dc(dc)
|
||||
, _skippedBytes(0)
|
||||
, _nextRequestOffset(0)
|
||||
, _lastComplete(false)
|
||||
, _dc(location->dc())
|
||||
, _locationType(UnknownFileLocation)
|
||||
, volume(volume)
|
||||
, local(local)
|
||||
, secret(secret)
|
||||
, id(0)
|
||||
, access(0)
|
||||
, fileIsOpen(false)
|
||||
, size(size)
|
||||
, type(mtpc_storage_fileUnknown)
|
||||
, _location(location)
|
||||
, _id(0)
|
||||
, _access(0)
|
||||
, _fileIsOpen(false)
|
||||
, _toCache(LoadToCacheAsWell)
|
||||
, _fromCloud(fromCloud)
|
||||
, _size(size)
|
||||
, _type(mtpc_storage_fileUnknown)
|
||||
, _localTaskId(0) {
|
||||
LoaderQueues::iterator i = queues.find(dc);
|
||||
LoaderQueues::iterator i = queues.find(_dc);
|
||||
if (i == queues.cend()) {
|
||||
i = queues.insert(dc, mtpFileLoaderQueue());
|
||||
i = queues.insert(_dc, mtpFileLoaderQueue());
|
||||
}
|
||||
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)
|
||||
, next(0)
|
||||
, priority(0)
|
||||
, _paused(false)
|
||||
, inQueue(false)
|
||||
, complete(false)
|
||||
, _autoLoading(autoLoading)
|
||||
, _inQueue(false)
|
||||
, _complete(false)
|
||||
, _localStatus(LocalNotTried)
|
||||
, skippedBytes(0)
|
||||
, nextRequestOffset(0)
|
||||
, lastComplete(false)
|
||||
, dc(dc)
|
||||
, _skippedBytes(0)
|
||||
, _nextRequestOffset(0)
|
||||
, _lastComplete(false)
|
||||
, _dc(dc)
|
||||
, _locationType(type)
|
||||
, volume(0)
|
||||
, local(0)
|
||||
, secret(0)
|
||||
, id(id)
|
||||
, access(access)
|
||||
, file(to)
|
||||
, fname(to)
|
||||
, fileIsOpen(false)
|
||||
, duplicateInData(todata)
|
||||
, size(size)
|
||||
, type(mtpc_storage_fileUnknown)
|
||||
, _location(0)
|
||||
, _id(id)
|
||||
, _access(access)
|
||||
, _file(to)
|
||||
, _fname(to)
|
||||
, _fileIsOpen(false)
|
||||
, _toCache(toCache)
|
||||
, _fromCloud(fromCloud)
|
||||
, _size(size)
|
||||
, _type(mtpc_storage_fileUnknown)
|
||||
, _localTaskId(0) {
|
||||
LoaderQueues::iterator i = queues.find(MTP::dld[0] + dc);
|
||||
LoaderQueues::iterator i = queues.find(MTP::dld[0] + _dc);
|
||||
if (i == queues.cend()) {
|
||||
i = queues.insert(MTP::dld[0] + dc, mtpFileLoaderQueue());
|
||||
i = queues.insert(MTP::dld[0] + _dc, mtpFileLoaderQueue());
|
||||
}
|
||||
queue = &i.value();
|
||||
}
|
||||
|
@ -124,40 +125,45 @@ QPixmap mtpFileLoader::imagePixmap() const {
|
|||
|
||||
void mtpFileLoader::readImage() const {
|
||||
QByteArray format;
|
||||
switch (type) {
|
||||
switch (_type) {
|
||||
case mtpc_storage_fileGif: format = "GIF"; break;
|
||||
case mtpc_storage_fileJpeg: format = "JPG"; break;
|
||||
case mtpc_storage_filePng: format = "PNG"; 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()) {
|
||||
_imageFormat = format;
|
||||
}
|
||||
}
|
||||
|
||||
float64 mtpFileLoader::currentProgress() const {
|
||||
if (complete) return 1;
|
||||
if (_complete) return 1;
|
||||
if (!fullSize()) return 0;
|
||||
return float64(currentOffset()) / fullSize();
|
||||
}
|
||||
|
||||
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 {
|
||||
return size;
|
||||
return _size;
|
||||
}
|
||||
|
||||
void mtpFileLoader::setFileName(const QString &fileName) {
|
||||
if (duplicateInData && fname.isEmpty() && !fileName.isEmpty()) {
|
||||
file.setFileName(fname = fileName);
|
||||
}
|
||||
bool mtpFileLoader::setFileName(const QString &fileName) {
|
||||
if (_toCache != LoadToCacheAsWell || !_fname.isEmpty()) return fileName.isEmpty();
|
||||
_fname = fileName;
|
||||
_file.setFileName(_fname);
|
||||
return true;
|
||||
}
|
||||
|
||||
void mtpFileLoader::permitLoadFromCloud() {
|
||||
_fromCloud = LoadFromCloudOrLocal;
|
||||
}
|
||||
|
||||
uint64 mtpFileLoader::objId() const {
|
||||
return id;
|
||||
return _id;
|
||||
}
|
||||
|
||||
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() {
|
||||
if (complete || lastComplete || (!requests.isEmpty() && !size)) return false;
|
||||
if (size && nextRequestOffset >= size) return false;
|
||||
if (_complete || _lastComplete || (!_requests.isEmpty() && !_size)) return false;
|
||||
if (_size && _nextRequestOffset >= _size) return false;
|
||||
|
||||
int32 limit = DocumentDownloadPartSize;
|
||||
MTPInputFileLocation loc;
|
||||
switch (_locationType) {
|
||||
case UnknownFileLocation:
|
||||
loc = MTP_inputFileLocation(MTP_long(volume), MTP_int(local), MTP_long(secret));
|
||||
if (_location) {
|
||||
loc = MTP_inputFileLocation(MTP_long(_location->volume()), MTP_int(_location->local()), MTP_long(_location->secret()));
|
||||
limit = DownloadPartSize;
|
||||
break;
|
||||
case VideoFileLocation:
|
||||
loc = MTP_inputVideoFileLocation(MTP_long(id), MTP_long(access));
|
||||
break;
|
||||
case AudioFileLocation:
|
||||
loc = MTP_inputAudioFileLocation(MTP_long(id), MTP_long(access));
|
||||
break;
|
||||
case DocumentFileLocation:
|
||||
loc = MTP_inputDocumentFileLocation(MTP_long(id), MTP_long(access));
|
||||
break;
|
||||
default:
|
||||
finishFail();
|
||||
return false;
|
||||
break;
|
||||
} else {
|
||||
switch (_locationType) {
|
||||
case VideoFileLocation:
|
||||
loc = MTP_inputVideoFileLocation(MTP_long(_id), MTP_long(_access));
|
||||
break;
|
||||
case AudioFileLocation:
|
||||
loc = MTP_inputAudioFileLocation(MTP_long(_id), MTP_long(_access));
|
||||
break;
|
||||
case DocumentFileLocation:
|
||||
loc = MTP_inputDocumentFileLocation(MTP_long(_id), MTP_long(_access));
|
||||
break;
|
||||
default:
|
||||
cancel(true);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int32 offset = nextRequestOffset, dcIndex = 0;
|
||||
DataRequested &dr(_dataRequested[dc]);
|
||||
if (size) {
|
||||
int32 offset = _nextRequestOffset, dcIndex = 0;
|
||||
DataRequested &dr(DataRequestedMap[_dc]);
|
||||
if (_size) {
|
||||
for (int32 i = 1; i < MTPDownloadSessionsCount; ++i) {
|
||||
if (dr.v[i] < dr.v[dcIndex]) {
|
||||
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;
|
||||
dr.v[dcIndex] += limit;
|
||||
requests.insert(reqId, dcIndex);
|
||||
nextRequestOffset += limit;
|
||||
_requests.insert(reqId, dcIndex);
|
||||
_nextRequestOffset += limit;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRequestId req) {
|
||||
// uint64 ms = getms();
|
||||
Requests::iterator i = requests.find(req);
|
||||
if (i == requests.cend()) return loadNext();
|
||||
Requests::iterator i = _requests.find(req);
|
||||
if (i == _requests.cend()) return loadNext();
|
||||
|
||||
int32 limit = (_locationType == UnknownFileLocation) ? DownloadPartSize : DocumentDownloadPartSize;
|
||||
int32 dcIndex = i.value();
|
||||
_dataRequested[dc].v[dcIndex] -= limit;
|
||||
DataRequestedMap[_dc].v[dcIndex] -= limit;
|
||||
|
||||
--queue->queries;
|
||||
requests.erase(i);
|
||||
_requests.erase(i);
|
||||
|
||||
const MTPDupload_file &d(result.c_upload_file());
|
||||
const string &bytes(d.vbytes.c_string().v);
|
||||
if (bytes.size()) {
|
||||
if (fileIsOpen) {
|
||||
int64 fsize = file.size();
|
||||
if (_fileIsOpen) {
|
||||
int64 fsize = _file.size();
|
||||
if (offset < fsize) {
|
||||
skippedBytes -= bytes.size();
|
||||
_skippedBytes -= bytes.size();
|
||||
} else if (offset > fsize) {
|
||||
skippedBytes += offset - fsize;
|
||||
_skippedBytes += offset - fsize;
|
||||
}
|
||||
file.seek(offset);
|
||||
if (file.write(bytes.data(), bytes.size()) != qint64(bytes.size())) {
|
||||
return finishFail();
|
||||
_file.seek(offset);
|
||||
if (_file.write(bytes.data(), bytes.size()) != qint64(bytes.size())) {
|
||||
return cancel(true);
|
||||
}
|
||||
} else {
|
||||
data.reserve(offset + bytes.size());
|
||||
if (offset > data.size()) {
|
||||
skippedBytes += offset - data.size();
|
||||
data.resize(offset);
|
||||
_data.reserve(offset + bytes.size());
|
||||
if (offset > _data.size()) {
|
||||
_skippedBytes += offset - _data.size();
|
||||
_data.resize(offset);
|
||||
}
|
||||
if (offset == data.size()) {
|
||||
data.append(bytes.data(), bytes.size());
|
||||
if (offset == _data.size()) {
|
||||
_data.append(bytes.data(), bytes.size());
|
||||
} else {
|
||||
skippedBytes -= bytes.size();
|
||||
if (int64(offset + bytes.size()) > data.size()) {
|
||||
data.resize(offset + bytes.size());
|
||||
_skippedBytes -= bytes.size();
|
||||
if (int64(offset + bytes.size()) > _data.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
|
||||
lastComplete = true;
|
||||
_lastComplete = true;
|
||||
}
|
||||
if (requests.isEmpty() && (lastComplete || (size && nextRequestOffset >= size))) {
|
||||
if (!fname.isEmpty() && duplicateInData) {
|
||||
if (!fileIsOpen) fileIsOpen = file.open(QIODevice::WriteOnly);
|
||||
if (!fileIsOpen) {
|
||||
return finishFail();
|
||||
if (_requests.isEmpty() && (_lastComplete || (_size && _nextRequestOffset >= _size))) {
|
||||
if (!_fname.isEmpty() && (_toCache == LoadToCacheAsWell)) {
|
||||
if (!_fileIsOpen) _fileIsOpen = _file.open(QIODevice::WriteOnly);
|
||||
if (!_fileIsOpen) {
|
||||
return cancel(true);
|
||||
}
|
||||
if (file.write(data) != qint64(data.size())) {
|
||||
return finishFail();
|
||||
if (_file.write(_data) != qint64(_data.size())) {
|
||||
return cancel(true);
|
||||
}
|
||||
}
|
||||
type = d.vtype.type();
|
||||
complete = true;
|
||||
if (fileIsOpen) {
|
||||
file.close();
|
||||
fileIsOpen = false;
|
||||
psPostprocessFile(QFileInfo(file).absoluteFilePath());
|
||||
_type = d.vtype.type();
|
||||
_complete = true;
|
||||
if (_fileIsOpen) {
|
||||
_file.close();
|
||||
_fileIsOpen = false;
|
||||
psPostprocessFile(QFileInfo(_file).absoluteFilePath());
|
||||
}
|
||||
removeFromQueue();
|
||||
|
||||
emit App::wnd()->imageLoaded();
|
||||
|
||||
if (!queue->queries) {
|
||||
App::app()->killDownloadSessionsStart(dc);
|
||||
App::app()->killDownloadSessionsStart(_dc);
|
||||
}
|
||||
|
||||
if (_localStatus == LocalNotFound || _localStatus == LocalFailed) {
|
||||
if (_locationType != UnknownFileLocation) { // audio, video, document
|
||||
MediaKey mkey = mediaKey(_locationType, dc, id);
|
||||
if (!fname.isEmpty()) {
|
||||
Local::writeFileLocation(mkey, FileLocation(mtpToStorageType(type), fname));
|
||||
MediaKey mkey = mediaKey(_locationType, _dc, _id);
|
||||
if (!_fname.isEmpty()) {
|
||||
Local::writeFileLocation(mkey, FileLocation(mtpToStorageType(_type), _fname));
|
||||
}
|
||||
if (duplicateInData) {
|
||||
if (_toCache == LoadToCacheAsWell) {
|
||||
if (_locationType == DocumentFileLocation) {
|
||||
Local::writeStickerImage(mkey, data);
|
||||
Local::writeStickerImage(mkey, _data);
|
||||
} else if (_locationType == AudioFileLocation) {
|
||||
Local::writeAudio(mkey, data);
|
||||
Local::writeAudio(mkey, _data);
|
||||
}
|
||||
}
|
||||
} 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) {
|
||||
if (mtpIsFlood(error)) return false;
|
||||
|
||||
finishFail();
|
||||
cancel(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void mtpFileLoader::removeFromQueue() {
|
||||
if (!inQueue) return;
|
||||
if (!_inQueue) return;
|
||||
if (next) {
|
||||
next->prev = prev;
|
||||
}
|
||||
|
@ -350,7 +340,7 @@ void mtpFileLoader::removeFromQueue() {
|
|||
queue->start = next;
|
||||
}
|
||||
next = prev = 0;
|
||||
inQueue = false;
|
||||
_inQueue = false;
|
||||
}
|
||||
|
||||
void mtpFileLoader::pause() {
|
||||
|
@ -366,11 +356,11 @@ bool mtpFileLoader::tryLoadLocal() {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (_locationType == UnknownFileLocation) {
|
||||
_localTaskId = Local::startImageLoad(storageKey(dc, volume, local), this);
|
||||
if (_location) {
|
||||
_localTaskId = Local::startImageLoad(storageKey(*_location), this);
|
||||
} else {
|
||||
if (duplicateInData) {
|
||||
MediaKey mkey = mediaKey(_locationType, dc, id);
|
||||
if (_toCache == LoadToCacheAsWell) {
|
||||
MediaKey mkey = mediaKey(_locationType, _dc, _id);
|
||||
if (_locationType == DocumentFileLocation) {
|
||||
_localTaskId = Local::startStickerImageLoad(mkey, this);
|
||||
} else if (_locationType == AudioFileLocation) {
|
||||
|
@ -379,37 +369,14 @@ bool mtpFileLoader::tryLoadLocal() {
|
|||
}
|
||||
}
|
||||
|
||||
if (data.isEmpty()) {
|
||||
if (_localTaskId) {
|
||||
_localStatus = LocalLoading;
|
||||
return true;
|
||||
}
|
||||
_localStatus = LocalNotFound;
|
||||
return false;
|
||||
if (_localStatus != LocalNotTried) {
|
||||
return _complete;
|
||||
} else if (_localTaskId) {
|
||||
_localStatus = LocalLoading;
|
||||
return true;
|
||||
}
|
||||
|
||||
_localStatus = LocalLoaded;
|
||||
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;
|
||||
_localStatus = LocalNotFound;
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
data = result.data;
|
||||
type = mtpFromStorageType(result.type);
|
||||
_data = result.data;
|
||||
_type = mtpFromStorageType(result.type);
|
||||
if (!imagePixmap.isNull()) {
|
||||
_imageFormat = imageFormat;
|
||||
_imagePixmap = imagePixmap;
|
||||
}
|
||||
_localStatus = LocalLoaded;
|
||||
if (!fname.isEmpty() && duplicateInData) {
|
||||
if (!fileIsOpen) fileIsOpen = file.open(QIODevice::WriteOnly);
|
||||
if (!fileIsOpen) {
|
||||
finishFail();
|
||||
if (!_fname.isEmpty() && _toCache == LoadToCacheAsWell) {
|
||||
if (!_fileIsOpen) _fileIsOpen = _file.open(QIODevice::WriteOnly);
|
||||
if (!_fileIsOpen) {
|
||||
cancel(true);
|
||||
return;
|
||||
}
|
||||
if (file.write(data) != qint64(data.size())) {
|
||||
finishFail();
|
||||
if (_file.write(_data) != qint64(_data.size())) {
|
||||
cancel(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
complete = true;
|
||||
if (fileIsOpen) {
|
||||
file.close();
|
||||
fileIsOpen = false;
|
||||
psPostprocessFile(QFileInfo(file).absoluteFilePath());
|
||||
|
||||
_complete = true;
|
||||
if (_fileIsOpen) {
|
||||
_file.close();
|
||||
_fileIsOpen = false;
|
||||
psPostprocessFile(QFileInfo(_file).absoluteFilePath());
|
||||
}
|
||||
emit App::wnd()->imageLoaded();
|
||||
emit progress(this);
|
||||
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) {
|
||||
if (_paused) {
|
||||
_paused = false;
|
||||
}
|
||||
if (complete || tryLoadLocal()) return;
|
||||
if (_complete || tryLoadLocal()) return;
|
||||
|
||||
if (!fname.isEmpty() && !duplicateInData && !fileIsOpen) {
|
||||
fileIsOpen = file.open(QIODevice::WriteOnly);
|
||||
if (!fileIsOpen) {
|
||||
return finishFail();
|
||||
if (_fromCloud == LoadFromLocalOnly) {
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_fname.isEmpty() && _toCache == LoadToFileOnly && !_fileIsOpen) {
|
||||
_fileIsOpen = _file.open(QIODevice::WriteOnly);
|
||||
if (!_fileIsOpen) {
|
||||
return cancel(true);
|
||||
}
|
||||
}
|
||||
|
||||
mtpFileLoader *before = 0, *after = 0;
|
||||
if (prior) {
|
||||
if (inQueue && priority == _priority) {
|
||||
if (_inQueue && priority == GlobalPriority) {
|
||||
if (loadFirst) {
|
||||
if (!prev) return startLoading(loadFirst, prior);
|
||||
before = queue->start;
|
||||
} else {
|
||||
if (!next || next->priority < _priority) return startLoading(loadFirst, prior);
|
||||
if (!next || next->priority < GlobalPriority) return startLoading(loadFirst, prior);
|
||||
after = next;
|
||||
while (after->next && after->next->priority == _priority) {
|
||||
while (after->next && after->next->priority == GlobalPriority) {
|
||||
after = after->next;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
priority = _priority;
|
||||
priority = GlobalPriority;
|
||||
if (loadFirst) {
|
||||
if (inQueue && !prev) return startLoading(loadFirst, prior);
|
||||
if (_inQueue && !prev) return startLoading(loadFirst, prior);
|
||||
before = queue->start;
|
||||
} else {
|
||||
if (inQueue) {
|
||||
if (next && next->priority == _priority) {
|
||||
if (_inQueue) {
|
||||
if (next && next->priority == GlobalPriority) {
|
||||
after = next;
|
||||
} else if (prev && prev->priority < _priority) {
|
||||
} else if (prev && prev->priority < GlobalPriority) {
|
||||
before = prev;
|
||||
while (before->prev && before->prev->priority < _priority) {
|
||||
while (before->prev && before->prev->priority < GlobalPriority) {
|
||||
before = before->prev;
|
||||
}
|
||||
} else {
|
||||
return startLoading(loadFirst, prior);
|
||||
}
|
||||
} else {
|
||||
if (queue->start && queue->start->priority == _priority) {
|
||||
if (queue->start && queue->start->priority == GlobalPriority) {
|
||||
after = queue->start;
|
||||
} else {
|
||||
before = queue->start;
|
||||
}
|
||||
}
|
||||
if (after) {
|
||||
while (after->next && after->next->priority == _priority) {
|
||||
while (after->next && after->next->priority == GlobalPriority) {
|
||||
after = after->next;
|
||||
}
|
||||
}
|
||||
|
@ -533,20 +480,20 @@ void mtpFileLoader::start(bool loadFirst, bool prior) {
|
|||
}
|
||||
} else {
|
||||
if (loadFirst) {
|
||||
if (inQueue && (!prev || prev->priority == _priority)) return startLoading(loadFirst, prior);
|
||||
if (_inQueue && (!prev || prev->priority == GlobalPriority)) return startLoading(loadFirst, prior);
|
||||
before = prev;
|
||||
while (before->prev && before->prev->priority != _priority) {
|
||||
while (before->prev && before->prev->priority != GlobalPriority) {
|
||||
before = before->prev;
|
||||
}
|
||||
} else {
|
||||
if (inQueue && !next) return startLoading(loadFirst, prior);
|
||||
if (_inQueue && !next) return startLoading(loadFirst, prior);
|
||||
after = queue->end;
|
||||
}
|
||||
}
|
||||
|
||||
removeFromQueue();
|
||||
|
||||
inQueue = true;
|
||||
_inQueue = true;
|
||||
if (!queue->start) {
|
||||
queue->start = queue->end = this;
|
||||
} else if (before) {
|
||||
|
@ -576,40 +523,50 @@ void mtpFileLoader::start(bool loadFirst, bool prior) {
|
|||
}
|
||||
|
||||
void mtpFileLoader::cancel() {
|
||||
cancel(false);
|
||||
}
|
||||
|
||||
void mtpFileLoader::cancel(bool fail) {
|
||||
bool started = currentOffset(true) > 0;
|
||||
cancelRequests();
|
||||
type = mtpc_storage_fileUnknown;
|
||||
complete = true;
|
||||
if (fileIsOpen) {
|
||||
file.close();
|
||||
fileIsOpen = false;
|
||||
file.remove();
|
||||
_type = mtpc_storage_fileUnknown;
|
||||
_complete = true;
|
||||
if (_fileIsOpen) {
|
||||
_file.close();
|
||||
_fileIsOpen = false;
|
||||
_file.remove();
|
||||
}
|
||||
data = QByteArray();
|
||||
file.setFileName(QString());
|
||||
emit progress(this);
|
||||
_data = QByteArray();
|
||||
if (fail) {
|
||||
emit failed(this, started);
|
||||
} else {
|
||||
emit progress(this);
|
||||
}
|
||||
_fname = QString();
|
||||
_file.setFileName(_fname);
|
||||
loadNext();
|
||||
}
|
||||
|
||||
void mtpFileLoader::cancelRequests() {
|
||||
if (requests.isEmpty()) return;
|
||||
if (_requests.isEmpty()) return;
|
||||
|
||||
int32 limit = (_locationType == UnknownFileLocation) ? DownloadPartSize : DocumentDownloadPartSize;
|
||||
DataRequested &dr(_dataRequested[dc]);
|
||||
for (Requests::const_iterator i = requests.cbegin(), e = requests.cend(); i != e; ++i) {
|
||||
DataRequested &dr(DataRequestedMap[_dc]);
|
||||
for (Requests::const_iterator i = _requests.cbegin(), e = _requests.cend(); i != e; ++i) {
|
||||
MTP::cancel(i.key());
|
||||
int32 dcIndex = i.value();
|
||||
dr.v[dcIndex] -= limit;
|
||||
}
|
||||
queue->queries -= requests.size();
|
||||
requests.clear();
|
||||
queue->queries -= _requests.size();
|
||||
_requests.clear();
|
||||
|
||||
if (!queue->queries) {
|
||||
App::app()->killDownloadSessionsStart(dc);
|
||||
App::app()->killDownloadSessionsStart(_dc);
|
||||
}
|
||||
}
|
||||
|
||||
void mtpFileLoader::startLoading(bool loadFirst, bool prior) {
|
||||
if ((queue->queries >= MaxFileQueries && (!loadFirst || !prior)) || complete) return;
|
||||
if ((queue->queries >= MaxFileQueries && (!loadFirst || !prior)) || _complete) return;
|
||||
loadPart();
|
||||
}
|
||||
|
||||
|
@ -623,6 +580,6 @@ mtpFileLoader::~mtpFileLoader() {
|
|||
|
||||
namespace MTP {
|
||||
void clearLoaderPriorities() {
|
||||
++_priority;
|
||||
++GlobalPriority;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,7 +100,6 @@ struct StorageImageSaved {
|
|||
|
||||
enum LocalLoadStatus {
|
||||
LocalNotTried,
|
||||
LocalNeedsTry,
|
||||
LocalNotFound,
|
||||
LocalLoading,
|
||||
LocalLoaded,
|
||||
|
@ -109,55 +108,64 @@ enum LocalLoadStatus {
|
|||
|
||||
typedef void *TaskId; // no interface, just id
|
||||
|
||||
enum LoadFromCloudSetting {
|
||||
LoadFromCloudOrLocal,
|
||||
LoadFromLocalOnly,
|
||||
};
|
||||
enum LoadToCacheSetting {
|
||||
LoadToFileOnly,
|
||||
LoadToCacheAsWell,
|
||||
};
|
||||
|
||||
struct mtpFileLoaderQueue;
|
||||
class StorageImageLocation;
|
||||
class mtpFileLoader : public QObject, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
mtpFileLoader(int32 dc, const uint64 &volume, int32 local, const uint64 &secret, int32 size = 0);
|
||||
mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, LocationType type, const QString &to, int32 size, bool todata = false);
|
||||
mtpFileLoader(const StorageImageLocation *location, int32 size, LoadFromCloudSetting fromCloud, bool autoLoading);
|
||||
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 {
|
||||
return complete;
|
||||
return _complete;
|
||||
}
|
||||
mtpTypeId fileType() const {
|
||||
return type;
|
||||
return _type;
|
||||
}
|
||||
const QByteArray &bytes() const {
|
||||
return data;
|
||||
return _data;
|
||||
}
|
||||
QByteArray imageFormat() const;
|
||||
QPixmap imagePixmap() const;
|
||||
QString fileName() const {
|
||||
return fname;
|
||||
return _fname;
|
||||
}
|
||||
float64 currentProgress() const;
|
||||
int32 currentOffset(bool includeSkipped = false) 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 start(bool loadFirst = false, bool prior = true);
|
||||
void cancel();
|
||||
|
||||
bool loading() const {
|
||||
return inQueue;
|
||||
return _inQueue;
|
||||
}
|
||||
|
||||
bool paused() const {
|
||||
return _paused;
|
||||
}
|
||||
|
||||
bool started() const {
|
||||
return inQueue || _paused;
|
||||
return _inQueue || _paused;
|
||||
}
|
||||
|
||||
bool loadingLocal() const {
|
||||
return (_localStatus == LocalLoading);
|
||||
}
|
||||
|
||||
bool localAvailable() const;
|
||||
bool autoLoading() const {
|
||||
return _autoLoading;
|
||||
}
|
||||
|
||||
uint64 objId() const;
|
||||
|
||||
|
@ -176,45 +184,44 @@ signals:
|
|||
private:
|
||||
|
||||
mtpFileLoaderQueue *queue;
|
||||
bool _paused, inQueue, complete;
|
||||
bool _paused, _autoLoading, _inQueue, _complete;
|
||||
mutable LocalLoadStatus _localStatus;
|
||||
|
||||
bool tryLoadLocal();
|
||||
void cancelRequests();
|
||||
|
||||
typedef QMap<mtpRequestId, int32> Requests;
|
||||
Requests requests;
|
||||
int32 skippedBytes;
|
||||
int32 nextRequestOffset;
|
||||
bool lastComplete;
|
||||
Requests _requests;
|
||||
int32 _skippedBytes;
|
||||
int32 _nextRequestOffset;
|
||||
bool _lastComplete;
|
||||
|
||||
void startLoading(bool loadFirst, bool prior);
|
||||
void removeFromQueue();
|
||||
|
||||
void loadNext();
|
||||
void finishFail();
|
||||
void cancel(bool failed);
|
||||
bool loadPart();
|
||||
void partLoaded(int32 offset, const MTPupload_File &result, mtpRequestId req);
|
||||
bool partFailed(const RPCError &error);
|
||||
|
||||
int32 dc;
|
||||
int32 _dc;
|
||||
LocationType _locationType;
|
||||
const StorageImageLocation *_location;
|
||||
|
||||
uint64 volume; // for photo locations
|
||||
int32 local;
|
||||
uint64 secret;
|
||||
uint64 _id; // for other locations
|
||||
uint64 _access;
|
||||
QFile _file;
|
||||
QString _fname;
|
||||
bool _fileIsOpen;
|
||||
|
||||
uint64 id; // for other locations
|
||||
uint64 access;
|
||||
QFile file;
|
||||
QString fname;
|
||||
bool fileIsOpen;
|
||||
bool duplicateInData;
|
||||
LoadToCacheSetting _toCache;
|
||||
LoadFromCloudSetting _fromCloud;
|
||||
|
||||
QByteArray data;
|
||||
QByteArray _data;
|
||||
|
||||
int32 size;
|
||||
mtpTypeId type;
|
||||
int32 _size;
|
||||
mtpTypeId _type;
|
||||
|
||||
TaskId _localTaskId;
|
||||
mutable QByteArray _imageFormat;
|
||||
|
@ -222,3 +229,5 @@ private:
|
|||
void readImage() const;
|
||||
|
||||
};
|
||||
|
||||
static mtpFileLoader * const CancelledFileLoader = reinterpret_cast<mtpFileLoader * const>(&SharedMemoryLocation0);
|
||||
|
|
|
@ -1271,7 +1271,7 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
if (lnkPhoto) {
|
||||
_menu->addAction(lang(lng_context_open_image), this, SLOT(openContextUrl()))->setEnabled(true);
|
||||
} 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);
|
||||
} else {
|
||||
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());
|
||||
AudioLink *lnkAudio = dynamic_cast<AudioLink*>(_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 (loader) loader->cancel();
|
||||
if (lnkVideo) {
|
||||
lnkVideo->video()->cancel();
|
||||
} else if (lnkAudio) {
|
||||
lnkAudio->audio()->cancel();
|
||||
} else if (lnkDocument) {
|
||||
lnkDocument->document()->cancel();
|
||||
}
|
||||
}
|
||||
|
||||
void OverviewInner::showContextInFolder() {
|
||||
|
|
|
@ -324,12 +324,8 @@ void PlayerWidget::preloadNext() {
|
|||
if (next) {
|
||||
if (HistoryDocument *document = static_cast<HistoryDocument*>(next->getMedia())) {
|
||||
DocumentData *d = document->getDocument();
|
||||
if (d->location(true).isEmpty() && d->data.isEmpty()) {
|
||||
if (!d->loader) {
|
||||
DocumentOpenLink::doOpen(d);
|
||||
d->openOnSave = 0;
|
||||
d->openOnSaveMsgId = FullMsgId();
|
||||
}
|
||||
if (!d->loaded(true)) {
|
||||
DocumentOpenLink::doOpen(d, ActionOnLoadNone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -648,12 +644,12 @@ void PlayerWidget::updateState(SongMsgId playing, AudioPlayerState playingState,
|
|||
float64 progress = 0.;
|
||||
int32 loaded;
|
||||
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);
|
||||
progress = duration ? snap(float64(position) / duration, 0., 1.) : 0.;
|
||||
loaded = duration ? _song.song->size : 0;
|
||||
} else {
|
||||
loaded = _song.song->loader ? _song.song->loader->currentOffset() : 0;
|
||||
loaded = _song.song->loading() ? _song.song->loadOffset() : 0;
|
||||
time = formatDownloadText(loaded, _song.song->size);
|
||||
loadProgress = snap(float64(loaded) / qMax(_song.song->size, 1), 0., 1.);
|
||||
}
|
||||
|
|
|
@ -195,7 +195,7 @@ DeclareRefSetting(EmojiColorVariants, EmojiVariants);
|
|||
|
||||
RecentEmojiPack &cGetRecentEmojis();
|
||||
|
||||
struct DocumentData;
|
||||
class DocumentData;
|
||||
typedef QVector<DocumentData*> StickerPack;
|
||||
DeclareSetting(int32, StickersHash);
|
||||
|
||||
|
|
|
@ -176,12 +176,6 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : TWidget(parent)
|
|||
|
||||
, _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
|
||||
, _localStorageClear(this, lang(lng_local_storage_clear))
|
||||
, _localStorageHeight(1)
|
||||
|
@ -189,6 +183,12 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : TWidget(parent)
|
|||
, _storageClearedWidth(st::linkFont->width(lang(lng_local_storage_cleared)))
|
||||
, _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
|
||||
, _passcodeEdit(this, lang(cHasPasscode() ? lng_passcode_change : lng_passcode_turn_on))
|
||||
, _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)
|
||||
, _supportGetRequest(0) {
|
||||
if (self()) {
|
||||
self()->photo->load();
|
||||
|
||||
connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
|
||||
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(&_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
|
||||
connect(&_localStorageClear, SIGNAL(clicked()), this, SLOT(onLocalStorageClear()));
|
||||
switch (App::wnd()->localStorageState()) {
|
||||
|
@ -309,6 +304,13 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : TWidget(parent)
|
|||
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
|
||||
connect(&_passcodeEdit, SIGNAL(clicked()), this, SLOT(onPasscode()));
|
||||
connect(&_passcodeTurnOff, SIGNAL(clicked()), this, SLOT(onPasscodeOff()));
|
||||
|
@ -553,45 +555,6 @@ void SettingsInner::paintEvent(QPaintEvent *e) {
|
|||
top += st::setLittleSkip;
|
||||
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
|
||||
p.setFont(st::setHeaderFont->f);
|
||||
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));
|
||||
}
|
||||
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
|
||||
|
@ -734,15 +736,6 @@ void SettingsInner::resizeEvent(QResizeEvent *e) {
|
|||
top += st::setLittleSkip;
|
||||
_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
|
||||
_localStorageClear.move(_left + st::setWidth - _localStorageClear.width(), top + st::setHeaderTop + st::setHeaderFont->ascent - st::linkFont->ascent);
|
||||
top += st::setHeaderSkip;
|
||||
|
@ -753,6 +746,15 @@ void SettingsInner::resizeEvent(QResizeEvent *e) {
|
|||
_localStorageHeight = 1;
|
||||
}
|
||||
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
|
||||
|
@ -1079,6 +1081,13 @@ void SettingsInner::showAll() {
|
|||
_autoDownload.hide();
|
||||
}
|
||||
|
||||
// local storage
|
||||
if (self() && _storageClearState == TempDirExists) {
|
||||
_localStorageClear.show();
|
||||
} else {
|
||||
_localStorageClear.hide();
|
||||
}
|
||||
|
||||
// chat background
|
||||
if (self()) {
|
||||
_backFromGallery.show();
|
||||
|
@ -1090,13 +1099,6 @@ void SettingsInner::showAll() {
|
|||
_tileBackground.hide();
|
||||
}
|
||||
|
||||
// local storage
|
||||
if (self() && _storageClearState == TempDirExists) {
|
||||
_localStorageClear.show();
|
||||
} else {
|
||||
_localStorageClear.hide();
|
||||
}
|
||||
|
||||
// advanced
|
||||
if (self()) {
|
||||
_passcodeEdit.show();
|
||||
|
|
|
@ -262,18 +262,18 @@ private:
|
|||
TempDirClearState _tempDirClearState;
|
||||
LinkButton _autoDownload;
|
||||
|
||||
// chat background
|
||||
QPixmap _background;
|
||||
LinkButton _backFromGallery, _backFromFile;
|
||||
FlatCheckbox _tileBackground;
|
||||
bool _needBackgroundUpdate;
|
||||
|
||||
// local storage
|
||||
LinkButton _localStorageClear;
|
||||
int32 _localStorageHeight;
|
||||
int32 _storageClearingWidth, _storageClearedWidth, _storageClearFailedWidth;
|
||||
TempDirClearState _storageClearState;
|
||||
|
||||
// chat background
|
||||
QPixmap _background;
|
||||
LinkButton _backFromGallery, _backFromFile;
|
||||
FlatCheckbox _tileBackground;
|
||||
bool _needBackgroundUpdate;
|
||||
|
||||
// advanced
|
||||
LinkButton _passcodeEdit, _passcodeTurnOff, _autoLock;
|
||||
QString _autoLockText;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -340,7 +340,7 @@ enum UserBlockedStatus {
|
|||
UserIsNotBlocked,
|
||||
};
|
||||
|
||||
struct PhotoData;
|
||||
class PhotoData;
|
||||
class UserData : public PeerData {
|
||||
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);
|
||||
}
|
||||
|
||||
enum ActionOnLoad {
|
||||
ActionOnLoadNone,
|
||||
ActionOnLoadOpen,
|
||||
ActionOnLoadOpenWith,
|
||||
ActionOnLoadPlayInline
|
||||
};
|
||||
|
||||
typedef QMap<char, QPixmap> PreparedPhotoThumbs;
|
||||
struct PhotoData {
|
||||
PhotoData(const PhotoId &id, const uint64 &access = 0, int32 date = 0, const ImagePtr &thumb = ImagePtr(), const ImagePtr &medium = ImagePtr(), const ImagePtr &full = ImagePtr()) :
|
||||
id(id), access(access), date(date), thumb(thumb), medium(medium), full(full), peer(0) {
|
||||
}
|
||||
void forget() {
|
||||
thumb->forget();
|
||||
replyPreview->forget();
|
||||
medium->forget();
|
||||
full->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;
|
||||
}
|
||||
class PhotoData {
|
||||
public:
|
||||
PhotoData(const PhotoId &id, const uint64 &access = 0, int32 date = 0, const ImagePtr &thumb = ImagePtr(), const ImagePtr &medium = ImagePtr(), const ImagePtr &full = ImagePtr());
|
||||
|
||||
void automaticLoad(const HistoryItem *item);
|
||||
|
||||
bool loaded() const;
|
||||
bool loading() const;
|
||||
bool displayLoading() const;
|
||||
void cancel();
|
||||
float64 progress() const;
|
||||
int32 loadOffset() const;
|
||||
bool uploading() const;
|
||||
|
||||
void forget();
|
||||
ImagePtr makeReplyPreview();
|
||||
|
||||
~PhotoData();
|
||||
|
||||
PhotoId id;
|
||||
uint64 access;
|
||||
int32 date;
|
||||
|
@ -754,17 +757,22 @@ struct PhotoData {
|
|||
PeerData *peer; // for chat and channel photos connection
|
||||
// geo, caption
|
||||
|
||||
int32 cachew;
|
||||
QPixmap cache;
|
||||
struct UploadingData {
|
||||
UploadingData(int32 size) : offset(0), size(size) {
|
||||
}
|
||||
int32 offset, size;
|
||||
};
|
||||
UploadingData *uploadingData;
|
||||
|
||||
// int32 cachew;
|
||||
// QPixmap cache;
|
||||
};
|
||||
|
||||
class PhotoLink : public ITextLink {
|
||||
TEXT_LINK_CLASS(PhotoLink)
|
||||
|
||||
public:
|
||||
PhotoLink(PhotoData *photo) : _photo(photo), _peer(0) {
|
||||
}
|
||||
PhotoLink(PhotoData *photo, PeerData *peer) : _photo(photo), _peer(peer) {
|
||||
PhotoLink(PhotoData *photo, PeerData *peer = 0) : _photo(photo), _peer(peer) {
|
||||
}
|
||||
void onClick(Qt::MouseButton button) const;
|
||||
PhotoData *photo() const {
|
||||
|
@ -777,6 +785,17 @@ public:
|
|||
private:
|
||||
PhotoData *_photo;
|
||||
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 {
|
||||
|
@ -786,52 +805,34 @@ enum FileStatus {
|
|||
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);
|
||||
|
||||
void forget() {
|
||||
thumb->forget();
|
||||
replyPreview->forget();
|
||||
void automaticLoad(const HistoryItem *item) {
|
||||
}
|
||||
|
||||
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) {
|
||||
mtpFileLoader *l = loader;
|
||||
loader = 0;
|
||||
if (l) {
|
||||
l->cancel();
|
||||
l->deleteLater();
|
||||
l->rpcInvalidate();
|
||||
QString already(bool check = false) const;
|
||||
QByteArray data() const;
|
||||
const FileLocation &location(bool check = false) const;
|
||||
void setLocation(const FileLocation &loc);
|
||||
|
||||
notifyLayoutChanged();
|
||||
}
|
||||
_location = FileLocation();
|
||||
if (!beforeDownload) {
|
||||
openOnSave = 0;
|
||||
openOnSaveMsgId = FullMsgId();
|
||||
}
|
||||
bool saveToCache() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void finish() {
|
||||
if (loader->done()) {
|
||||
_location = FileLocation(mtpToStorageType(loader->fileType()), loader->fileName());
|
||||
}
|
||||
loader->deleteLater();
|
||||
loader->rpcInvalidate();
|
||||
loader = 0;
|
||||
void performActionOnLoad();
|
||||
|
||||
notifyLayoutChanged();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
void forget();
|
||||
|
||||
VideoId id;
|
||||
uint64 access;
|
||||
|
@ -845,14 +846,15 @@ struct VideoData {
|
|||
FileStatus status;
|
||||
int32 uploadOffset;
|
||||
|
||||
mtpTypeId fileType;
|
||||
int32 openOnSave;
|
||||
FullMsgId openOnSaveMsgId;
|
||||
mtpFileLoader *loader;
|
||||
|
||||
private:
|
||||
FileLocation _location;
|
||||
|
||||
ActionOnLoad _actionOnLoad;
|
||||
FullMsgId _actionOnLoadMsgId;
|
||||
mutable mtpFileLoader *_loader;
|
||||
|
||||
void notifyLayoutChanged() const;
|
||||
|
||||
};
|
||||
|
||||
class VideoLink : public ITextLink {
|
||||
|
@ -867,6 +869,7 @@ public:
|
|||
|
||||
private:
|
||||
VideoData *_video;
|
||||
|
||||
};
|
||||
|
||||
class VideoSaveLink : public VideoLink {
|
||||
|
@ -886,6 +889,7 @@ public:
|
|||
VideoOpenLink(VideoData *video) : VideoLink(video) {
|
||||
}
|
||||
void onClick(Qt::MouseButton button) const;
|
||||
|
||||
};
|
||||
|
||||
class VideoCancelLink : public VideoLink {
|
||||
|
@ -895,63 +899,36 @@ public:
|
|||
VideoCancelLink(VideoData *video) : VideoLink(video) {
|
||||
}
|
||||
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);
|
||||
|
||||
void forget() {
|
||||
}
|
||||
void automaticLoad(const HistoryItem *item); // auto load voice message
|
||||
|
||||
bool prepareAutoLoader(const HistoryItem *item, bool force = false);
|
||||
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) {
|
||||
mtpFileLoader *l = loader;
|
||||
loader = 0;
|
||||
if (l) {
|
||||
l->cancel();
|
||||
l->deleteLater();
|
||||
l->rpcInvalidate();
|
||||
QString already(bool check = false) const;
|
||||
QByteArray data() const;
|
||||
const FileLocation &location(bool check = false) const;
|
||||
void setLocation(const FileLocation &loc);
|
||||
|
||||
notifyLayoutChanged();
|
||||
}
|
||||
_location = FileLocation();
|
||||
if (!beforeDownload) {
|
||||
openOnSave = 0;
|
||||
openOnSaveMsgId = FullMsgId();
|
||||
}
|
||||
}
|
||||
bool saveToCache() const;
|
||||
|
||||
void finish() {
|
||||
if (loader->done()) {
|
||||
_location = FileLocation(mtpToStorageType(loader->fileType()), loader->fileName());
|
||||
data = loader->bytes();
|
||||
}
|
||||
loader->deleteLater();
|
||||
loader->rpcInvalidate();
|
||||
loader = 0;
|
||||
void performActionOnLoad();
|
||||
|
||||
notifyLayoutChanged();
|
||||
}
|
||||
void notifyLayoutChanged() const;
|
||||
|
||||
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);
|
||||
void forget();
|
||||
void setData(const QByteArray &data) {
|
||||
_data = data;
|
||||
}
|
||||
|
||||
AudioId id;
|
||||
|
@ -965,14 +942,17 @@ struct AudioData {
|
|||
FileStatus status;
|
||||
int32 uploadOffset;
|
||||
|
||||
int32 openOnSave;
|
||||
FullMsgId openOnSaveMsgId;
|
||||
mtpFileLoader *loader;
|
||||
QByteArray data;
|
||||
int32 md5[8];
|
||||
|
||||
private:
|
||||
FileLocation _location;
|
||||
QByteArray _data;
|
||||
|
||||
ActionOnLoad _actionOnLoad;
|
||||
FullMsgId _actionOnLoadMsgId;
|
||||
mutable mtpFileLoader *_loader;
|
||||
|
||||
void notifyLayoutChanged() const;
|
||||
|
||||
};
|
||||
|
||||
|
@ -988,7 +968,9 @@ struct AudioMsgId {
|
|||
}
|
||||
AudioData *audio;
|
||||
FullMsgId msgId;
|
||||
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -1011,6 +993,7 @@ public:
|
|||
|
||||
private:
|
||||
AudioData *_audio;
|
||||
|
||||
};
|
||||
|
||||
class AudioSaveLink : public AudioLink {
|
||||
|
@ -1021,6 +1004,7 @@ public:
|
|||
}
|
||||
static void doSave(AudioData *audio, bool forceSavingAs = false);
|
||||
void onClick(Qt::MouseButton button) const;
|
||||
|
||||
};
|
||||
|
||||
class AudioOpenLink : public AudioLink {
|
||||
|
@ -1030,6 +1014,7 @@ public:
|
|||
AudioOpenLink(AudioData *audio) : AudioLink(audio) {
|
||||
}
|
||||
void onClick(Qt::MouseButton button) const;
|
||||
|
||||
};
|
||||
|
||||
class AudioCancelLink : public AudioLink {
|
||||
|
@ -1039,6 +1024,7 @@ public:
|
|||
AudioCancelLink(AudioData *audio) : AudioLink(audio) {
|
||||
}
|
||||
void onClick(Qt::MouseButton button) const;
|
||||
|
||||
};
|
||||
|
||||
enum DocumentType {
|
||||
|
@ -1062,6 +1048,7 @@ struct StickerData : public DocumentAdditionalData {
|
|||
bool setInstalled() const;
|
||||
|
||||
StorageImageLocation loc; // doc thumb location
|
||||
|
||||
};
|
||||
|
||||
struct SongData : public DocumentAdditionalData {
|
||||
|
@ -1069,93 +1056,63 @@ struct SongData : public DocumentAdditionalData {
|
|||
}
|
||||
int32 duration;
|
||||
QString title, performer;
|
||||
|
||||
};
|
||||
|
||||
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);
|
||||
void setattributes(const QVector<MTPDocumentAttribute> &attributes);
|
||||
|
||||
void forget() {
|
||||
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 automaticLoad(const HistoryItem *item); // auto load sticker or video
|
||||
|
||||
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) {
|
||||
mtpFileLoader *l = loader;
|
||||
loader = 0;
|
||||
if (l) {
|
||||
l->cancel();
|
||||
l->deleteLater();
|
||||
l->rpcInvalidate();
|
||||
QString already(bool check = false) const;
|
||||
QByteArray data() const;
|
||||
const FileLocation &location(bool check = false) const;
|
||||
void setLocation(const FileLocation &loc);
|
||||
|
||||
notifyLayoutChanged();
|
||||
}
|
||||
_location = FileLocation();
|
||||
if (!beforeDownload) {
|
||||
openOnSave = 0;
|
||||
openOnSaveMsgId = FullMsgId();
|
||||
}
|
||||
}
|
||||
bool saveToCache() const;
|
||||
|
||||
void finish() {
|
||||
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;
|
||||
void performActionOnLoad();
|
||||
|
||||
notifyLayoutChanged();
|
||||
}
|
||||
void notifyLayoutChanged() const;
|
||||
void forget();
|
||||
ImagePtr makeReplyPreview();
|
||||
|
||||
~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() {
|
||||
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() {
|
||||
return (type == SongDocument) ? static_cast<SongData*>(_additional) : 0;
|
||||
}
|
||||
bool isAnimation() {
|
||||
bool isAnimation() const {
|
||||
return (type == AnimatedDocument) || !mime.compare(qstr("image/gif"), Qt::CaseInsensitive);
|
||||
}
|
||||
bool isImage() const {
|
||||
|
@ -1163,9 +1120,7 @@ struct DocumentData {
|
|||
}
|
||||
void recountIsImage();
|
||||
|
||||
float64 progress() const {
|
||||
return loader ? loader->currentProgress() : ((status == FileDownloadFailed || (_location.name().isEmpty() && data.isEmpty())) ? 0 : 1);
|
||||
}
|
||||
~DocumentData();
|
||||
|
||||
DocumentId id;
|
||||
DocumentType type;
|
||||
|
@ -1180,20 +1135,21 @@ struct DocumentData {
|
|||
FileStatus status;
|
||||
int32 uploadOffset;
|
||||
|
||||
int32 openOnSave;
|
||||
FullMsgId openOnSaveMsgId;
|
||||
mtpFileLoader *loader;
|
||||
|
||||
QByteArray data;
|
||||
DocumentAdditionalData *_additional;
|
||||
|
||||
int32 md5[8];
|
||||
|
||||
private:
|
||||
|
||||
FileLocation _location;
|
||||
QByteArray _data;
|
||||
DocumentAdditionalData *_additional;
|
||||
bool _isImage;
|
||||
|
||||
ActionOnLoad _actionOnLoad;
|
||||
FullMsgId _actionOnLoadMsgId;
|
||||
mutable mtpFileLoader *_loader;
|
||||
|
||||
void notifyLayoutChanged() const;
|
||||
|
||||
};
|
||||
|
||||
struct SongMsgId {
|
||||
|
@ -1208,6 +1164,7 @@ struct SongMsgId {
|
|||
}
|
||||
DocumentData *song;
|
||||
FullMsgId msgId;
|
||||
|
||||
};
|
||||
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);
|
||||
|
@ -1231,6 +1188,7 @@ public:
|
|||
|
||||
private:
|
||||
DocumentData *_document;
|
||||
|
||||
};
|
||||
|
||||
class DocumentSaveLink : public DocumentLink {
|
||||
|
@ -1241,6 +1199,7 @@ public:
|
|||
}
|
||||
static void doSave(DocumentData *document, bool forceSavingAs = false);
|
||||
void onClick(Qt::MouseButton button) const;
|
||||
|
||||
};
|
||||
|
||||
class DocumentOpenLink : public DocumentLink {
|
||||
|
@ -1249,8 +1208,9 @@ class DocumentOpenLink : public DocumentLink {
|
|||
public:
|
||||
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;
|
||||
|
||||
};
|
||||
|
||||
class GifOpenLink : public DocumentOpenLink {
|
||||
|
@ -1261,6 +1221,7 @@ public:
|
|||
}
|
||||
static void doOpen(DocumentData *document);
|
||||
void onClick(Qt::MouseButton button) const;
|
||||
|
||||
};
|
||||
|
||||
class DocumentCancelLink : public DocumentLink {
|
||||
|
@ -1270,6 +1231,7 @@ public:
|
|||
DocumentCancelLink(DocumentData *document) : DocumentLink(document) {
|
||||
}
|
||||
void onClick(Qt::MouseButton button) const;
|
||||
|
||||
};
|
||||
|
||||
enum WebPageType {
|
||||
|
@ -1300,6 +1262,7 @@ struct WebPageData {
|
|||
PhotoData *photo;
|
||||
DocumentData *doc;
|
||||
int32 pendingTill;
|
||||
|
||||
};
|
||||
|
||||
QString saveFileName(const QString &title, const QString &filter, const QString &prefix, QString name, bool savingAs, const QDir &dir = QDir());
|
||||
|
|
|
@ -38,6 +38,11 @@ typedef quint64 uint64;
|
|||
|
||||
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
|
||||
typedef float float32;
|
||||
typedef double float64;
|
||||
|
|
Loading…
Add table
Reference in a new issue