saving QByteArray bookmark along with file paths and download path for OS X sandbox, will be actually implemented only in macstore branch

This commit is contained in:
John Preston 2015-11-26 20:34:52 +03:00
parent 50222ad87e
commit 4487ad9e15
32 changed files with 591 additions and 206 deletions

View File

@ -1632,8 +1632,9 @@ namespace App {
convert->sticker()->loc = thumbLocation; convert->sticker()->loc = thumbLocation;
} }
if (convert->location.check()) { const FileLocation &loc(convert->location(true));
Local::writeFileLocation(mediaKey(DocumentFileLocation, convert->dc, convert->id), convert->location); if (!loc.isEmpty()) {
Local::writeFileLocation(mediaKey(DocumentFileLocation, convert->dc, convert->id), loc);
} }
} }
DocumentsData::const_iterator i = documentsData.constFind(document); DocumentsData::const_iterator i = documentsData.constFind(document);

View File

@ -709,6 +709,9 @@ void Application::checkMapVersion() {
} }
} }
} }
if (cNeedConfigResave()) {
Local::writeUserSettings();
}
} }
void Application::startApp() { void Application::startApp() {

View File

@ -270,7 +270,7 @@ void audioFinish() {
} }
void AudioPlayer::Msg::clearData() { void AudioPlayer::Msg::clearData() {
fname = QString(); file = FileLocation();
data = QByteArray(); data = QByteArray();
position = duration = 0; position = duration = 0;
frequency = AudioVoiceMsgFrequency; frequency = AudioVoiceMsgFrequency;
@ -463,9 +463,9 @@ void AudioPlayer::play(const AudioMsgId &audio, int64 position) {
current = &_audioData[_audioCurrent]; current = &_audioData[_audioCurrent];
} }
current->audio = audio; current->audio = audio;
current->fname = audio.audio->already(true); current->file = audio.audio->location(true);
current->data = audio.audio->data; current->data = audio.audio->data;
if (current->fname.isEmpty() && current->data.isEmpty()) { if (current->file.isEmpty() && current->data.isEmpty()) {
setStoppedState(current, AudioPlayerStoppedAtError); setStoppedState(current, AudioPlayerStoppedAtError);
onError(audio); onError(audio);
} else { } else {
@ -507,9 +507,9 @@ void AudioPlayer::play(const SongMsgId &song, int64 position) {
current = &_songData[_songCurrent]; current = &_songData[_songCurrent];
} }
current->song = song; current->song = song;
current->fname = song.song->already(true); current->file = song.song->location(true);
current->data = song.song->data; current->data = song.song->data;
if (current->fname.isEmpty() && current->data.isEmpty()) { if (current->file.isEmpty() && current->data.isEmpty()) {
setStoppedState(current); setStoppedState(current);
if (!song.song->loader) { if (!song.song->loader) {
DocumentOpenLink::doOpen(song.song); DocumentOpenLink::doOpen(song.song);
@ -1076,13 +1076,17 @@ void AudioPlayerFader::resumeDevice() {
class AudioPlayerLoader { class AudioPlayerLoader {
public: public:
AudioPlayerLoader(const QString &fname, const QByteArray &data) : fname(fname), data(data), dataPos(0) { AudioPlayerLoader(const FileLocation &file, const QByteArray &data) : file(file), access(false), data(data), dataPos(0) {
} }
virtual ~AudioPlayerLoader() { virtual ~AudioPlayerLoader() {
if (access) {
file.accessDisable();
access = false;
}
} }
bool check(const QString &fname, const QByteArray &data) { bool check(const FileLocation &file, const QByteArray &data) {
return this->fname == fname && this->data.size() == data.size(); return this->file == file && this->data.size() == data.size();
} }
virtual bool open(qint64 position = 0) = 0; virtual bool open(qint64 position = 0) = 0;
@ -1093,7 +1097,8 @@ public:
protected: protected:
QString fname; FileLocation file;
bool access;
QByteArray data; QByteArray data;
QFile f; QFile f;
@ -1102,9 +1107,16 @@ protected:
bool openFile() { bool openFile() {
if (data.isEmpty()) { if (data.isEmpty()) {
if (f.isOpen()) f.close(); if (f.isOpen()) f.close();
f.setFileName(fname); if (!access) {
if (!file.accessEnable()) {
LOG(("Audio Error: could not open file access '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(f.error()).arg(f.errorString()));
return false;
}
access = true;
}
f.setFileName(file.name());
if (!f.open(QIODevice::ReadOnly)) { if (!f.open(QIODevice::ReadOnly)) {
LOG(("Audio Error: could not open file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(f.error()).arg(f.errorString())); LOG(("Audio Error: could not open file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(f.error()).arg(f.errorString()));
return false; return false;
} }
} }
@ -1121,7 +1133,7 @@ static const int32 _toChannels = 2;
class FFMpegLoader : public AudioPlayerLoader { class FFMpegLoader : public AudioPlayerLoader {
public: public:
FFMpegLoader(const QString &fname, const QByteArray &data) : AudioPlayerLoader(fname, data), FFMpegLoader(const FileLocation &file, const QByteArray &data) : AudioPlayerLoader(file, data),
freq(AudioVoiceMsgFrequency), fmt(AL_FORMAT_STEREO16), freq(AudioVoiceMsgFrequency), fmt(AL_FORMAT_STEREO16),
sampleSize(2 * sizeof(short)), srcRate(AudioVoiceMsgFrequency), dstRate(AudioVoiceMsgFrequency), sampleSize(2 * sizeof(short)), srcRate(AudioVoiceMsgFrequency), dstRate(AudioVoiceMsgFrequency),
maxResampleSamples(1024), dstSamplesData(0), len(0), maxResampleSamples(1024), dstSamplesData(0), len(0),
@ -1143,7 +1155,7 @@ public:
} }
fmtContext = avformat_alloc_context(); fmtContext = avformat_alloc_context();
if (!fmtContext) { if (!fmtContext) {
LOG(("Audio Error: Unable to avformat_alloc_context for file '%1', data size '%2'").arg(fname).arg(data.size())); LOG(("Audio Error: Unable to avformat_alloc_context for file '%1', data size '%2'").arg(file.name()).arg(data.size()));
return false; return false;
} }
fmtContext->pb = ioContext; fmtContext->pb = ioContext;
@ -1153,19 +1165,19 @@ public:
if ((res = avformat_open_input(&fmtContext, 0, 0, 0)) < 0) { if ((res = avformat_open_input(&fmtContext, 0, 0, 0)) < 0) {
ioBuffer = 0; ioBuffer = 0;
LOG(("Audio Error: Unable to avformat_open_input for file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res))); LOG(("Audio Error: Unable to avformat_open_input for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
return false; return false;
} }
_opened = true; _opened = true;
if ((res = avformat_find_stream_info(fmtContext, 0)) < 0) { if ((res = avformat_find_stream_info(fmtContext, 0)) < 0) {
LOG(("Audio Error: Unable to avformat_find_stream_info for file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res))); LOG(("Audio Error: Unable to avformat_find_stream_info for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
return false; return false;
} }
streamId = av_find_best_stream(fmtContext, AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0); streamId = av_find_best_stream(fmtContext, AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0);
if (streamId < 0) { if (streamId < 0) {
LOG(("Audio Error: Unable to av_find_best_stream for file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(streamId).arg(av_make_error_string(err, sizeof(err), streamId))); LOG(("Audio Error: Unable to av_find_best_stream for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(streamId).arg(av_make_error_string(err, sizeof(err), streamId)));
return false; return false;
} }
@ -1173,7 +1185,7 @@ public:
codecContext = fmtContext->streams[streamId]->codec; codecContext = fmtContext->streams[streamId]->codec;
av_opt_set_int(codecContext, "refcounted_frames", 1, 0); av_opt_set_int(codecContext, "refcounted_frames", 1, 0);
if ((res = avcodec_open2(codecContext, codec, 0)) < 0) { if ((res = avcodec_open2(codecContext, codec, 0)) < 0) {
LOG(("Audio Error: Unable to avcodec_open2 for file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res))); LOG(("Audio Error: Unable to avcodec_open2 for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
return false; return false;
} }
@ -1217,7 +1229,7 @@ public:
if (sampleSize < 0) { if (sampleSize < 0) {
swrContext = swr_alloc(); swrContext = swr_alloc();
if (!swrContext) { if (!swrContext) {
LOG(("Audio Error: Unable to swr_alloc for file '%1', data size '%2'").arg(fname).arg(data.size())); LOG(("Audio Error: Unable to swr_alloc for file '%1', data size '%2'").arg(file.name()).arg(data.size()));
return false; return false;
} }
int64_t src_ch_layout = layout, dst_ch_layout = _toChannelLayout; int64_t src_ch_layout = layout, dst_ch_layout = _toChannelLayout;
@ -1233,7 +1245,7 @@ public:
av_opt_set_sample_fmt(swrContext, "out_sample_fmt", dst_sample_fmt, 0); av_opt_set_sample_fmt(swrContext, "out_sample_fmt", dst_sample_fmt, 0);
if ((res = swr_init(swrContext)) < 0) { if ((res = swr_init(swrContext)) < 0) {
LOG(("Audio Error: Unable to swr_init for file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res))); LOG(("Audio Error: Unable to swr_init for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
return false; return false;
} }
@ -1244,7 +1256,7 @@ public:
maxResampleSamples = av_rescale_rnd(AVBlockSize / sampleSize, dstRate, srcRate, AV_ROUND_UP); maxResampleSamples = av_rescale_rnd(AVBlockSize / sampleSize, dstRate, srcRate, AV_ROUND_UP);
if ((res = av_samples_alloc_array_and_samples(&dstSamplesData, 0, _toChannels, maxResampleSamples, _toFormat, 0)) < 0) { if ((res = av_samples_alloc_array_and_samples(&dstSamplesData, 0, _toChannels, maxResampleSamples, _toFormat, 0)) < 0) {
LOG(("Audio Error: Unable to av_samples_alloc for file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res))); LOG(("Audio Error: Unable to av_samples_alloc for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
return false; return false;
} }
} }
@ -1279,7 +1291,7 @@ public:
if ((res = av_read_frame(fmtContext, &avpkt)) < 0) { if ((res = av_read_frame(fmtContext, &avpkt)) < 0) {
if (res != AVERROR_EOF) { if (res != AVERROR_EOF) {
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 }; char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
LOG(("Audio Error: Unable to av_read_frame() file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res))); LOG(("Audio Error: Unable to av_read_frame() file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
} }
return -1; return -1;
} }
@ -1288,7 +1300,7 @@ public:
int got_frame = 0; int got_frame = 0;
if ((res = avcodec_decode_audio4(codecContext, frame, &got_frame, &avpkt)) < 0) { if ((res = avcodec_decode_audio4(codecContext, frame, &got_frame, &avpkt)) < 0) {
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 }; char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
LOG(("Audio Error: Unable to avcodec_decode_audio4() file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res))); LOG(("Audio Error: Unable to avcodec_decode_audio4() file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
av_free_packet(&avpkt); av_free_packet(&avpkt);
if (res == AVERROR_INVALIDDATA) return 0; // try to skip bad packet if (res == AVERROR_INVALIDDATA) return 0; // try to skip bad packet
@ -1305,7 +1317,7 @@ public:
if ((res = av_samples_alloc(dstSamplesData, 0, _toChannels, maxResampleSamples, _toFormat, 1)) < 0) { if ((res = av_samples_alloc(dstSamplesData, 0, _toChannels, maxResampleSamples, _toFormat, 1)) < 0) {
dstSamplesData[0] = 0; dstSamplesData[0] = 0;
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 }; char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
LOG(("Audio Error: Unable to av_samples_alloc for file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res))); LOG(("Audio Error: Unable to av_samples_alloc for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
av_free_packet(&avpkt); av_free_packet(&avpkt);
return -1; return -1;
@ -1313,7 +1325,7 @@ public:
} }
if ((res = swr_convert(swrContext, dstSamplesData, dstSamples, (const uint8_t**)frame->extended_data, frame->nb_samples)) < 0) { if ((res = swr_convert(swrContext, dstSamplesData, dstSamples, (const uint8_t**)frame->extended_data, frame->nb_samples)) < 0) {
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 }; char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
LOG(("Audio Error: Unable to swr_convert for file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res))); LOG(("Audio Error: Unable to swr_convert for file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
av_free_packet(&avpkt); av_free_packet(&avpkt);
return -1; return -1;
@ -1678,7 +1690,7 @@ AudioPlayerLoader *AudioPlayerLoaders::setupLoader(MediaOverviewType type, const
return 0; return 0;
} }
if (*l && (!isGoodId || !(*l)->check(m->fname, m->data))) { if (*l && (!isGoodId || !(*l)->check(m->file, m->data))) {
delete *l; delete *l;
*l = 0; *l = 0;
switch (type) { switch (type) {
@ -1693,23 +1705,23 @@ AudioPlayerLoader *AudioPlayerLoaders::setupLoader(MediaOverviewType type, const
case OverviewDocuments: _song = *static_cast<const SongMsgId*>(objId); break; case OverviewDocuments: _song = *static_cast<const SongMsgId*>(objId); break;
} }
QByteArray header = m->data.mid(0, 8); // QByteArray header = m->data.mid(0, 8);
if (header.isEmpty()) { // if (header.isEmpty()) {
QFile f(m->fname); // QFile f(m->fname);
if (!f.open(QIODevice::ReadOnly)) { // if (!f.open(QIODevice::ReadOnly)) {
LOG(("Audio Error: could not open file '%1'").arg(m->fname)); // LOG(("Audio Error: could not open file '%1'").arg(m->fname));
m->state = AudioPlayerStoppedAtStart; // m->state = AudioPlayerStoppedAtStart;
return 0; // return 0;
} // }
header = f.read(8); // header = f.read(8);
} // }
if (header.size() < 8) { // if (header.size() < 8) {
LOG(("Audio Error: could not read header from file '%1', data size %2").arg(m->fname).arg(m->data.isEmpty() ? QFileInfo(m->fname).size() : m->data.size())); // LOG(("Audio Error: could not read header from file '%1', data size %2").arg(m->fname).arg(m->data.isEmpty() ? QFileInfo(m->fname).size() : m->data.size()));
m->state = AudioPlayerStoppedAtStart; // m->state = AudioPlayerStoppedAtStart;
return 0; // return 0;
} // }
*l = new FFMpegLoader(m->fname, m->data); *l = new FFMpegLoader(m->file, m->data);
int ret; int ret;
if (!(*l)->open(position)) { if (!(*l)->open(position)) {
@ -1758,7 +1770,7 @@ AudioPlayer::Msg *AudioPlayerLoaders::checkLoader(MediaOverviewType type) {
} }
if (!l || !m) return 0; if (!l || !m) return 0;
if (!isGoodId || !m->loading || !(*l)->check(m->fname, m->data)) { if (!isGoodId || !m->loading || !(*l)->check(m->file, m->data)) {
LOG(("Audio Error: playing changed while loading")); LOG(("Audio Error: playing changed while loading"));
return 0; return 0;
} }
@ -2278,7 +2290,7 @@ void AudioCaptureInner::writeFrame(int32 offset, int32 framesize) {
class FFMpegAttributesReader : public AudioPlayerLoader { class FFMpegAttributesReader : public AudioPlayerLoader {
public: public:
FFMpegAttributesReader(const QString &fname, const QByteArray &data) : AudioPlayerLoader(fname, data), FFMpegAttributesReader(const FileLocation &file, const QByteArray &data) : AudioPlayerLoader(file, data),
ioBuffer(0), ioContext(0), fmtContext(0), codec(0), streamId(0), ioBuffer(0), ioContext(0), fmtContext(0), codec(0), streamId(0),
_opened(false) { _opened(false) {
} }
@ -2488,7 +2500,7 @@ private:
}; };
MTPDocumentAttribute audioReadSongAttributes(const QString &fname, const QByteArray &data, QImage &cover, QByteArray &coverBytes, QByteArray &coverFormat) { MTPDocumentAttribute audioReadSongAttributes(const QString &fname, const QByteArray &data, QImage &cover, QByteArray &coverBytes, QByteArray &coverFormat) {
FFMpegAttributesReader reader(fname, data); FFMpegAttributesReader reader(FileLocation(StorageFilePartial, fname), data);
if (reader.open()) { if (reader.open()) {
int32 duration = reader.duration() / reader.frequency(); int32 duration = reader.duration() / reader.frequency();
if (reader.duration() > 0) { if (reader.duration() > 0) {

View File

@ -127,7 +127,7 @@ private:
void clearData(); void clearData();
QString fname; FileLocation file;
QByteArray data; QByteArray data;
int64 position, duration; int64 position, duration;
int32 frequency; int32 frequency;

View File

@ -25,15 +25,17 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include "downloadpathbox.h" #include "downloadpathbox.h"
#include "gui/filedialog.h" #include "gui/filedialog.h"
#include "pspecific.h"
DownloadPathBox::DownloadPathBox() : DownloadPathBox::DownloadPathBox() : AbstractBox()
_path(cDownloadPath()), , _path(cDownloadPath())
_default(this, qsl("dir_type"), 0, lang(lng_download_path_default_radio), _path.isEmpty()), , _pathBookmark(cDownloadPathBookmark())
_temp(this, qsl("dir_type"), 1, lang(lng_download_path_temp_radio), _path == qsl("tmp")), , _default(this, qsl("dir_type"), 0, lang(lng_download_path_default_radio), _path.isEmpty())
_dir(this, qsl("dir_type"), 2, lang(lng_download_path_dir_radio), !_path.isEmpty() && _path != qsl("tmp")), , _temp(this, qsl("dir_type"), 1, lang(lng_download_path_temp_radio), _path == qsl("tmp"))
_pathLink(this, QString(), st::defaultBoxLinkButton), , _dir(this, qsl("dir_type"), 2, lang(lng_download_path_dir_radio), !_path.isEmpty() && _path != qsl("tmp"))
_save(this, lang(lng_connection_save), st::defaultBoxButton), , _pathLink(this, QString(), st::defaultBoxLinkButton)
_cancel(this, lang(lng_cancel), st::cancelBoxButton) { , _save(this, lang(lng_connection_save), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
connect(&_save, SIGNAL(clicked()), this, SLOT(onSave())); connect(&_save, SIGNAL(clicked()), this, SLOT(onSave()));
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose())); connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
@ -124,12 +126,13 @@ void DownloadPathBox::onChange() {
void DownloadPathBox::onEditPath() { void DownloadPathBox::onEditPath() {
filedialogInit(); filedialogInit();
QString path, lastPath = cDialogLastPath(); QString path, lastPath = cDialogLastPath();
if (!cDownloadPath().isEmpty()) { if (!cDownloadPath().isEmpty() && cDownloadPath() != qstr("tmp")) {
cSetDialogLastPath(cDownloadPath()); cSetDialogLastPath(cDownloadPath().left(cDownloadPath().size() - (cDownloadPath().endsWith('/') ? 1 : 0)));
} }
if (filedialogGetDir(path, lang(lng_download_path_choose))) { if (filedialogGetDir(path, lang(lng_download_path_choose))) {
if (!path.isEmpty()) { if (!path.isEmpty()) {
_path = path + '/'; _path = path + '/';
_pathBookmark = psDownloadPathBookmark(_path);
setPathText(QDir::toNativeSeparators(_path)); setPathText(QDir::toNativeSeparators(_path));
} }
} }
@ -138,6 +141,7 @@ void DownloadPathBox::onEditPath() {
void DownloadPathBox::onSave() { void DownloadPathBox::onSave() {
cSetDownloadPath(_default.checked() ? QString() : (_temp.checked() ? qsl("tmp") : _path)); cSetDownloadPath(_default.checked() ? QString() : (_temp.checked() ? qsl("tmp") : _path));
cSetDownloadPathBookmark((_default.checked() || _temp.checked()) ? QByteArray() : _pathBookmark);
Local::writeUserSettings(); Local::writeUserSettings();
emit closed(); emit closed();
} }

View File

@ -47,6 +47,7 @@ private:
void setPathText(const QString &text); void setPathText(const QString &text);
QString _path; QString _path;
QByteArray _pathBookmark;
Radiobutton _default, _temp, _dir; Radiobutton _default, _temp, _dir;
LinkButton _pathLink; LinkButton _pathLink;

View File

@ -20,9 +20,9 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
*/ */
#pragma once #pragma once
static const int32 AppVersion = 9013; static const int32 AppVersion = 9014;
static const wchar_t *AppVersionStr = L"0.9.13"; static const wchar_t *AppVersionStr = L"0.9.14";
static const bool DevVersion = false; static const bool DevVersion = true;
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)"; static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
static const wchar_t *AppName = L"Telegram Desktop"; static const wchar_t *AppName = L"Telegram Desktop";

View File

@ -41,7 +41,7 @@ void FileUploader::uploadMedia(const FullMsgId &msgId, const ReadyLocalMedia &me
} }
document->status = FileUploading; document->status = FileUploading;
if (!media.file.isEmpty()) { if (!media.file.isEmpty()) {
document->location = FileLocation(StorageFilePartial, media.file); document->setLocation(FileLocation(StorageFilePartial, media.file));
} }
} else if (media.type == PrepareAudio) { } else if (media.type == PrepareAudio) {
AudioData *audio = App::feedAudio(media.audio); AudioData *audio = App::feedAudio(media.audio);
@ -64,7 +64,7 @@ void FileUploader::upload(const FullMsgId &msgId, const FileLoadResultPtr &file)
} }
document->status = FileUploading; document->status = FileUploading;
if (!file->filepath.isEmpty()) { if (!file->filepath.isEmpty()) {
document->location = FileLocation(StorageFilePartial, file->filepath); document->setLocation(FileLocation(StorageFilePartial, file->filepath));
} }
} else if (file->type == PrepareAudio) { } else if (file->type == PrepareAudio) {
AudioData *audio = App::feedAudio(file->audio); AudioData *audio = App::feedAudio(file->audio);

View File

@ -161,10 +161,17 @@ bool AnimatedGif::animStep(float64 ms) {
return true; return true;
} }
void AnimatedGif::start(HistoryItem *row, const QString &file) { void AnimatedGif::start(HistoryItem *row, const FileLocation &f) {
stop(); stop();
reader = new QImageReader(file); file = new FileLocation(f);
if (!file->accessEnable()) {
stop();
return;
}
access = true;
reader = new QImageReader(file->name());
if (!reader->canRead() || !reader->supportsAnimation()) { if (!reader->canRead() || !reader->supportsAnimation()) {
stop(); stop();
return; return;
@ -206,6 +213,15 @@ void AnimatedGif::start(HistoryItem *row, const QString &file) {
} }
void AnimatedGif::stop(bool onItemRemoved) { void AnimatedGif::stop(bool onItemRemoved) {
if (file) {
if (access) {
file->accessDisable();
}
delete file;
file = 0;
}
access = false;
if (isNull()) return; if (isNull()) return;
delete reader; delete reader;

View File

@ -387,17 +387,18 @@ private:
}; };
class HistoryItem; class HistoryItem;
class FileLocation;
class AnimatedGif : public QObject, public Animated { class AnimatedGif : public QObject, public Animated {
Q_OBJECT Q_OBJECT
public: public:
AnimatedGif() : msg(0), reader(0), w(0), h(0), frame(0), framesCount(0), duration(0) { AnimatedGif() : msg(0), file(0), access(false), reader(0), w(0), h(0), frame(0), framesCount(0), duration(0) {
} }
bool animStep(float64 ms); bool animStep(float64 ms);
void start(HistoryItem *row, const QString &file); void start(HistoryItem *row, const FileLocation &file);
void stop(bool onItemRemoved = false); void stop(bool onItemRemoved = false);
bool isNull() const { bool isNull() const {
@ -418,6 +419,8 @@ public:
HistoryItem *msg; HistoryItem *msg;
QImage img; QImage img;
FileLocation *file;
bool access;
QImageReader *reader; QImageReader *reader;
int32 w, h, frame; int32 w, h, frame;

View File

@ -89,7 +89,7 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS
} }
return !files.isEmpty(); return !files.isEmpty();
} else if (multipleFiles < -1) { } else if (multipleFiles < -1) {
file = QFileDialog::getExistingDirectory(App::wnd() ? App::wnd()->filedialogParent() : 0, caption); file = QFileDialog::getExistingDirectory(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile);
} else if (multipleFiles < 0) { } else if (multipleFiles < 0) {
file = QFileDialog::getSaveFileName(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter); file = QFileDialog::getSaveFileName(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter);
} else { } else {

View File

@ -24,6 +24,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include "mainwidget.h" #include "mainwidget.h"
#include "localstorage.h" #include "localstorage.h"
#include "pspecific.h"
namespace { namespace {
typedef QMap<QString, LocalImage*> LocalImages; typedef QMap<QString, LocalImage*> LocalImages;
LocalImages localImages; LocalImages localImages;
@ -712,3 +714,82 @@ StorageImage *getImage(const StorageImageLocation &location, const QByteArray &b
} }
return i.value(); return i.value();
} }
ReadAccessEnabler::ReadAccessEnabler(const PsFileBookmark *bookmark) : _bookmark(bookmark), _failed(_bookmark ? !_bookmark->enable() : false) {
}
ReadAccessEnabler::ReadAccessEnabler(const QSharedPointer<PsFileBookmark> &bookmark) : _bookmark(bookmark.data()), _failed(_bookmark ? !_bookmark->enable() : false) {
}
ReadAccessEnabler::~ReadAccessEnabler() {
if (_bookmark && !_failed) _bookmark->disable();
}
FileLocation::FileLocation(StorageFileType type, const QString &name) : type(type), fname(name) {
if (fname.isEmpty()) {
size = 0;
type = StorageFileUnknown;
} else {
setBookmark(psPathBookmark(name));
QFileInfo f(name);
if (f.exists()) {
qint64 s = f.size();
if (s > INT_MAX) {
fname = QString();
_bookmark.reset(0);
size = 0;
type = StorageFileUnknown;
} else {
modified = f.lastModified();
size = qint32(s);
}
} else {
fname = QString();
_bookmark.reset(0);
size = 0;
type = StorageFileUnknown;
}
}
}
bool FileLocation::check() const {
if (fname.isEmpty()) return false;
ReadAccessEnabler enabler(_bookmark);
if (enabler.failed()) {
const_cast<FileLocation*>(this)->_bookmark.reset(0);
}
QFileInfo f(name());
if (!f.exists() || !f.isReadable()) return false;
quint64 s = f.size();
if (s > INT_MAX) return false;
return (f.lastModified() == modified) && (qint32(s) == size);
}
const QString &FileLocation::name() const {
return _bookmark ? _bookmark->name(fname) : fname;
}
QByteArray FileLocation::bookmark() const {
return _bookmark ? _bookmark->bookmark() : QByteArray();
}
void FileLocation::setBookmark(const QByteArray &bm) {
if (bm.isEmpty()) {
_bookmark.reset(0);
} else {
_bookmark.reset(new PsFileBookmark(bm));
}
}
bool FileLocation::accessEnable() const {
return isEmpty() ? false : (_bookmark ? _bookmark->enable() : true);
}
void FileLocation::accessDisable() const {
return _bookmark ? _bookmark->disable() : (void)0;
}

View File

@ -240,46 +240,50 @@ void clearStorageImages();
void clearAllImages(); void clearAllImages();
int64 imageCacheSize(); int64 imageCacheSize();
struct FileLocation { class PsFileBookmark;
FileLocation(StorageFileType type, const QString &name, const QDateTime &modified, qint32 size) : type(type), name(name), modified(modified), size(size) { class ReadAccessEnabler {
} public:
FileLocation(StorageFileType type, const QString &name) : type(type), name(name) { ReadAccessEnabler(const PsFileBookmark *bookmark);
QFileInfo f(name); ReadAccessEnabler(const QSharedPointer<PsFileBookmark> &bookmark);
if (f.exists()) { bool failed() const {
qint64 s = f.size(); return _failed;
if (s > INT_MAX) {
this->name = QString();
size = 0;
type = StorageFileUnknown;
} else {
modified = f.lastModified();
size = qint32(s);
}
} else {
this->name = QString();
size = 0;
type = StorageFileUnknown;
}
} }
~ReadAccessEnabler();
private:
const PsFileBookmark *_bookmark;
bool _failed;
};
class FileLocation {
public:
FileLocation(StorageFileType type, const QString &name);
FileLocation() : size(0) { FileLocation() : size(0) {
} }
bool check() const {
if (name.isEmpty()) return false;
QFileInfo f(name);
if (!f.exists()) return false;
quint64 s = f.size(); bool check() const;
if (s > INT_MAX) return false; const QString &name() const;
void setBookmark(const QByteArray &bookmark);
return (f.lastModified() == modified) && (qint32(s) == size); QByteArray bookmark() const;
bool isEmpty() const {
return name().isEmpty();
} }
bool accessEnable() const;
void accessDisable() const;
StorageFileType type; StorageFileType type;
QString name; QString fname;
QDateTime modified; QDateTime modified;
qint32 size; qint32 size;
private:
QSharedPointer<PsFileBookmark> _bookmark;
}; };
inline bool operator==(const FileLocation &a, const FileLocation &b) { inline bool operator==(const FileLocation &a, const FileLocation &b) {
return a.type == b.type && a.name == b.name && a.modified == b.modified && a.size == b.size; return a.type == b.type && a.name() == b.name() && a.modified == b.modified && a.size == b.size;
} }
inline bool operator!=(const FileLocation &a, const FileLocation &b) { inline bool operator!=(const FileLocation &a, const FileLocation &b) {
return !(a == b); return !(a == b);

View File

@ -150,7 +150,7 @@ void historyInit() {
_initTextOptions(); _initTextOptions();
} }
void startGif(HistoryItem *row, const QString &file) { void startGif(HistoryItem *row, const FileLocation &file) {
if (row == animated.msg) { if (row == animated.msg) {
stopGif(); stopGif();
} else { } else {

View File

@ -24,7 +24,7 @@ void historyInit();
class HistoryItem; class HistoryItem;
void startGif(HistoryItem *row, const QString &file); void startGif(HistoryItem *row, const FileLocation &file);
void itemRemovedGif(HistoryItem *item); void itemRemovedGif(HistoryItem *item);
void itemReplacedGif(HistoryItem *oldItem, HistoryItem *newItem); void itemReplacedGif(HistoryItem *oldItem, HistoryItem *newItem);
void stopGif(); void stopGif();

View File

@ -579,11 +579,23 @@ namespace {
} }
quint32 size = 0; quint32 size = 0;
for (FileLocations::const_iterator i = _fileLocations.cbegin(), e = _fileLocations.cend(); i != e; ++i) { for (FileLocations::const_iterator i = _fileLocations.cbegin(), e = _fileLocations.cend(); i != e; ++i) {
// location + type + namelen + name + date + size // location + type + namelen + name
size += sizeof(quint64) * 2 + sizeof(quint32) + _stringSize(i.value().name) + _dateTimeSize() + sizeof(quint32); size += sizeof(quint64) * 2 + sizeof(quint32) + _stringSize(i.value().name());
if (AppVersion > 9013) {
// bookmark
size += _bytearraySize(i.value().bookmark());
} }
// date + size
size += _dateTimeSize() + sizeof(quint32);
}
//end mark //end mark
size += sizeof(quint64) * 2 + sizeof(quint32) + _stringSize(QString()) + _dateTimeSize() + sizeof(quint32); size += sizeof(quint64) * 2 + sizeof(quint32) + _stringSize(QString());
if (AppVersion > 9013) {
size += _bytearraySize(QByteArray());
}
size += _dateTimeSize() + sizeof(quint32);
size += sizeof(quint32); // aliases count size += sizeof(quint32); // aliases count
for (FileLocationAliases::const_iterator i = _fileLocationAliases.cbegin(), e = _fileLocationAliases.cend(); i != e; ++i) { for (FileLocationAliases::const_iterator i = _fileLocationAliases.cbegin(), e = _fileLocationAliases.cend(); i != e; ++i) {
// alias + location // alias + location
@ -592,9 +604,19 @@ namespace {
EncryptedDescriptor data(size); EncryptedDescriptor data(size);
for (FileLocations::const_iterator i = _fileLocations.cbegin(); i != _fileLocations.cend(); ++i) { for (FileLocations::const_iterator i = _fileLocations.cbegin(); i != _fileLocations.cend(); ++i) {
data.stream << quint64(i.key().first) << quint64(i.key().second) << quint32(i.value().type) << i.value().name << i.value().modified << quint32(i.value().size); data.stream << quint64(i.key().first) << quint64(i.key().second) << quint32(i.value().type) << i.value().name();
if (AppVersion > 9013) {
data.stream << i.value().bookmark();
} }
data.stream << quint64(0) << quint64(0) << quint32(0) << QString() << QDateTime::currentDateTime() << quint32(0); data.stream << i.value().modified << quint32(i.value().size);
}
data.stream << quint64(0) << quint64(0) << quint32(0) << QString();
if (AppVersion > 9013) {
data.stream << QByteArray();
}
data.stream << QDateTime::currentDateTime() << quint32(0);
data.stream << quint32(_fileLocationAliases.size()); data.stream << quint32(_fileLocationAliases.size());
for (FileLocationAliases::const_iterator i = _fileLocationAliases.cbegin(), e = _fileLocationAliases.cend(); i != e; ++i) { for (FileLocationAliases::const_iterator i = _fileLocationAliases.cbegin(), e = _fileLocationAliases.cend(); i != e; ++i) {
data.stream << quint64(i.key().first) << quint64(i.key().second) << quint64(i.value().first) << quint64(i.value().second); data.stream << quint64(i.key().first) << quint64(i.key().second) << quint64(i.value().first) << quint64(i.value().second);
@ -617,11 +639,17 @@ namespace {
bool endMarkFound = false; bool endMarkFound = false;
while (!locations.stream.atEnd()) { while (!locations.stream.atEnd()) {
quint64 first, second; quint64 first, second;
QByteArray bookmark;
FileLocation loc; FileLocation loc;
quint32 type; quint32 type;
locations.stream >> first >> second >> type >> loc.name >> loc.modified >> loc.size; locations.stream >> first >> second >> type >> loc.fname;
if (locations.version > 9013) {
locations.stream >> bookmark;
}
locations.stream >> loc.modified >> loc.size;
loc.setBookmark(bookmark);
if (!first && !second && !type && loc.name.isEmpty() && !loc.size) { // end mark if (!first && !second && !type && loc.fname.isEmpty() && !loc.size) { // end mark
endMarkFound = true; endMarkFound = true;
break; break;
} }
@ -629,12 +657,8 @@ namespace {
MediaKey key(first, second); MediaKey key(first, second);
loc.type = StorageFileType(type); loc.type = StorageFileType(type);
if (loc.check()) {
_fileLocations.insert(key, loc); _fileLocations.insert(key, loc);
_fileLocationPairs.insert(loc.name, FileLocationPair(key, loc)); _fileLocationPairs.insert(loc.fname, FileLocationPair(key, loc));
} else {
_writeLocations();
}
} }
if (endMarkFound) { if (endMarkFound) {
@ -1038,12 +1062,26 @@ namespace {
cSetAskDownloadPath(v == 1); cSetAskDownloadPath(v == 1);
} break; } break;
case dbiDownloadPath: { case dbiDownloadPathOld: {
QString v; QString v;
stream >> v; stream >> v;
if (!_checkStreamStatus(stream)) return false; if (!_checkStreamStatus(stream)) return false;
if (!v.isEmpty() && v != qstr("tmp") && !v.endsWith('/')) v += '/';
cSetDownloadPath(v); cSetDownloadPath(v);
cSetDownloadPathBookmark(QByteArray());
} break;
case dbiDownloadPath: {
QString v;
QByteArray bookmark;
stream >> v >> bookmark;
if (!_checkStreamStatus(stream)) return false;
if (!v.isEmpty() && v != qstr("tmp") && !v.endsWith('/')) v += '/';
cSetDownloadPath(v);
cSetDownloadPathBookmark(bookmark);
psDownloadPathEnableAccess();
} break; } break;
case dbiCompressPastedImage: { case dbiCompressPastedImage: {
@ -1362,7 +1400,7 @@ namespace {
} }
uint32 size = 14 * (sizeof(quint32) + sizeof(qint32)); uint32 size = 14 * (sizeof(quint32) + sizeof(qint32));
size += sizeof(quint32) + _stringSize(cAskDownloadPath() ? QString() : cDownloadPath()); size += sizeof(quint32) + _stringSize(cAskDownloadPath() ? QString() : cDownloadPath()) + _bytearraySize(cAskDownloadPath() ? QByteArray() : cDownloadPathBookmark());
size += sizeof(quint32) + sizeof(qint32) + (cRecentEmojisPreload().isEmpty() ? cGetRecentEmojis().size() : cRecentEmojisPreload().size()) * (sizeof(uint64) + sizeof(ushort)); size += sizeof(quint32) + sizeof(qint32) + (cRecentEmojisPreload().isEmpty() ? cGetRecentEmojis().size() : cRecentEmojisPreload().size()) * (sizeof(uint64) + sizeof(ushort));
size += sizeof(quint32) + sizeof(qint32) + cEmojiVariants().size() * (sizeof(uint32) + sizeof(uint64)); size += sizeof(quint32) + sizeof(qint32) + cEmojiVariants().size() * (sizeof(uint32) + sizeof(uint64));
size += sizeof(quint32) + sizeof(qint32) + (cRecentStickersPreload().isEmpty() ? cGetRecentStickers().size() : cRecentStickersPreload().size()) * (sizeof(uint64) + sizeof(ushort)); size += sizeof(quint32) + sizeof(qint32) + (cRecentStickersPreload().isEmpty() ? cGetRecentStickers().size() : cRecentStickersPreload().size()) * (sizeof(uint64) + sizeof(ushort));
@ -1380,7 +1418,7 @@ namespace {
data.stream << quint32(dbiNotifyView) << qint32(cNotifyView()); data.stream << quint32(dbiNotifyView) << qint32(cNotifyView());
data.stream << quint32(dbiWindowsNotifications) << qint32(cWindowsNotifications()); data.stream << quint32(dbiWindowsNotifications) << qint32(cWindowsNotifications());
data.stream << quint32(dbiAskDownloadPath) << qint32(cAskDownloadPath()); data.stream << quint32(dbiAskDownloadPath) << qint32(cAskDownloadPath());
data.stream << quint32(dbiDownloadPath) << (cAskDownloadPath() ? QString() : cDownloadPath()); data.stream << quint32(dbiDownloadPath) << (cAskDownloadPath() ? QString() : cDownloadPath()) << (cAskDownloadPath() ? QByteArray() : cDownloadPathBookmark());
data.stream << quint32(dbiCompressPastedImage) << qint32(cCompressPastedImage()); data.stream << quint32(dbiCompressPastedImage) << qint32(cCompressPastedImage());
data.stream << quint32(dbiEmojiTab) << qint32(cEmojiTab()); data.stream << quint32(dbiEmojiTab) << qint32(cEmojiTab());
data.stream << quint32(dbiDialogLastPath) << cDialogLastPath(); data.stream << quint32(dbiDialogLastPath) << cDialogLastPath();
@ -2178,14 +2216,14 @@ namespace Local {
} }
void writeFileLocation(MediaKey location, const FileLocation &local) { void writeFileLocation(MediaKey location, const FileLocation &local) {
if (local.name.isEmpty()) return; if (local.fname.isEmpty()) return;
FileLocationAliases::const_iterator aliasIt = _fileLocationAliases.constFind(location); FileLocationAliases::const_iterator aliasIt = _fileLocationAliases.constFind(location);
if (aliasIt != _fileLocationAliases.cend()) { if (aliasIt != _fileLocationAliases.cend()) {
location = aliasIt.value(); location = aliasIt.value();
} }
FileLocationPairs::iterator i = _fileLocationPairs.find(local.name); FileLocationPairs::iterator i = _fileLocationPairs.find(local.fname);
if (i != _fileLocationPairs.cend()) { if (i != _fileLocationPairs.cend()) {
if (i.value().second == local) { if (i.value().second == local) {
if (i.value().first != location) { if (i.value().first != location) {
@ -2205,7 +2243,7 @@ namespace Local {
} }
} }
_fileLocations.insert(location, local); _fileLocations.insert(location, local);
_fileLocationPairs.insert(local.name, FileLocationPair(location, local)); _fileLocationPairs.insert(local.fname, FileLocationPair(location, local));
_writeLocations(WriteMapFast); _writeLocations(WriteMapFast);
} }
@ -2218,9 +2256,8 @@ namespace Local {
FileLocations::iterator i = _fileLocations.find(location); FileLocations::iterator i = _fileLocations.find(location);
for (FileLocations::iterator i = _fileLocations.find(location); (i != _fileLocations.end()) && (i.key() == location);) { for (FileLocations::iterator i = _fileLocations.find(location); (i != _fileLocations.end()) && (i.key() == location);) {
if (check) { if (check) {
QFileInfo info(i.value().name); if (!i.value().check()) {
if (!info.exists() || info.lastModified() != i.value().modified || info.size() != i.value().size) { _fileLocationPairs.remove(i.value().fname);
_fileLocationPairs.remove(i.value().name);
i = _fileLocations.erase(i); i = _fileLocations.erase(i);
_writeLocations(); _writeLocations();
continue; continue;

View File

@ -30,6 +30,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include "boxes/confirmbox.h" #include "boxes/confirmbox.h"
#include "boxes/stickersetbox.h" #include "boxes/stickersetbox.h"
#include "boxes/contactsbox.h" #include "boxes/contactsbox.h"
#include "boxes/downloadpathbox.h"
#include "localstorage.h" #include "localstorage.h"
@ -1585,6 +1586,7 @@ void MainWidget::messagesAffected(PeerData *peer, const MTPmessages_AffectedMess
void MainWidget::videoLoadProgress(mtpFileLoader *loader) { void MainWidget::videoLoadProgress(mtpFileLoader *loader) {
VideoData *video = App::video(loader->objId()); VideoData *video = App::video(loader->objId());
if (video->loader) { if (video->loader) {
video->status = FileReady;
if (video->loader->done()) { if (video->loader->done()) {
video->finish(); video->finish();
QString already = video->already(); QString already = video->already();
@ -1614,7 +1616,17 @@ void MainWidget::loadFailed(mtpFileLoader *loader, bool started, const char *ret
if (started) { if (started) {
connect(box, SIGNAL(confirmed()), this, retrySlot); connect(box, SIGNAL(confirmed()), this, retrySlot);
} else { } else {
connect(box, SIGNAL(confirmed()), App::wnd(), SLOT(showSettings())); connect(box, SIGNAL(confirmed()), this, SLOT(onDownloadPathSettings()));
}
App::wnd()->showLayer(box);
}
void MainWidget::onDownloadPathSettings() {
cSetDownloadPath(QString());
cSetDownloadPathBookmark(QByteArray());
DownloadPathBox *box = new DownloadPathBox();
if (App::wnd() && App::wnd()->settingsWidget()) {
connect(box, SIGNAL(closed()), App::wnd()->settingsWidget(), SLOT(onDownloadPathEdited()));
} }
App::wnd()->showLayer(box); App::wnd()->showLayer(box);
} }
@ -1634,6 +1646,7 @@ void MainWidget::videoLoadRetry() {
void MainWidget::audioLoadProgress(mtpFileLoader *loader) { void MainWidget::audioLoadProgress(mtpFileLoader *loader) {
AudioData *audio = App::audio(loader->objId()); AudioData *audio = App::audio(loader->objId());
if (audio->loader) { if (audio->loader) {
audio->status = FileReady;
if (audio->loader->done()) { if (audio->loader->done()) {
audio->finish(); audio->finish();
QString already = audio->already(); QString already = audio->already();
@ -1688,7 +1701,7 @@ void MainWidget::audioPlayProgress(const AudioMsgId &audioId) {
if (f.write(audio->data) == audio->data.size()) { if (f.write(audio->data) == audio->data.size()) {
f.close(); f.close();
already = filename; already = filename;
audio->location = FileLocation(mtpToStorageType(mtpc_storage_filePartial), filename); audio->setLocation(FileLocation(StorageFilePartial, filename));
Local::writeFileLocation(mediaKey(mtpToLocationType(mtpc_inputAudioFileLocation), audio->dc, audio->id), FileLocation(mtpToStorageType(mtpc_storage_filePartial), filename)); Local::writeFileLocation(mediaKey(mtpToLocationType(mtpc_inputAudioFileLocation), audio->dc, audio->id), FileLocation(mtpToStorageType(mtpc_storage_filePartial), filename));
} }
} }
@ -1736,7 +1749,7 @@ void MainWidget::documentPlayProgress(const SongMsgId &songId) {
if (f.write(document->data) == document->data.size()) { if (f.write(document->data) == document->data.size()) {
f.close(); f.close();
already = filename; already = filename;
document->location = FileLocation(mtpToStorageType(mtpc_storage_filePartial), filename); document->setLocation(FileLocation(StorageFilePartial, filename));
Local::writeFileLocation(mediaKey(mtpToLocationType(mtpc_inputDocumentFileLocation), document->dc, document->id), FileLocation(mtpToStorageType(mtpc_storage_filePartial), filename)); Local::writeFileLocation(mediaKey(mtpToLocationType(mtpc_inputDocumentFileLocation), document->dc, document->id), FileLocation(mtpToStorageType(mtpc_storage_filePartial), filename));
} }
} }
@ -1793,6 +1806,7 @@ void MainWidget::documentLoadProgress(mtpFileLoader *loader) {
bool songPlayActivated = false; bool songPlayActivated = false;
DocumentData *document = App::document(loader->objId()); DocumentData *document = App::document(loader->objId());
if (document->loader) { if (document->loader) {
document->status = FileReady;
if (document->loader->done()) { if (document->loader->done()) {
document->finish(); document->finish();
QString already = document->already(); QString already = document->already();
@ -1814,10 +1828,12 @@ void MainWidget::documentLoadProgress(mtpFileLoader *loader) {
songPlayActivated = true; songPlayActivated = true;
} else if (document->openOnSave > 0 && document->size < MediaViewImageSizeLimit) { } else if (document->openOnSave > 0 && document->size < MediaViewImageSizeLimit) {
QImageReader reader(already); const FileLocation &location(document->location(true));
if (location.accessEnable()) {
QImageReader reader(location.name());
if (reader.canRead()) { if (reader.canRead()) {
if (reader.supportsAnimation() && reader.imageCount() > 1 && item) { if (reader.supportsAnimation() && reader.imageCount() > 1 && item) {
startGif(item, already); startGif(item, location);
} else if (item) { } else if (item) {
App::wnd()->showDocument(document, item); App::wnd()->showDocument(document, item);
} else { } else {
@ -1826,6 +1842,10 @@ void MainWidget::documentLoadProgress(mtpFileLoader *loader) {
} else { } else {
psOpenFile(already); psOpenFile(already);
} }
location.accessDisable();
} else {
psOpenFile(already);
}
} else { } else {
QPoint pos(QCursor::pos()); QPoint pos(QCursor::pos());
if (document->openOnSave < 0 && !psShowOpenWithMenu(pos.x(), pos.y(), already)) { if (document->openOnSave < 0 && !psShowOpenWithMenu(pos.x(), pos.y(), already)) {

View File

@ -482,6 +482,8 @@ public slots:
void onViewsIncrement(); void onViewsIncrement();
void onActiveChannelUpdateFull(); void onActiveChannelUpdateFull();
void onDownloadPathSettings();
private: private:
void sendReadRequest(PeerData *peer, MsgId upTo); void sendReadRequest(PeerData *peer, MsgId upTo);

View File

@ -453,11 +453,14 @@ bool MediaView::animStep(float64 msp) {
_docRadialFirst = _docRadialLast = _docRadialStart = 0; _docRadialFirst = _docRadialLast = _docRadialStart = 0;
a_docRadial = anim::fvalue(0, 0); a_docRadial = anim::fvalue(0, 0);
if (!_doc->already().isEmpty() && _doc->size < MediaViewImageSizeLimit) { if (!_doc->already().isEmpty() && _doc->size < MediaViewImageSizeLimit) {
QString fname(_doc->already(true)); const FileLocation &location(_doc->location(true));
QImageReader reader(fname); if (location.accessEnable()) {
QImageReader reader(location.name());
if (reader.canRead()) { if (reader.canRead()) {
displayDocument(_doc, App::histItemById(_msgmigrated ? 0 : _channel, _msgid)); displayDocument(_doc, App::histItemById(_msgmigrated ? 0 : _channel, _msgid));
} }
location.accessDisable();
}
} }
} else { } else {
float64 r = dt / st::radialDuration; float64 r = dt / st::radialDuration;
@ -529,20 +532,9 @@ void MediaView::onToMessage() {
void MediaView::onSaveAs() { void MediaView::onSaveAs() {
QString file; QString file;
if (_doc) { if (_doc) {
QString cur = _doc->already(true); const FileLocation &location(_doc->location(true));
if (cur.isEmpty()) { if (location.accessEnable()) {
if (_current.isNull() && _currentGif.isNull()) { QFileInfo alreadyInfo(location.name());
DocumentSaveLink::doSave(_doc, true);
updateControls();
} else {
_saveVisible = false;
update(_saveNav);
}
updateOver(_lastMouseMovePos);
return;
}
QFileInfo alreadyInfo(cur);
QDir alreadyDir(alreadyInfo.dir()); QDir alreadyDir(alreadyInfo.dir());
QString name = alreadyInfo.fileName(), filter; QString name = alreadyInfo.fileName(), filter;
MimeType mimeType = mimeTypeForName(_doc->mime); MimeType mimeType = mimeTypeForName(_doc->mime);
@ -561,8 +553,20 @@ void MediaView::onSaveAs() {
psBringToBack(this); psBringToBack(this);
file = saveFileName(lang(lng_save_file), filter, qsl("doc"), name, true, alreadyDir); file = saveFileName(lang(lng_save_file), filter, qsl("doc"), name, true, alreadyDir);
psShowOverAll(this); psShowOverAll(this);
if (!file.isEmpty() && file != cur) { if (!file.isEmpty() && file != location.name()) {
QFile(cur).copy(file); QFile(location.name()).copy(file);
}
location.accessDisable();
} else {
if (_current.isNull() && _currentGif.isNull()) {
DocumentSaveLink::doSave(_doc, true);
updateControls();
} else {
_saveVisible = false;
update(_saveNav);
}
updateOver(_lastMouseMovePos);
} }
} else { } else {
if (!_photo || !_photo->full->loaded()) return; if (!_photo || !_photo->full->loaded()) return;
@ -609,8 +613,15 @@ void MediaView::onDownload() {
} }
QString toName; QString toName;
if (_doc) { if (_doc) {
QString cur = _doc->already(true); const FileLocation &location(_doc->location(true));
if (cur.isEmpty()) { if (location.accessEnable()) {
if (!QDir().exists(path)) QDir().mkpath(path);
toName = filedialogNextFilename(_doc->name, location.name(), path);
if (toName != location.name() && !QFile(location.name()).copy(toName)) {
toName = QString();
}
location.accessDisable();
} else {
if (_current.isNull() && _currentGif.isNull()) { if (_current.isNull() && _currentGif.isNull()) {
DocumentSaveLink::doSave(_doc); DocumentSaveLink::doSave(_doc);
updateControls(); updateControls();
@ -619,12 +630,6 @@ void MediaView::onDownload() {
update(_saveNav); update(_saveNav);
} }
updateOver(_lastMouseMovePos); updateOver(_lastMouseMovePos);
} else {
if (!QDir().exists(path)) QDir().mkpath(path);
toName = filedialogNextFilename(_doc->name, cur, path);
if (toName != cur && !QFile(cur).copy(toName)) {
toName = QString();
}
} }
} else { } else {
if (!_photo || !_photo->full->loaded()) { if (!_photo || !_photo->full->loaded()) {
@ -902,25 +907,26 @@ void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) { // empty
_caption = Text(); _caption = Text();
if (_doc) { if (_doc) {
QString already = _doc->already(true); const FileLocation &location(_doc->location(true));
if (_doc->sticker() && !_doc->sticker()->img->isNull() && _doc->sticker()->img->loaded()) { if (_doc->sticker() && !_doc->sticker()->img->isNull() && _doc->sticker()->img->loaded()) {
_currentGif.stop(); _currentGif.stop();
_current = _doc->sticker()->img->pix(); _current = _doc->sticker()->img->pix();
} else if (!already.isEmpty()) { } else if (location.accessEnable()) {
QImageReader reader(already); QImageReader reader(location.name());
if (reader.canRead()) { if (reader.canRead()) {
if (reader.supportsAnimation() && reader.imageCount() > 1) { if (reader.supportsAnimation() && reader.imageCount() > 1) {
_currentGif.start(0, already); _currentGif.start(0, location);
_current = QPixmap(); _current = QPixmap();
} else { } else {
_currentGif.stop(); _currentGif.stop();
QPixmap pix = QPixmap::fromImage(App::readImage(already, 0, false), Qt::ColorOnly); QPixmap pix = QPixmap::fromImage(App::readImage(location.name(), 0, false), Qt::ColorOnly);
_current = pix; _current = pix;
} }
} else { } else {
_currentGif.stop(); _currentGif.stop();
_current = QPixmap(); _current = QPixmap();
} }
location.accessDisable();
} else { } else {
_currentGif.stop(); _currentGif.stop();
_current = QPixmap(); _current = QPixmap();

View File

@ -78,7 +78,6 @@ void PasscodeWidget::onSubmit() {
} else { } else {
if (Local::readMap(_passcode.text().toUtf8()) != Local::ReadMapPassNeeded) { if (Local::readMap(_passcode.text().toUtf8()) != Local::ReadMapPassNeeded) {
cSetPasscodeBadTries(0); cSetPasscodeBadTries(0);
App::app()->checkMapVersion();
MTP::start(); MTP::start();
if (MTP::authedId()) { if (MTP::authedId()) {
@ -86,6 +85,8 @@ void PasscodeWidget::onSubmit() {
} else { } else {
App::wnd()->setupIntro(true); App::wnd()->setupIntro(true);
} }
App::app()->checkMapVersion();
} else { } else {
cSetPasscodeBadTries(cPasscodeBadTries() + 1); cSetPasscodeBadTries(cPasscodeBadTries() + 1);
cSetPasscodeLastTry(getms(true)); cSetPasscodeLastTry(getms(true));

View File

@ -323,7 +323,7 @@ void PlayerWidget::preloadNext() {
} }
if (next) { if (next) {
if (HistoryDocument *document = static_cast<HistoryDocument*>(next->getMedia())) { if (HistoryDocument *document = static_cast<HistoryDocument*>(next->getMedia())) {
if (document->document()->already(true).isEmpty() && document->document()->data.isEmpty()) { if (document->document()->location(true).isEmpty() && document->document()->data.isEmpty()) {
if (!document->document()->loader) { if (!document->document()->loader) {
DocumentOpenLink::doOpen(document->document()); DocumentOpenLink::doOpen(document->document());
document->document()->openOnSave = 0; document->document()->openOnSave = 0;

View File

@ -175,5 +175,34 @@ void psUpdateOverlayed(QWidget *widget);
inline QString psConvertFileUrl(const QString &url) { inline QString psConvertFileUrl(const QString &url) {
return url; return url;
} }
inline QByteArray psDownloadPathBookmark(const QString &path) {
return QByteArray();
}
inline QByteArray psPathBookmark(const QString &path) {
return QByteArray();
}
inline void psDownloadPathEnableAccess() {
}
class PsFileBookmark {
public:
PsFileBookmark(const QByteArray &bookmark) {
}
bool check() const {
return true;
}
bool enable() const {
return true;
}
void disable() const {
}
const QString &name(const QString &original) const {
return original;
}
QByteArray bookmark() const {
return QByteArray();
}
};
bool linuxMoveFile(const char *from, const char *to); bool linuxMoveFile(const char *from, const char *to);

View File

@ -684,6 +684,18 @@ QString psConvertFileUrl(const QString &url) {
return objc_convertFileUrl(url); return objc_convertFileUrl(url);
} }
void psDownloadPathEnableAccess() {
objc_downloadPathEnableAccess(cDownloadPathBookmark());
}
QByteArray psDownloadPathBookmark(const QString &path) {
return objc_downloadPathBookmark(path);
}
QByteArray psPathBookmark(const QString &path) {
return objc_pathBookmark(path);
}
QString strNotificationAboutThemeChange() { QString strNotificationAboutThemeChange() {
const uint32 letters[] = { 0xE9005541, 0x5600DC70, 0x88001570, 0xF500D86C, 0x8100E165, 0xEE005949, 0x2900526E, 0xAE00FB74, 0x96000865, 0x7000CD72, 0x3B001566, 0x5F007361, 0xAE00B663, 0x74009A65, 0x29003054, 0xC6002668, 0x98003865, 0xFA00336D, 0xA3007A65, 0x93001443, 0xBB007868, 0xE100E561, 0x3500366E, 0xC0007A67, 0x200CA65, 0xBE00DF64, 0xE300BB4E, 0x2900D26F, 0xD500D374, 0xE900E269, 0x86008F66, 0xC4006669, 0x1C00A863, 0xE600A761, 0x8E00EE74, 0xB300B169, 0xCF00B36F, 0xE600D36E }; const uint32 letters[] = { 0xE9005541, 0x5600DC70, 0x88001570, 0xF500D86C, 0x8100E165, 0xEE005949, 0x2900526E, 0xAE00FB74, 0x96000865, 0x7000CD72, 0x3B001566, 0x5F007361, 0xAE00B663, 0x74009A65, 0x29003054, 0xC6002668, 0x98003865, 0xFA00336D, 0xA3007A65, 0x93001443, 0xBB007868, 0xE100E561, 0x3500366E, 0xC0007A67, 0x200CA65, 0xBE00DF64, 0xE300BB4E, 0x2900D26F, 0xD500D374, 0xE900E269, 0x86008F66, 0xC4006669, 0x1C00A863, 0xE600A761, 0x8E00EE74, 0xB300B169, 0xCF00B36F, 0xE600D36E };
return strMakeFromLetters(letters, sizeof(letters) / sizeof(letters[0])); return strMakeFromLetters(letters, sizeof(letters) / sizeof(letters[0]));

View File

@ -198,6 +198,35 @@ void psNewVersion();
void psUpdateOverlayed(QWidget *widget); void psUpdateOverlayed(QWidget *widget);
QString psConvertFileUrl(const QString &url); QString psConvertFileUrl(const QString &url);
void psDownloadPathEnableAccess();
QByteArray psDownloadPathBookmark(const QString &path);
QByteArray psPathBookmark(const QString &path);
class PsFileBookmark {
public:
PsFileBookmark(const QByteArray &bookmark) : _inner(bookmark) {
}
bool check() const {
return _inner.valid();
}
bool enable() const {
return _inner.enable();
}
void disable() const {
return _inner.disable();
}
const QString &name(const QString &original) const {
return _inner.name(original);
}
QByteArray bookmark() const {
return _inner.bookmark();
}
private:
objc_FileBookmark _inner;
};
QString strNotificationAboutThemeChange(); QString strNotificationAboutThemeChange();
QString strStyleOfInterface(); QString strStyleOfInterface();
QString strNeedToReload(); QString strNeedToReload();

View File

@ -82,3 +82,20 @@ QString objc_downloadPath();
QString objc_currentCountry(); QString objc_currentCountry();
QString objc_currentLang(); QString objc_currentLang();
QString objc_convertFileUrl(const QString &url); QString objc_convertFileUrl(const QString &url);
QByteArray objc_downloadPathBookmark(const QString &path);
QByteArray objc_pathBookmark(const QString &path);
void objc_downloadPathEnableAccess(const QByteArray &bookmark);
class objc_FileBookmark {
public:
objc_FileBookmark(const QByteArray &bookmark);
bool valid() const;
bool enable() const;
void disable() const;
const QString &name(const QString &original) const;
QByteArray bookmark() const;
~objc_FileBookmark();
};

View File

@ -931,8 +931,16 @@ void objc_start() {
name: NSWorkspaceDidWakeNotification object: NULL]; name: NSWorkspaceDidWakeNotification object: NULL];
} }
namespace {
NSURL *_downloadPathUrl = nil;
}
void objc_finish() { void objc_finish() {
[_sharedDelegate release]; [_sharedDelegate release];
if (_downloadPathUrl) {
[_downloadPathUrl stopAccessingSecurityScopedResource];
_downloadPathUrl = nil;
}
} }
void objc_registerCustomScheme() { void objc_registerCustomScheme() {
@ -1054,3 +1062,38 @@ QString objc_convertFileUrl(const QString &url) {
return objcString(nsurl); return objcString(nsurl);
} }
QByteArray objc_downloadPathBookmark(const QString &path) {
return QByteArray();
}
QByteArray objc_pathBookmark(const QString &path) {
return QByteArray();
}
void objc_downloadPathEnableAccess(const QByteArray &bookmark) {
}
objc_FileBookmark::objc_FileBookmark(const QByteArray &bookmark) {
}
bool objc_FileBookmark::valid() const {
return true;
}
bool objc_FileBookmark::enable() const {
return true;
}
void objc_FileBookmark::disable() const {
}
const QString &objc_FileBookmark::name(const QString &original) const {
return original;
}
QByteArray objc_FileBookmark::bookmark() const {
return QByteArray();
}
objc_FileBookmark::~objc_FileBookmark() {
}

View File

@ -177,3 +177,32 @@ void psUpdateOverlayed(TWidget *widget);
inline QString psConvertFileUrl(const QString &url) { inline QString psConvertFileUrl(const QString &url) {
return url; return url;
} }
inline QByteArray psDownloadPathBookmark(const QString &path) {
return QByteArray();
}
inline QByteArray psPathBookmark(const QString &path) {
return QByteArray();
}
inline void psDownloadPathEnableAccess() {
}
class PsFileBookmark {
public:
PsFileBookmark(const QByteArray &bookmark) {
}
bool check() const {
return true;
}
bool enable() const {
return true;
}
void disable() const {
}
const QString &name(const QString &original) const {
return original;
}
QByteArray bookmark() const {
return QByteArray();
}
};

View File

@ -74,6 +74,7 @@ DBIDefaultAttach gDefaultAttach = dbidaDocument;
bool gReplaceEmojis = true; bool gReplaceEmojis = true;
bool gAskDownloadPath = false; bool gAskDownloadPath = false;
QString gDownloadPath; QString gDownloadPath;
QByteArray gDownloadPathBookmark;
bool gNeedConfigResave = false; bool gNeedConfigResave = false;

View File

@ -134,6 +134,7 @@ DeclareSetting(bool, ReplaceEmojis);
DeclareReadSetting(bool, ManyInstance); DeclareReadSetting(bool, ManyInstance);
DeclareSetting(bool, AskDownloadPath); DeclareSetting(bool, AskDownloadPath);
DeclareSetting(QString, DownloadPath); DeclareSetting(QString, DownloadPath);
DeclareSetting(QByteArray, DownloadPathBookmark);
DeclareSetting(QByteArray, LocalSalt); DeclareSetting(QByteArray, LocalSalt);
DeclareSetting(DBIScale, RealScale); DeclareSetting(DBIScale, RealScale);
DeclareSetting(DBIScale, ScreenScale); DeclareSetting(DBIScale, ScreenScale);

View File

@ -710,7 +710,7 @@ void VideoCancelLink::onClick(Qt::MouseButton button) const {
VideoData::VideoData(const VideoId &id, const uint64 &access, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size) : VideoData::VideoData(const VideoId &id, const uint64 &access, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size) :
id(id), access(access), date(date), duration(duration), w(w), h(h), thumb(thumb), dc(dc), size(size), status(FileReady), uploadOffset(0), fileType(0), openOnSave(0), loader(0) { id(id), access(access), date(date), duration(duration), w(w), h(h), thumb(thumb), dc(dc), size(size), status(FileReady), uploadOffset(0), fileType(0), openOnSave(0), loader(0) {
location = Local::readFileLocation(mediaKey(VideoFileLocation, dc, id)); _location = Local::readFileLocation(mediaKey(VideoFileLocation, dc, id));
} }
void VideoData::save(const QString &toFile) { void VideoData::save(const QString &toFile) {
@ -722,9 +722,12 @@ void VideoData::save(const QString &toFile) {
} }
QString VideoData::already(bool check) { QString VideoData::already(bool check) {
if (!check) return location.name; return location(check).name();
if (!location.check()) location = Local::readFileLocation(mediaKey(VideoFileLocation, dc, id)); }
return location.name;
const FileLocation &VideoData::location(bool check) {
if (check && !_location.check()) _location = Local::readFileLocation(mediaKey(VideoFileLocation, dc, id));
return _location;
} }
void AudioOpenLink::onClick(Qt::MouseButton button) const { void AudioOpenLink::onClick(Qt::MouseButton button) const {
@ -818,7 +821,7 @@ bool StickerData::setInstalled() const {
AudioData::AudioData(const AudioId &id, const uint64 &access, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) : AudioData::AudioData(const AudioId &id, const uint64 &access, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) :
id(id), access(access), date(date), mime(mime), duration(duration), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), loader(0) { id(id), access(access), date(date), mime(mime), duration(duration), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), loader(0) {
location = Local::readFileLocation(mediaKey(AudioFileLocation, dc, id)); _location = Local::readFileLocation(mediaKey(AudioFileLocation, dc, id));
} }
void AudioData::save(const QString &toFile) { void AudioData::save(const QString &toFile) {
@ -830,17 +833,20 @@ void AudioData::save(const QString &toFile) {
} }
QString AudioData::already(bool check) { QString AudioData::already(bool check) {
if (!check) return location.name; return location(check).name();
if (!location.check()) location = Local::readFileLocation(mediaKey(AudioFileLocation, dc, id)); }
return location.name;
const FileLocation &AudioData::location(bool check) {
if (check && !_location.check()) _location = Local::readFileLocation(mediaKey(AudioFileLocation, dc, id));
return _location;
} }
void DocumentOpenLink::doOpen(DocumentData *data) { void DocumentOpenLink::doOpen(DocumentData *data) {
if (!data->date) return; if (!data->date) return;
bool play = data->song() && App::hoveredLinkItem() && audioPlayer(); bool play = data->song() && App::hoveredLinkItem() && audioPlayer();
QString already = data->already(true); const FileLocation &location(data->location(true));
if (!already.isEmpty() || (!data->data.isEmpty() && play)) { if (!location.isEmpty() || (!data->data.isEmpty() && play)) {
if (play) { if (play) {
SongMsgId playing; SongMsgId playing;
AudioPlayerState playingState = AudioPlayerStopped; AudioPlayerState playingState = AudioPlayerStopped;
@ -852,21 +858,22 @@ void DocumentOpenLink::doOpen(DocumentData *data) {
audioPlayer()->play(song); audioPlayer()->play(song);
if (App::main()) App::main()->documentPlayProgress(song); if (App::main()) App::main()->documentPlayProgress(song);
} }
} else if (data->size < MediaViewImageSizeLimit) { } else if (data->size < MediaViewImageSizeLimit && location.accessEnable()) {
QImageReader reader(already); QImageReader reader(location.name());
if (reader.canRead()) { if (reader.canRead()) {
if (reader.supportsAnimation() && reader.imageCount() > 1 && App::hoveredLinkItem()) { if (reader.supportsAnimation() && reader.imageCount() > 1 && App::hoveredLinkItem()) {
startGif(App::hoveredLinkItem(), already); startGif(App::hoveredLinkItem(), location);
} else if (App::hoveredLinkItem() || App::contextItem()) { } else if (App::hoveredLinkItem() || App::contextItem()) {
App::wnd()->showDocument(data, App::hoveredLinkItem() ? App::hoveredLinkItem() : App::contextItem()); App::wnd()->showDocument(data, App::hoveredLinkItem() ? App::hoveredLinkItem() : App::contextItem());
} else { } else {
psOpenFile(already); psOpenFile(location.name());
} }
} else { } else {
psOpenFile(already); psOpenFile(location.name());
} }
location.accessDisable();
} else { } else {
psOpenFile(already); psOpenFile(location.name());
} }
return; return;
} }
@ -954,7 +961,7 @@ void DocumentCancelLink::onClick(Qt::MouseButton button) const {
DocumentData::DocumentData(const DocumentId &id, const uint64 &access, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size) : DocumentData::DocumentData(const DocumentId &id, const uint64 &access, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size) :
id(id), type(FileDocument), access(access), date(date), mime(mime), thumb(thumb), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), loader(0), _additional(0) { id(id), type(FileDocument), access(access), date(date), mime(mime), thumb(thumb), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), loader(0), _additional(0) {
setattributes(attributes); setattributes(attributes);
location = Local::readFileLocation(mediaKey(DocumentFileLocation, dc, id)); _location = Local::readFileLocation(mediaKey(DocumentFileLocation, dc, id));
} }
void DocumentData::setattributes(const QVector<MTPDocumentAttribute> &attributes) { void DocumentData::setattributes(const QVector<MTPDocumentAttribute> &attributes) {
@ -1016,9 +1023,12 @@ void DocumentData::save(const QString &toFile) {
} }
QString DocumentData::already(bool check) { QString DocumentData::already(bool check) {
if (!check) return location.name; return location(check).name();
if (!location.check()) location = Local::readFileLocation(mediaKey(DocumentFileLocation, dc, id)); }
return location.name;
const FileLocation &DocumentData::location(bool check) {
if (check && !_location.check()) _location = Local::readFileLocation(mediaKey(DocumentFileLocation, dc, id));
return _location;
} }
WebPageData::WebPageData(const WebPageId &id, WebPageType type, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const QString &description, PhotoData *photo, DocumentData *doc, int32 duration, const QString &author, int32 pendingTill) : WebPageData::WebPageData(const WebPageId &id, WebPageType type, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const QString &description, PhotoData *photo, DocumentData *doc, int32 duration, const QString &author, int32 pendingTill) :

View File

@ -807,7 +807,7 @@ struct VideoData {
l->deleteLater(); l->deleteLater();
l->rpcInvalidate(); l->rpcInvalidate();
} }
location = FileLocation(); _location = FileLocation();
if (!beforeDownload) { if (!beforeDownload) {
openOnSave = 0; openOnSave = 0;
openOnSaveMsgId = FullMsgId(); openOnSaveMsgId = FullMsgId();
@ -816,7 +816,7 @@ struct VideoData {
void finish() { void finish() {
if (loader->done()) { if (loader->done()) {
location = FileLocation(mtpToStorageType(loader->fileType()), loader->fileName()); _location = FileLocation(mtpToStorageType(loader->fileType()), loader->fileName());
} }
loader->deleteLater(); loader->deleteLater();
loader->rpcInvalidate(); loader->rpcInvalidate();
@ -824,6 +824,7 @@ struct VideoData {
} }
QString already(bool check = false); QString already(bool check = false);
const FileLocation &location(bool check = false);
VideoId id; VideoId id;
uint64 access; uint64 access;
@ -841,7 +842,10 @@ struct VideoData {
int32 openOnSave; int32 openOnSave;
FullMsgId openOnSaveMsgId; FullMsgId openOnSaveMsgId;
mtpFileLoader *loader; mtpFileLoader *loader;
FileLocation location;
private:
FileLocation _location;
}; };
class VideoLink : public ITextLink { class VideoLink : public ITextLink {
@ -902,7 +906,7 @@ struct AudioData {
l->deleteLater(); l->deleteLater();
l->rpcInvalidate(); l->rpcInvalidate();
} }
location = FileLocation(); _location = FileLocation();
if (!beforeDownload) { if (!beforeDownload) {
openOnSave = 0; openOnSave = 0;
openOnSaveMsgId = FullMsgId(); openOnSaveMsgId = FullMsgId();
@ -911,7 +915,7 @@ struct AudioData {
void finish() { void finish() {
if (loader->done()) { if (loader->done()) {
location = FileLocation(mtpToStorageType(loader->fileType()), loader->fileName()); _location = FileLocation(mtpToStorageType(loader->fileType()), loader->fileName());
data = loader->bytes(); data = loader->bytes();
} }
loader->deleteLater(); loader->deleteLater();
@ -920,6 +924,12 @@ struct AudioData {
} }
QString already(bool check = false); QString already(bool check = false);
const FileLocation &location(bool check = false);
void setLocation(const FileLocation &loc) {
if (loc.check()) {
_location = loc;
}
}
AudioId id; AudioId id;
uint64 access; uint64 access;
@ -935,9 +945,12 @@ struct AudioData {
int32 openOnSave; int32 openOnSave;
FullMsgId openOnSaveMsgId; FullMsgId openOnSaveMsgId;
mtpFileLoader *loader; mtpFileLoader *loader;
FileLocation location;
QByteArray data; QByteArray data;
int32 md5[8]; int32 md5[8];
private:
FileLocation _location;
}; };
struct AudioMsgId { struct AudioMsgId {
@ -1068,7 +1081,7 @@ struct DocumentData {
l->deleteLater(); l->deleteLater();
l->rpcInvalidate(); l->rpcInvalidate();
} }
location = FileLocation(); _location = FileLocation();
if (!beforeDownload) { if (!beforeDownload) {
openOnSave = 0; openOnSave = 0;
openOnSaveMsgId = FullMsgId(); openOnSaveMsgId = FullMsgId();
@ -1077,7 +1090,7 @@ struct DocumentData {
void finish() { void finish() {
if (loader->done()) { if (loader->done()) {
location = FileLocation(mtpToStorageType(loader->fileType()), loader->fileName()); _location = FileLocation(mtpToStorageType(loader->fileType()), loader->fileName());
data = loader->bytes(); data = loader->bytes();
if (sticker() && !loader->imagePixmap().isNull()) { if (sticker() && !loader->imagePixmap().isNull()) {
sticker()->img = ImagePtr(data, loader->imageFormat(), loader->imagePixmap()); sticker()->img = ImagePtr(data, loader->imageFormat(), loader->imagePixmap());
@ -1092,6 +1105,12 @@ struct DocumentData {
} }
QString already(bool check = false); QString already(bool check = false);
const FileLocation &location(bool check = false);
void setLocation(const FileLocation &loc) {
if (loc.check()) {
_location = loc;
}
}
StickerData *sticker() { StickerData *sticker() {
return (type == StickerDocument) ? static_cast<StickerData*>(_additional) : 0; return (type == StickerDocument) ? static_cast<StickerData*>(_additional) : 0;
} }
@ -1115,12 +1134,15 @@ struct DocumentData {
int32 openOnSave; int32 openOnSave;
FullMsgId openOnSaveMsgId; FullMsgId openOnSaveMsgId;
mtpFileLoader *loader; mtpFileLoader *loader;
FileLocation location;
QByteArray data; QByteArray data;
DocumentAdditionalData *_additional; DocumentAdditionalData *_additional;
int32 md5[8]; int32 md5[8];
private:
FileLocation _location;
}; };
struct SongMsgId { struct SongMsgId {

View File

@ -258,7 +258,7 @@ enum DataBlockId {
dbiCatsAndDogs = 0x12, dbiCatsAndDogs = 0x12,
dbiReplaceEmojis = 0x13, dbiReplaceEmojis = 0x13,
dbiAskDownloadPath = 0x14, dbiAskDownloadPath = 0x14,
dbiDownloadPath = 0x15, dbiDownloadPathOld = 0x15,
dbiScale = 0x16, dbiScale = 0x16,
dbiEmojiTab = 0x17, dbiEmojiTab = 0x17,
dbiRecentEmojisOld = 0x18, dbiRecentEmojisOld = 0x18,
@ -282,6 +282,7 @@ enum DataBlockId {
dbiWindowsNotifications = 0x30, dbiWindowsNotifications = 0x30,
dbiIncludeMuted = 0x31, dbiIncludeMuted = 0x31,
dbiMaxMegaGroupCount = 0x32, dbiMaxMegaGroupCount = 0x32,
dbiDownloadPath = 0x33,
dbiEncryptedWithSalt = 333, dbiEncryptedWithSalt = 333,
dbiEncrypted = 444, dbiEncrypted = 444,