mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-02-20 15:17:41 +00:00
Merge branch 'master' of https://github.com/telegramdesktop/tdesktop
This commit is contained in:
commit
b8b4a81576
@ -192,7 +192,13 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
||||
"lng_settings_send_enter" = "Send by Enter";
|
||||
"lng_settings_send_ctrlenter" = "Send by Ctrl+Enter";
|
||||
"lng_settings_send_cmdenter" = "Send by Cmd+Enter";
|
||||
"lng_settings_cats_and_dogs" = "Allow cats and dogs";
|
||||
|
||||
"lng_settings_section_background" = "Chat background";
|
||||
"lng_settings_bg_from_gallery" = "Choose from gallery";
|
||||
"lng_settings_bg_from_file" = "Choose from file";
|
||||
"lng_settings_bg_tile" = "Tile background";
|
||||
|
||||
"lng_backgrounds_header" = "Choose your new chat background";
|
||||
|
||||
"lng_download_path_dont_ask" = "Don't ask download path for each file";
|
||||
"lng_download_path_label" = "Download path:";
|
||||
|
@ -350,8 +350,7 @@ introPointTop: 3px;
|
||||
introPointDelta: 10px;
|
||||
introPointColor: rgb(0, 0, 0);
|
||||
introPointAlpha: 0.5;
|
||||
introPointHoverColor: rgb(47, 158, 218);
|
||||
introPointHoverAlpha: 0.5;
|
||||
introPointHoverColor: #86b4e3;
|
||||
introPointStepT: transition(sineInOut);
|
||||
introPointAlphaT: transition(linear);
|
||||
introPointShowStepT: transition(easeOutCirc);
|
||||
@ -554,6 +553,8 @@ setErrHeight: 30px;
|
||||
setErrFont: font(fsize);
|
||||
setGoodColor: #008000;
|
||||
|
||||
setBackgroundSize: 120px;
|
||||
|
||||
btnSetUpload: flatButton(btnDefNext, btnDefBig) {
|
||||
width: 206px;
|
||||
height: 42px;
|
||||
@ -736,8 +737,6 @@ topBarActionButton: flatButton(btnDefNext, btnDefBig) {
|
||||
}
|
||||
topBarActionSkip: 13px;
|
||||
|
||||
historyBG: #dfe4e8;
|
||||
|
||||
historyToEnd: iconedButton(btnDefIconed) {
|
||||
bgColor: transparent;
|
||||
overBgColor: transparent;
|
||||
@ -1688,3 +1687,9 @@ langButton: flatCheckbox(rbDefFlat) {
|
||||
langsCloseButton: flatButton(aboutCloseButton) {
|
||||
width: langsWidth;
|
||||
}
|
||||
|
||||
backgroundPadding: 10px;
|
||||
backgroundSize: size(108px, 193px);
|
||||
backgroundScroll: flatScroll(newGroupScroll) {
|
||||
topsh: -2px;
|
||||
}
|
||||
|
@ -78,6 +78,13 @@ namespace {
|
||||
LastPhotosList lastPhotos;
|
||||
typedef QHash<PhotoData*, LastPhotosList::iterator> LastPhotosMap;
|
||||
LastPhotosMap lastPhotosMap;
|
||||
|
||||
style::color _msgServiceBG;
|
||||
style::color _historyScrollBarColor;
|
||||
style::color _historyScrollBgColor;
|
||||
style::color _historyScrollBarOverColor;
|
||||
style::color _historyScrollBgOverColor;
|
||||
style::color _introPointHoverColor;
|
||||
}
|
||||
|
||||
namespace App {
|
||||
@ -1390,6 +1397,7 @@ namespace App {
|
||||
clearAllImages();
|
||||
} else {
|
||||
clearStorageImages();
|
||||
cSetServerBackgrounds(WallPapers());
|
||||
}
|
||||
|
||||
serviceImageCacheSize = imageCacheSize();
|
||||
@ -1684,7 +1692,7 @@ namespace App {
|
||||
}
|
||||
|
||||
stream << quint32(dbiSendKey) << qint32(cCtrlEnter() ? dbiskCtrlEnter : dbiskEnter);
|
||||
stream << quint32(dbiCatsAndDogs) << qint32(cCatsAndDogs() ? 1 : 0);
|
||||
stream << quint32(dbiTileBackground) << qint32(cTileBackground() ? 1 : 0);
|
||||
stream << quint32(dbiReplaceEmojis) << qint32(cReplaceEmojis() ? 1 : 0);
|
||||
stream << quint32(dbiDefaultAttach) << qint32(cDefaultAttach());
|
||||
stream << quint32(dbiSoundNotify) << qint32(cSoundNotify());
|
||||
@ -1823,7 +1831,12 @@ namespace App {
|
||||
case dbiCatsAndDogs: {
|
||||
qint32 v;
|
||||
stream >> v;
|
||||
cSetCatsAndDogs(v == 1);
|
||||
} break;
|
||||
|
||||
case dbiTileBackground: {
|
||||
qint32 v;
|
||||
stream >> v;
|
||||
cSetTileBackground(v == 1);
|
||||
} break;
|
||||
|
||||
case dbiReplaceEmojis: {
|
||||
@ -2140,4 +2153,171 @@ namespace App {
|
||||
}
|
||||
}
|
||||
|
||||
void initBackground(int32 id, const QImage &p, bool nowrite) {
|
||||
if (Local::readBackground()) return;
|
||||
|
||||
QImage img(p);
|
||||
if (p.isNull()) {
|
||||
img.load(st::msgBG);
|
||||
id = 0;
|
||||
}
|
||||
if (img.format() != QImage::Format_ARGB32 && img.format() != QImage::Format_ARGB32_Premultiplied && img.format() != QImage::Format_RGB32) {
|
||||
img = img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
}
|
||||
|
||||
if (!nowrite) Local::writeBackground(id, img);
|
||||
|
||||
delete cChatBackground();
|
||||
cSetChatBackground(new QPixmap(QPixmap::fromImage(img, Qt::ColorOnly)));
|
||||
cSetChatBackgroundId(id);
|
||||
|
||||
if (App::main()) App::main()->clearCachedBackground();
|
||||
|
||||
uint64 components[3] = { 0 }, componentsScroll[3] = { 0 }, componentsPoint[3] = { 0 };
|
||||
int w = img.width(), h = img.height(), size = w * h;
|
||||
const uchar *pix = img.constBits();
|
||||
if (pix) {
|
||||
for (int32 i = 0, l = size * 4; i < l; i += 4) {
|
||||
components[2] += pix[i + 0];
|
||||
components[1] += pix[i + 1];
|
||||
components[0] += pix[i + 2];
|
||||
}
|
||||
}
|
||||
if (size) {
|
||||
for (int32 i = 0; i < 3; ++i) components[i] /= size;
|
||||
}
|
||||
int maxtomin[3] = { 0, 1, 2 };
|
||||
if (components[maxtomin[0]] < components[maxtomin[1]]) {
|
||||
qSwap(maxtomin[0], maxtomin[1]);
|
||||
}
|
||||
if (components[maxtomin[1]] < components[maxtomin[2]]) {
|
||||
qSwap(maxtomin[1], maxtomin[2]);
|
||||
if (components[maxtomin[0]] < components[maxtomin[1]]) {
|
||||
qSwap(maxtomin[0], maxtomin[1]);
|
||||
}
|
||||
}
|
||||
|
||||
uint64 max = qMax(1ULL, components[maxtomin[0]]), mid = qMax(1ULL, components[maxtomin[1]]), min = qMax(1ULL, components[maxtomin[2]]);
|
||||
|
||||
QImage dog = App::sprite().toImage().copy(st::msgDogImg);
|
||||
QImage::Format f = dog.format();
|
||||
if (f != QImage::Format_ARGB32 && f != QImage::Format_ARGB32_Premultiplied) {
|
||||
dog = dog.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
}
|
||||
uchar *dogBits = dog.bits();
|
||||
if (max != min) {
|
||||
float64 coef = float64(mid - min) / float64(max - min);
|
||||
for (int i = 0, s = dog.width() * dog.height() * 4; i < s; i += 4) {
|
||||
int dogmaxtomin[3] = { i, i + 1, i + 2 };
|
||||
if (dogBits[dogmaxtomin[0]] < dogBits[dogmaxtomin[1]]) {
|
||||
qSwap(dogmaxtomin[0], dogmaxtomin[1]);
|
||||
}
|
||||
if (dogBits[dogmaxtomin[1]] < dogBits[dogmaxtomin[2]]) {
|
||||
qSwap(dogmaxtomin[1], dogmaxtomin[2]);
|
||||
if (dogBits[dogmaxtomin[0]] < dogBits[dogmaxtomin[1]]) {
|
||||
qSwap(dogmaxtomin[0], dogmaxtomin[1]);
|
||||
}
|
||||
}
|
||||
uchar result[3];
|
||||
result[maxtomin[0]] = dogBits[dogmaxtomin[0]];
|
||||
result[maxtomin[2]] = dogBits[dogmaxtomin[2]];
|
||||
result[maxtomin[1]] = uchar(qRound(result[maxtomin[2]] + (result[maxtomin[0]] - result[maxtomin[2]]) * coef));
|
||||
dogBits[i] = result[2];
|
||||
dogBits[i + 1] = result[1];
|
||||
dogBits[i + 2] = result[0];
|
||||
}
|
||||
} else {
|
||||
for (int i = 0, s = dog.width() * dog.height() * 4; i < s; i += 4) {
|
||||
uchar b = dogBits[i], g = dogBits[i + 1], r = dogBits[i + 2];
|
||||
dogBits[i] = dogBits[i + 1] = dogBits[i + 2] = (r + r + b + g + g + g) / 6;
|
||||
}
|
||||
}
|
||||
delete cChatDogImage();
|
||||
cSetChatDogImage(new QPixmap(QPixmap::fromImage(dog)));
|
||||
|
||||
memcpy(componentsScroll, components, sizeof(components));
|
||||
memcpy(componentsPoint, components, sizeof(components));
|
||||
|
||||
if (max != min) {
|
||||
if (min > qRound(0.77 * max)) {
|
||||
uint64 newmin = qRound(0.77 * max); // min saturation 23%
|
||||
uint64 newmid = max - ((max - mid) * (max - newmin)) / (max - min);
|
||||
components[maxtomin[1]] = newmid;
|
||||
components[maxtomin[2]] = newmin;
|
||||
}
|
||||
uint64 newmin = qRound(0.77 * max); // saturation 23% for scroll
|
||||
uint64 newmid = max - ((max - mid) * (max - newmin)) / (max - min);
|
||||
componentsScroll[maxtomin[1]] = newmid;
|
||||
componentsScroll[maxtomin[2]] = newmin;
|
||||
|
||||
uint64 pmax = 227; // 89% brightness
|
||||
uint64 pmin = qRound(0.75 * pmax); // 41% saturation
|
||||
uint64 pmid = pmax - ((max - mid) * (pmax - pmin)) / (max - min);
|
||||
componentsPoint[maxtomin[0]] = pmax;
|
||||
componentsPoint[maxtomin[1]] = pmid;
|
||||
componentsPoint[maxtomin[2]] = pmin;
|
||||
} else {
|
||||
componentsPoint[0] = componentsPoint[1] = componentsPoint[2] = 227; // 89% brightness
|
||||
}
|
||||
|
||||
float64 luminance = 0.299 * componentsScroll[0] + 0.587 * componentsScroll[1] + 0.114 * componentsScroll[2];
|
||||
uint64 maxScroll = max;
|
||||
if (luminance < 0.5 * 0xFF) {
|
||||
maxScroll += qRound(0.2 * 0xFF);
|
||||
} else {
|
||||
maxScroll -= qRound(0.2 * 0xFF);
|
||||
}
|
||||
componentsScroll[maxtomin[2]] = qMin(uint64(float64(componentsScroll[maxtomin[2]]) * maxScroll / float64(componentsScroll[maxtomin[0]])), 0xFFULL);
|
||||
componentsScroll[maxtomin[1]] = qMin(uint64(float64(componentsScroll[maxtomin[1]]) * maxScroll / float64(componentsScroll[maxtomin[0]])), 0xFFULL);
|
||||
componentsScroll[maxtomin[0]] = qMin(maxScroll, 0xFFULL);
|
||||
|
||||
if (max > qRound(0.2 * 0xFF)) { // brightness greater than 20%
|
||||
max -= qRound(0.2 * 0xFF);
|
||||
} else {
|
||||
max = 0;
|
||||
}
|
||||
components[maxtomin[2]] = uint64(float64(components[maxtomin[2]]) * max / float64(components[maxtomin[0]]));
|
||||
components[maxtomin[1]] = uint64(float64(components[maxtomin[1]]) * max / float64(components[maxtomin[0]]));
|
||||
components[maxtomin[0]] = max;
|
||||
|
||||
uchar r = uchar(components[0]), g = uchar(components[1]), b = uchar(components[2]);
|
||||
_msgServiceBG = style::color(r, g, b, qRound(st::msgServiceBG->c.alphaF() * 0xFF));
|
||||
|
||||
uchar rScroll = uchar(componentsScroll[0]), gScroll = uchar(componentsScroll[1]), bScroll = uchar(componentsScroll[2]);
|
||||
_historyScrollBarColor = style::color(rScroll, gScroll, bScroll, qRound(st::historyScroll.barColor->c.alphaF() * 0xFF));
|
||||
_historyScrollBgColor = style::color(rScroll, gScroll, bScroll, qRound(st::historyScroll.bgColor->c.alphaF() * 0xFF));
|
||||
_historyScrollBarOverColor = style::color(rScroll, gScroll, bScroll, qRound(st::historyScroll.barOverColor->c.alphaF() * 0xFF));
|
||||
_historyScrollBgOverColor = style::color(rScroll, gScroll, bScroll, qRound(st::historyScroll.bgOverColor->c.alphaF() * 0xFF));
|
||||
|
||||
uchar rPoint = uchar(componentsPoint[0]), gPoint = uchar(componentsPoint[1]), bPoint = uchar(componentsPoint[2]);
|
||||
_introPointHoverColor = style::color(rPoint, gPoint, bPoint);
|
||||
if (App::main()) App::main()->updateScrollColors();
|
||||
}
|
||||
|
||||
style::color msgServiceBG() {
|
||||
return _msgServiceBG;
|
||||
}
|
||||
|
||||
style::color historyScrollBarColor() {
|
||||
return _historyScrollBarColor;
|
||||
}
|
||||
|
||||
style::color historyScrollBgColor() {
|
||||
return _historyScrollBgColor;
|
||||
}
|
||||
|
||||
style::color historyScrollBarOverColor() {
|
||||
return _historyScrollBarOverColor;
|
||||
}
|
||||
|
||||
style::color historyScrollBgOverColor() {
|
||||
return _historyScrollBgOverColor;
|
||||
}
|
||||
|
||||
style::color introPointHoverColor() {
|
||||
return _introPointHoverColor;
|
||||
}
|
||||
|
||||
WallPapers gServerBackgrounds;
|
||||
|
||||
}
|
||||
|
@ -81,6 +81,8 @@ namespace App {
|
||||
void feedMessageMedia(MsgId msgId, const MTPMessage &msg);
|
||||
int32 maxMsgId();
|
||||
|
||||
ImagePtr image(const MTPPhotoSize &size);
|
||||
|
||||
PhotoData *feedPhoto(const MTPPhoto &photo, const PreparedPhotoThumbs &thumbs);
|
||||
PhotoData *feedPhoto(const MTPPhoto &photo, PhotoData *convert = 0);
|
||||
PhotoData *feedPhoto(const MTPDphoto &photo, PhotoData *convert = 0);
|
||||
@ -191,4 +193,23 @@ namespace App {
|
||||
void openUserByName(const QString &username);
|
||||
void openLocalUrl(const QString &url);
|
||||
|
||||
void initBackground(int32 id = 0, const QImage &p = QImage(), bool nowrite = false);
|
||||
|
||||
style::color msgServiceBG();
|
||||
style::color historyScrollBarColor();
|
||||
style::color historyScrollBgColor();
|
||||
style::color historyScrollBarOverColor();
|
||||
style::color historyScrollBgOverColor();
|
||||
style::color introPointHoverColor();
|
||||
|
||||
struct WallPaper {
|
||||
WallPaper(int32 id, ImagePtr thumb, ImagePtr full) : id(id), thumb(thumb), full(full) {
|
||||
}
|
||||
int32 id;
|
||||
ImagePtr thumb;
|
||||
ImagePtr full;
|
||||
};
|
||||
typedef QList<WallPaper> WallPapers;
|
||||
DeclareSetting(WallPapers, ServerBackgrounds);
|
||||
|
||||
};
|
||||
|
@ -833,6 +833,12 @@ Application::~Application() {
|
||||
|
||||
delete window;
|
||||
|
||||
delete cChatBackground();
|
||||
cSetChatBackground(0);
|
||||
|
||||
delete cChatDogImage();
|
||||
cSetChatDogImage(0);
|
||||
|
||||
style::stopManager();
|
||||
Local::stop();
|
||||
|
||||
|
285
Telegram/SourceFiles/boxes/backgroundbox.cpp
Normal file
285
Telegram/SourceFiles/boxes/backgroundbox.cpp
Normal file
@ -0,0 +1,285 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "lang.h"
|
||||
|
||||
#include "backgroundbox.h"
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "settingswidget.h"
|
||||
|
||||
BackgroundInner::BackgroundInner() :
|
||||
_bgCount(0), _rows(0), _over(-1), _overDown(-1) {
|
||||
if (App::cServerBackgrounds().isEmpty()) {
|
||||
resize(BackgroundsInRow * (st::backgroundSize.width() + st::backgroundPadding) + st::backgroundPadding, 2 * (st::backgroundSize.height() + st::backgroundPadding) + st::backgroundPadding);
|
||||
MTP::send(MTPaccount_GetWallPapers(), rpcDone(&BackgroundInner::gotWallpapers));
|
||||
} else {
|
||||
updateWallpapers();
|
||||
}
|
||||
setMouseTracking(true);
|
||||
}
|
||||
|
||||
void BackgroundInner::gotWallpapers(const MTPVector<MTPWallPaper> &result) {
|
||||
App::WallPapers wallpapers;
|
||||
|
||||
wallpapers.push_back(App::WallPaper(0, ImagePtr(st::msgBG), ImagePtr(st::msgBG)));
|
||||
const QVector<MTPWallPaper> &v(result.c_vector().v);
|
||||
for (int i = 0, l = v.size(); i < l; ++i) {
|
||||
const MTPWallPaper w(v.at(i));
|
||||
switch (w.type()) {
|
||||
case mtpc_wallPaper: {
|
||||
const MTPDwallPaper &d(w.c_wallPaper());
|
||||
const QVector<MTPPhotoSize> &sizes(d.vsizes.c_vector().v);
|
||||
const MTPPhotoSize *thumb = 0, *full = 0;
|
||||
int32 thumbLevel = -1, fullLevel = -1;
|
||||
for (QVector<MTPPhotoSize>::const_iterator j = sizes.cbegin(), e = sizes.cend(); j != e; ++j) {
|
||||
char size = 0;
|
||||
int32 w = 0, h = 0;
|
||||
switch (j->type()) {
|
||||
case mtpc_photoSize: {
|
||||
const string &s(j->c_photoSize().vtype.c_string().v);
|
||||
if (s.size()) size = s[0];
|
||||
w = j->c_photoSize().vw.v;
|
||||
h = j->c_photoSize().vh.v;
|
||||
} break;
|
||||
|
||||
case mtpc_photoCachedSize: {
|
||||
const string &s(j->c_photoCachedSize().vtype.c_string().v);
|
||||
if (s.size()) size = s[0];
|
||||
w = j->c_photoCachedSize().vw.v;
|
||||
h = j->c_photoCachedSize().vh.v;
|
||||
} break;
|
||||
}
|
||||
if (!size || !w || !h) continue;
|
||||
|
||||
int32 newThumbLevel = qAbs(st::backgroundSize.width() - w), newFullLevel = qAbs(2560 - w);
|
||||
if (thumbLevel < 0 || newThumbLevel < thumbLevel) {
|
||||
thumbLevel = newThumbLevel;
|
||||
thumb = &(*j);
|
||||
}
|
||||
if (fullLevel < 0 || newFullLevel < fullLevel) {
|
||||
fullLevel = newFullLevel;
|
||||
full = &(*j);
|
||||
}
|
||||
}
|
||||
if (thumb && full && full->type() != mtpc_photoSizeEmpty) {
|
||||
wallpapers.push_back(App::WallPaper(d.vid.v, App::image(*thumb), App::image(*full)));
|
||||
}
|
||||
} break;
|
||||
|
||||
case mtpc_wallPaperSolid: {
|
||||
const MTPDwallPaperSolid &d(w.c_wallPaperSolid());
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
App::cSetServerBackgrounds(wallpapers);
|
||||
updateWallpapers();
|
||||
}
|
||||
|
||||
void BackgroundInner::updateWallpapers() {
|
||||
_bgCount = App::cServerBackgrounds().size();
|
||||
_rows = _bgCount / BackgroundsInRow;
|
||||
if (_bgCount % BackgroundsInRow) ++_rows;
|
||||
|
||||
resize(BackgroundsInRow * (st::backgroundSize.width() + st::backgroundPadding) + st::backgroundPadding, _rows * (st::backgroundSize.height() + st::backgroundPadding) + st::backgroundPadding);
|
||||
for (int i = 0; i < BackgroundsInRow * 3; ++i) {
|
||||
if (i >= _bgCount) break;
|
||||
|
||||
App::cServerBackgrounds().at(i).thumb->load();
|
||||
}
|
||||
}
|
||||
|
||||
void BackgroundInner::paintEvent(QPaintEvent *e) {
|
||||
QRect r(e->rect());
|
||||
QPainter p(this);
|
||||
|
||||
if (_rows) {
|
||||
for (int i = 0; i < _rows; ++i) {
|
||||
if ((st::backgroundSize.height() + st::backgroundPadding) * (i + 1) <= r.top()) continue;
|
||||
for (int j = 0; j < BackgroundsInRow; ++j) {
|
||||
int index = i * BackgroundsInRow + j;
|
||||
if (index >= _bgCount) break;
|
||||
|
||||
const App::WallPaper &paper(App::cServerBackgrounds().at(index));
|
||||
paper.thumb->load();
|
||||
|
||||
int x = st::backgroundPadding + j * (st::backgroundSize.width() + st::backgroundPadding);
|
||||
int y = st::backgroundPadding + i * (st::backgroundSize.height() + st::backgroundPadding);
|
||||
|
||||
const QPixmap &pix(paper.thumb->pix(st::backgroundSize.width(), st::backgroundSize.height()));
|
||||
p.drawPixmap(x, y, pix);
|
||||
|
||||
if (paper.id == cChatBackgroundId()) {
|
||||
p.drawPixmap(QPoint(x + st::backgroundSize.width() - st::overviewPhotoChecked.pxWidth(), y + st::backgroundSize.height() - st::overviewPhotoChecked.pxHeight()), App::sprite(), st::overviewPhotoChecked);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p.setFont(st::noContactsFont->f);
|
||||
p.setPen(st::noContactsColor->p);
|
||||
p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang(lng_contacts_loading), style::al_center);
|
||||
}
|
||||
}
|
||||
|
||||
void BackgroundInner::mouseMoveEvent(QMouseEvent *e) {
|
||||
int x = e->pos().x(), y = e->pos().y();
|
||||
int row = int((y - st::backgroundPadding) / (st::backgroundSize.height() + st::backgroundPadding));
|
||||
if (y - row * (st::backgroundSize.height() + st::backgroundPadding) > st::backgroundPadding + st::backgroundSize.height()) row = _rows + 1;
|
||||
|
||||
int col = int((x - st::backgroundPadding) / (st::backgroundSize.width() + st::backgroundPadding));
|
||||
if (x - col * (st::backgroundSize.width() + st::backgroundPadding) > st::backgroundPadding + st::backgroundSize.width()) row = _rows + 1;
|
||||
|
||||
int newOver = row * BackgroundsInRow + col;
|
||||
if (newOver >= _bgCount) newOver = -1;
|
||||
if (newOver != _over) {
|
||||
_over = newOver;
|
||||
setCursor((_over >= 0 || _overDown >= 0) ? style::cur_pointer : style::cur_default);
|
||||
}
|
||||
}
|
||||
|
||||
void BackgroundInner::mousePressEvent(QMouseEvent *e) {
|
||||
_overDown = _over;
|
||||
}
|
||||
|
||||
void BackgroundInner::mouseReleaseEvent(QMouseEvent *e) {
|
||||
if (_overDown == _over && _over >= 0) {
|
||||
emit backgroundChosen(_over);
|
||||
} else if (_over < 0) {
|
||||
setCursor(style::cur_default);
|
||||
}
|
||||
}
|
||||
|
||||
BackgroundInner::~BackgroundInner() {
|
||||
}
|
||||
|
||||
void BackgroundInner::resizeEvent(QResizeEvent *e) {
|
||||
}
|
||||
|
||||
BackgroundBox::BackgroundBox() : _scroll(this, st::backgroundScroll), _inner(),
|
||||
_close(this, lang(lng_contacts_done), st::contactsClose),
|
||||
_hiding(false), a_opacity(0, 1) {
|
||||
|
||||
_width = st::participantWidth;
|
||||
_height = App::wnd()->height() - st::boxPadding.top() - st::boxPadding.bottom();
|
||||
|
||||
resize(_width, _height);
|
||||
resizeEvent(0);
|
||||
|
||||
_scroll.setWidget(&_inner);
|
||||
_scroll.setFocusPolicy(Qt::NoFocus);
|
||||
|
||||
connect(&_close, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||
connect(&_inner, SIGNAL(backgroundChosen(int)), this, SLOT(onBackgroundChosen(int)));
|
||||
|
||||
showAll();
|
||||
_cache = myGrab(this, rect());
|
||||
hideAll();
|
||||
}
|
||||
|
||||
void BackgroundBox::hideAll() {
|
||||
_scroll.hide();
|
||||
_close.hide();
|
||||
}
|
||||
|
||||
void BackgroundBox::showAll() {
|
||||
_scroll.show();
|
||||
_close.show();
|
||||
_close.raise();
|
||||
}
|
||||
|
||||
void BackgroundBox::keyPressEvent(QKeyEvent *e) {
|
||||
if (e->key() == Qt::Key_Escape) {
|
||||
onClose();
|
||||
} else {
|
||||
e->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
void BackgroundBox::parentResized() {
|
||||
QSize s = parentWidget()->size();
|
||||
_height = App::wnd()->height() - st::boxPadding.top() - st::boxPadding.bottom();
|
||||
if (_height > st::participantMaxHeight) _height = st::participantMaxHeight;
|
||||
setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height);
|
||||
update();
|
||||
}
|
||||
|
||||
void BackgroundBox::paintEvent(QPaintEvent *e) {
|
||||
QPainter p(this);
|
||||
if (_cache.isNull()) {
|
||||
if (!_hiding || a_opacity.current() > 0.01) {
|
||||
// fill bg
|
||||
p.fillRect(QRect(QPoint(0, 0), size()), st::boxBG->b);
|
||||
|
||||
// draw box title / text
|
||||
p.setFont(st::boxFont->f);
|
||||
p.setPen(st::boxGrayTitle->p);
|
||||
p.drawText(QRect(st::addContactTitlePos.x(), st::addContactTitlePos.y(), _width - 2 * st::addContactTitlePos.x(), st::boxFont->height), lang(lng_backgrounds_header), style::al_top);
|
||||
}
|
||||
} else {
|
||||
p.setOpacity(a_opacity.current());
|
||||
p.drawPixmap(0, 0, _cache);
|
||||
}
|
||||
}
|
||||
|
||||
void BackgroundBox::resizeEvent(QResizeEvent *e) {
|
||||
LayeredWidget::resizeEvent(e);
|
||||
_inner.resize(_width, _inner.height());
|
||||
_scroll.resize(_width, _height - st::boxFont->height - st::newGroupNamePadding.top() - st::newGroupNamePadding.bottom() - _close.height());
|
||||
_scroll.move(0, st::boxFont->height + st::newGroupNamePadding.top() + st::newGroupNamePadding.bottom());
|
||||
_close.move(0, _height - _close.height());
|
||||
}
|
||||
|
||||
void BackgroundBox::animStep(float64 dt) {
|
||||
if (dt >= 1) {
|
||||
a_opacity.finish();
|
||||
_cache = QPixmap();
|
||||
if (!_hiding) {
|
||||
showAll();
|
||||
}
|
||||
} else {
|
||||
a_opacity.update(dt, anim::linear);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
void BackgroundBox::startHide() {
|
||||
_hiding = true;
|
||||
if (_cache.isNull()) {
|
||||
_cache = myGrab(this, rect());
|
||||
hideAll();
|
||||
}
|
||||
a_opacity.start(0);
|
||||
}
|
||||
|
||||
void BackgroundBox::onBackgroundChosen(int index) {
|
||||
if (index >= 0 && index < App::cServerBackgrounds().size()) {
|
||||
const App::WallPaper &paper(App::cServerBackgrounds().at(index));
|
||||
if (App::main()) App::main()->setChatBackground(paper);
|
||||
if (App::settings()) App::settings()->needBackgroundUpdate(!paper.id);
|
||||
}
|
||||
emit closed();
|
||||
}
|
||||
|
||||
void BackgroundBox::onClose() {
|
||||
emit closed();
|
||||
}
|
||||
|
||||
BackgroundBox::~BackgroundBox() {
|
||||
|
||||
}
|
84
Telegram/SourceFiles/boxes/backgroundbox.h
Normal file
84
Telegram/SourceFiles/boxes/backgroundbox.h
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "layerwidget.h"
|
||||
|
||||
class BackgroundInner : public QWidget, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
BackgroundInner();
|
||||
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void mouseMoveEvent(QMouseEvent *e);
|
||||
void mousePressEvent(QMouseEvent *e);
|
||||
void mouseReleaseEvent(QMouseEvent *e);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
|
||||
~BackgroundInner();
|
||||
|
||||
signals:
|
||||
|
||||
void backgroundChosen(int index);
|
||||
|
||||
private:
|
||||
|
||||
void gotWallpapers(const MTPVector<MTPWallPaper> &result);
|
||||
void updateWallpapers();
|
||||
|
||||
int32 _bgCount, _rows;
|
||||
int32 _over, _overDown;
|
||||
|
||||
};
|
||||
|
||||
class BackgroundBox : public LayeredWidget, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
BackgroundBox();
|
||||
void parentResized();
|
||||
void animStep(float64 dt);
|
||||
void keyPressEvent(QKeyEvent *e);
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
void startHide();
|
||||
~BackgroundBox();
|
||||
|
||||
public slots:
|
||||
|
||||
void onBackgroundChosen(int index);
|
||||
void onClose();
|
||||
|
||||
private:
|
||||
|
||||
void hideAll();
|
||||
void showAll();
|
||||
|
||||
ScrollArea _scroll;
|
||||
BackgroundInner _inner;
|
||||
int32 _width, _height;
|
||||
BottomButton _close;
|
||||
bool _hiding;
|
||||
|
||||
QPixmap _cache;
|
||||
|
||||
anim::fvalue a_opacity;
|
||||
};
|
@ -116,6 +116,9 @@ enum {
|
||||
HiddenIsOnlineAfterMessage = 30, // user with hidden last seen stays online for such amount of seconds in the interface
|
||||
|
||||
ServiceUserId = 777000,
|
||||
|
||||
CacheBackgroundTimeout = 3000, // cache background scaled image after 3s
|
||||
BackgroundsInRow = 3,
|
||||
};
|
||||
|
||||
inline bool isServiceUser(uint64 id) {
|
||||
|
@ -105,8 +105,8 @@ void ScrollBar::updateBar() {
|
||||
|
||||
void ScrollBar::onHideTimer() {
|
||||
_hideIn = -1;
|
||||
a_bg.start(st::transparent->c);
|
||||
a_bar.start(st::transparent->c);
|
||||
a_bg.start(QColor(a_bg.current().red(), a_bg.current().green(), a_bg.current().blue(), 0));
|
||||
a_bar.start(QColor(a_bar.current().red(), a_bar.current().green(), a_bar.current().blue(), 0));
|
||||
anim::start(this);
|
||||
}
|
||||
|
||||
@ -603,3 +603,12 @@ void ScrollArea::setWidget(QWidget *w) {
|
||||
|
||||
void ScrollArea::rangeChanged(int oldMax, int newMax, bool vertical) {
|
||||
}
|
||||
|
||||
void ScrollArea::updateColors(const style::color &bar, const style::color &bg, const style::color &barOver, const style::color &bgOver) {
|
||||
_st.barColor = bar;
|
||||
_st.bgColor = bg;
|
||||
_st.barOverColor = barOver;
|
||||
_st.bgOverColor = bgOver;
|
||||
hor.update();
|
||||
vert.update();
|
||||
}
|
||||
|
@ -128,6 +128,8 @@ public:
|
||||
|
||||
void rangeChanged(int oldMax, int newMax, bool vertical);
|
||||
|
||||
void updateColors(const style::color &bar, const style::color &bg, const style::color &barOver, const style::color &bgOver);
|
||||
|
||||
public slots:
|
||||
|
||||
void scrollToY(int toTop, int toBottom = -1);
|
||||
|
@ -2661,7 +2661,8 @@ QString Text::original(uint16 selectedFrom, uint16 selectedTo, bool expandLinks)
|
||||
if (url.isEmpty() || !expandLinks || lnkFrom != rangeFrom || blockFrom != rangeTo) {
|
||||
result += r;
|
||||
} else {
|
||||
if (r.size() > 3 && _text.midRef(lnkFrom, r.size() - 3) == url.midRef(0, r.size() - 3)) { // same link
|
||||
QUrl u(url);
|
||||
if (r.size() > 3 && _text.midRef(lnkFrom, r.size() - 3) == (u.isValid() ? u.toDisplayString() : url).midRef(0, r.size() - 3)) { // same link
|
||||
result += url;
|
||||
} else {
|
||||
result.append(r).append(qsl(" ( ")).append(url).append(qsl(" )"));
|
||||
|
@ -4649,9 +4649,9 @@ void HistoryServiceMsg::draw(QPainter &p, uint32 selection) const {
|
||||
}
|
||||
// QRect r(0, st::msgServiceMargin.top(), _history->width, height);
|
||||
QRect r(left, st::msgServiceMargin.top(), width, height);
|
||||
p.setBrush(st::msgServiceBG->b);
|
||||
p.setBrush(App::msgServiceBG()->b);
|
||||
p.setPen(Qt::NoPen);
|
||||
// p.fillRect(r, st::msgServiceBG->b);
|
||||
// p.fillRect(r, App::msgServiceBG()->b);
|
||||
p.drawRoundedRect(r, st::msgServiceRadius, st::msgServiceRadius);
|
||||
if (selection == FullItemSel) {
|
||||
p.setBrush(st::msgServiceSelectBG->b);
|
||||
|
@ -94,7 +94,7 @@ void HistoryList::paintEvent(QPaintEvent *e) {
|
||||
|
||||
if (hist->isEmpty()) {
|
||||
QPoint dogPos((width() - st::msgDogImg.pxWidth()) / 2, ((height() - st::msgDogImg.pxHeight()) * 4) / 9);
|
||||
p.drawPixmap(dogPos, App::sprite(), st::msgDogImg);
|
||||
p.drawPixmap(dogPos, *cChatDogImage());
|
||||
} else {
|
||||
adjustCurrent(r.top());
|
||||
HistoryBlock *block = (*hist)[currentBlock];
|
||||
@ -1567,7 +1567,6 @@ HistoryWidget::HistoryWidget(QWidget *parent) : QWidget(parent)
|
||||
, confirmImageId(0)
|
||||
, confirmWithText(false)
|
||||
, titlePeerTextWidth(0)
|
||||
, bg(st::msgBG)
|
||||
, hiderOffered(false)
|
||||
, _scrollDelta(0)
|
||||
, _typingRequest(0)
|
||||
@ -3267,6 +3266,10 @@ void HistoryWidget::itemResized(HistoryItem *row) {
|
||||
updateListSize(0, false, false, row);
|
||||
}
|
||||
|
||||
void HistoryWidget::updateScrollColors() {
|
||||
_scroll.updateColors(App::historyScrollBarColor(), App::historyScrollBgColor(), App::historyScrollBarOverColor(), App::historyScrollBgOverColor());
|
||||
}
|
||||
|
||||
void HistoryWidget::updateListSize(int32 addToY, bool initial, bool loadedDown, HistoryItem *resizedItem) {
|
||||
if (!hist || (!_histInited && !initial)) return;
|
||||
|
||||
@ -3629,17 +3632,36 @@ void HistoryWidget::paintEvent(QPaintEvent *e) {
|
||||
p.drawPixmap(a_coord.current(), 0, _animCache);
|
||||
return;
|
||||
}
|
||||
if (cCatsAndDogs()) {
|
||||
int32 i_from = r.left() / bg.width(), i_to = (r.left() + r.width() - 1) / bg.width() + 1;
|
||||
int32 j_from = r.top() / bg.height(), j_to = (r.top() + r.height() - 1) / bg.height() + 1;
|
||||
for (int32 i = i_from; i < i_to; ++i) {
|
||||
for (int32 j = j_from; j < j_to; ++j) {
|
||||
p.drawPixmap(i * bg.width(), j * bg.height(), bg);
|
||||
}
|
||||
|
||||
bool hasTopBar = !App::main()->topBar()->isHidden();
|
||||
if (cTileBackground()) {
|
||||
int left = r.left(), top = r.top(), right = r.left() + r.width(), bottom = r.top() + r.height();
|
||||
if (right > 0 && bottom > 0) {
|
||||
QRect fill(left, top + (hasTopBar ? st::topBarHeight : 0), right, bottom + (hasTopBar ? st::topBarHeight : 0));
|
||||
|
||||
if (hasTopBar) p.translate(0, -st::topBarHeight);
|
||||
p.fillRect(fill, QBrush(*cChatBackground()));
|
||||
if (hasTopBar) p.translate(0, st::topBarHeight);
|
||||
}
|
||||
} else {
|
||||
p.fillRect(r, st::historyBG->b);
|
||||
QRect fill(0, 0, width(), App::main()->height());
|
||||
int fromy = hasTopBar ? (-st::topBarHeight) : 0, x = 0, y = 0;
|
||||
QPixmap cached = App::main()->cachedBackground(fill, x, y);
|
||||
if (cached.isNull()) {
|
||||
bool smooth = p.renderHints().testFlag(QPainter::SmoothPixmapTransform);
|
||||
p.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
|
||||
QRect to, from;
|
||||
App::main()->backgroundParams(fill, to, from);
|
||||
to.moveTop(to.top() + fromy);
|
||||
p.drawPixmap(to, *cChatBackground(), from);
|
||||
|
||||
if (!smooth) p.setRenderHint(QPainter::SmoothPixmapTransform, false);
|
||||
} else {
|
||||
p.drawPixmap(x, fromy + y, cached);
|
||||
}
|
||||
}
|
||||
|
||||
if (_list) {
|
||||
if (!_scroll.isHidden()) {
|
||||
if (!_field.isHidden()) {
|
||||
@ -3647,15 +3669,14 @@ void HistoryWidget::paintEvent(QPaintEvent *e) {
|
||||
}
|
||||
} else {
|
||||
QPoint dogPos((width() - st::msgDogImg.pxWidth()) / 2, ((height() - _field.height() - 2 * st::sendPadding - st::msgDogImg.pxHeight()) * 4) / 9);
|
||||
p.drawPixmap(dogPos, App::sprite(), st::msgDogImg);
|
||||
p.drawPixmap(dogPos, *cChatDogImage());
|
||||
|
||||
int32 pointsCount = 8, w = pointsCount * (st::introPointWidth + 2 * st::introPointDelta), h = st::introPointHeight;
|
||||
int32 pointsLeft = (width() - w) / 2 + st::introPointDelta - st::introPointLeft, pointsTop = dogPos.y() + (st::msgDogImg.pxHeight() * 6) / 5;
|
||||
|
||||
int32 curPoint = histRequestsCount % pointsCount;
|
||||
|
||||
p.setOpacity(st::introPointHoverAlpha);
|
||||
p.fillRect(pointsLeft + curPoint * (st::introPointWidth + 2 * st::introPointDelta), pointsTop, st::introPointHoverWidth, st::introPointHoverHeight, st::introPointHoverColor->b);
|
||||
p.fillRect(pointsLeft + curPoint * (st::introPointWidth + 2 * st::introPointDelta), pointsTop, st::introPointHoverWidth, st::introPointHoverHeight, App::introPointHoverColor()->b);
|
||||
|
||||
// points
|
||||
p.setOpacity(st::introPointAlpha);
|
||||
@ -3670,7 +3691,7 @@ void HistoryWidget::paintEvent(QPaintEvent *e) {
|
||||
int32 w = font->m.width(lang(lng_willbe_history)) + st::msgPadding.left() + st::msgPadding.right(), h = font->height + st::msgServicePadding.top() + st::msgServicePadding.bottom() + 2;
|
||||
QRect tr((width() - w) / 2, (height() - _field.height() - 2 * st::sendPadding - h) / 2, w, h);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(st::msgServiceBG->b);
|
||||
p.setBrush(App::msgServiceBG()->b);
|
||||
p.drawRoundedRect(tr, st::msgServiceRadius, st::msgServiceRadius);
|
||||
|
||||
p.setPen(st::msgServiceColor->p);
|
||||
|
@ -341,6 +341,8 @@ public:
|
||||
void itemReplaced(HistoryItem *oldItem, HistoryItem *newItem);
|
||||
void itemResized(HistoryItem *item);
|
||||
|
||||
void updateScrollColors();
|
||||
|
||||
~HistoryWidget();
|
||||
|
||||
signals:
|
||||
@ -471,8 +473,6 @@ private:
|
||||
QString titlePeerText;
|
||||
int32 titlePeerTextWidth;
|
||||
|
||||
QPixmap bg;
|
||||
|
||||
bool hiderOffered;
|
||||
|
||||
QPixmap _animCache, _bgAnimCache, _animTopBarCache, _bgAnimTopBarCache;
|
||||
|
@ -442,6 +442,7 @@ namespace {
|
||||
lskStickers, // data: StorageKey location
|
||||
lskAudios, // data: StorageKey location
|
||||
lskRecentStickers, // no data
|
||||
lskBackground, // no data
|
||||
};
|
||||
|
||||
typedef QMap<PeerId, FileKey> DraftsMap;
|
||||
@ -457,6 +458,9 @@ namespace {
|
||||
FileKey _locationsKey = 0;
|
||||
|
||||
FileKey _recentStickersKey = 0;
|
||||
|
||||
FileKey _backgroundKey = 0;
|
||||
bool _backgroundWasRead = false;
|
||||
|
||||
typedef QPair<FileKey, qint32> FileDesc; // file, size
|
||||
typedef QMap<StorageKey, FileDesc> StorageMap;
|
||||
@ -584,7 +588,7 @@ namespace {
|
||||
DraftsNotReadMap draftsNotReadMap;
|
||||
StorageMap imagesMap, stickersMap, audiosMap;
|
||||
qint64 storageImagesSize = 0, storageStickersSize = 0, storageAudiosSize = 0;
|
||||
quint64 locationsKey = 0, recentStickersKey = 0;
|
||||
quint64 locationsKey = 0, recentStickersKey = 0, backgroundKey = 0;
|
||||
while (!map.stream.atEnd()) {
|
||||
quint32 keyType;
|
||||
map.stream >> keyType;
|
||||
@ -652,6 +656,9 @@ namespace {
|
||||
case lskRecentStickers: {
|
||||
map.stream >> recentStickersKey;
|
||||
} break;
|
||||
case lskBackground: {
|
||||
map.stream >> backgroundKey;
|
||||
} break;
|
||||
default:
|
||||
LOG(("App Error: unknown key type in encrypted map: %1").arg(keyType));
|
||||
return Local::ReadMapFailed;
|
||||
@ -675,6 +682,7 @@ namespace {
|
||||
|
||||
_locationsKey = locationsKey;
|
||||
_recentStickersKey = recentStickersKey;
|
||||
_backgroundKey = backgroundKey;
|
||||
_oldMapVersion = mapData.version;
|
||||
if (_oldMapVersion < AppVersion) {
|
||||
_mapChanged = true;
|
||||
@ -732,6 +740,7 @@ namespace {
|
||||
if (!_audiosMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _audiosMap.size() * (sizeof(quint64) * 3 + sizeof(qint32));
|
||||
if (_locationsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_recentStickersKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_backgroundKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
EncryptedDescriptor mapData(mapSize);
|
||||
if (!_draftsMap.isEmpty()) {
|
||||
mapData.stream << quint32(lskDraft) << quint32(_draftsMap.size());
|
||||
@ -769,6 +778,9 @@ namespace {
|
||||
if (_recentStickersKey) {
|
||||
mapData.stream << quint32(lskRecentStickers) << quint64(_recentStickersKey);
|
||||
}
|
||||
if (_backgroundKey) {
|
||||
mapData.stream << quint32(lskBackground) << quint64(_backgroundKey);
|
||||
}
|
||||
map.writeEncrypted(mapData);
|
||||
|
||||
map.finish();
|
||||
@ -1282,6 +1294,53 @@ namespace Local {
|
||||
cSetRecentStickers(recent);
|
||||
}
|
||||
|
||||
void writeBackground(int32 id, const QImage &img) {
|
||||
if (!_working()) return;
|
||||
|
||||
QByteArray png;
|
||||
{
|
||||
QBuffer buf(&png);
|
||||
if (!img.save(&buf, "BMP")) return;
|
||||
}
|
||||
if (!_backgroundKey) {
|
||||
_backgroundKey = genKey();
|
||||
_mapChanged = true;
|
||||
_writeMap(WriteMapFast);
|
||||
}
|
||||
quint32 size = sizeof(qint32) + sizeof(quint32) + sizeof(quint32) + png.size();
|
||||
EncryptedDescriptor data(size);
|
||||
data.stream << qint32(id) << png;
|
||||
|
||||
FileWriteDescriptor file(_backgroundKey);
|
||||
file.writeEncrypted(data);
|
||||
}
|
||||
|
||||
bool readBackground() {
|
||||
if (_backgroundWasRead) return false;
|
||||
_backgroundWasRead = true;
|
||||
|
||||
FileReadDescriptor bg;
|
||||
if (!readEncryptedFile(bg, toFilePart(_backgroundKey))) {
|
||||
clearKey(_backgroundKey);
|
||||
_backgroundKey = 0;
|
||||
_writeMap();
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray pngData;
|
||||
qint32 id;
|
||||
bg.stream >> id >> pngData;
|
||||
|
||||
QImage img;
|
||||
QBuffer buf(&pngData);
|
||||
QImageReader reader(&buf);
|
||||
if (reader.read(&img)) {
|
||||
App::initBackground(id, img, true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
struct ClearManagerData {
|
||||
QThread *thread;
|
||||
StorageMap images, stickers, audios;
|
||||
|
@ -121,4 +121,7 @@ namespace Local {
|
||||
void writeRecentStickers();
|
||||
void readRecentStickers();
|
||||
|
||||
void writeBackground(int32 id, const QImage &img);
|
||||
bool readBackground();
|
||||
|
||||
};
|
||||
|
@ -351,9 +351,11 @@ MainWidget *TopBarWidget::main() {
|
||||
MainWidget::MainWidget(Window *window) : QWidget(window), _started(0), failedObjId(0), _dialogsWidth(st::dlgMinWidth),
|
||||
dialogs(this), history(this), profile(0), overview(0), _topBar(this), _forwardConfirm(0), hider(0), _mediaType(this), _mediaTypeMask(0),
|
||||
updPts(0), updDate(0), updQts(-1), updSeq(0), updInited(false), _onlineRequest(0), _lastWasOnline(false), _lastSetOnline(0), _isIdle(false),
|
||||
_failDifferenceTimeout(1), _lastUpdateTime(0) {
|
||||
_failDifferenceTimeout(1), _lastUpdateTime(0), _cachedX(0), _cachedY(0), _background(0) {
|
||||
setGeometry(QRect(0, st::titleHeight, App::wnd()->width(), App::wnd()->height() - st::titleHeight));
|
||||
|
||||
App::initBackground();
|
||||
|
||||
connect(window, SIGNAL(resized(const QSize &)), this, SLOT(onParentResize(const QSize &)));
|
||||
connect(&dialogs, SIGNAL(cancelled()), this, SLOT(dialogsCancelled()));
|
||||
connect(&history, SIGNAL(cancelled()), &dialogs, SLOT(activate()));
|
||||
@ -374,6 +376,8 @@ _failDifferenceTimeout(1), _lastUpdateTime(0) {
|
||||
connect(audioVoice(), SIGNAL(stopped(AudioData*)), this, SLOT(audioPlayProgress(AudioData*)));
|
||||
}
|
||||
|
||||
connect(&_cacheBackgroundTimer, SIGNAL(timeout()), this, SLOT(onCacheBackground()));
|
||||
|
||||
dialogs.show();
|
||||
if (cWideMode()) {
|
||||
history.show();
|
||||
@ -712,6 +716,16 @@ void MainWidget::onCancelResend() {
|
||||
}
|
||||
}
|
||||
|
||||
void MainWidget::onCacheBackground() {
|
||||
const QPixmap &bg(*cChatBackground());
|
||||
QRect to, from;
|
||||
backgroundParams(_willCacheFor, to, from);
|
||||
_cachedX = to.x();
|
||||
_cachedY = to.y();
|
||||
_cachedBackground = QPixmap::fromImage(bg.toImage().copy(from).scaled(to.width(), to.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
_cachedFor = _willCacheFor;
|
||||
}
|
||||
|
||||
void MainWidget::forwardSelectedItems() {
|
||||
if (overview) {
|
||||
overview->onForwardSelected();
|
||||
@ -1279,6 +1293,83 @@ bool MainWidget::isIdle() const {
|
||||
return _isIdle;
|
||||
}
|
||||
|
||||
void MainWidget::clearCachedBackground() {
|
||||
_cachedBackground = QPixmap();
|
||||
_cacheBackgroundTimer.stop();
|
||||
}
|
||||
|
||||
QPixmap MainWidget::cachedBackground(const QRect &forRect, int &x, int &y) {
|
||||
if (!_cachedBackground.isNull() && forRect == _cachedFor) {
|
||||
x = _cachedX;
|
||||
y = _cachedY;
|
||||
return _cachedBackground;
|
||||
}
|
||||
if (_willCacheFor != forRect || !_cacheBackgroundTimer.isActive()) {
|
||||
_willCacheFor = forRect;
|
||||
_cacheBackgroundTimer.start(CacheBackgroundTimeout);
|
||||
}
|
||||
return QPixmap();
|
||||
}
|
||||
|
||||
void MainWidget::backgroundParams(const QRect &forRect, QRect &to, QRect &from) const {
|
||||
const QSize &bg(cChatBackground()->size());
|
||||
if (uint64(bg.width()) * forRect.height() > uint64(bg.height()) * forRect.width()) {
|
||||
float64 pxsize = forRect.height() / float64(bg.height());
|
||||
int takewidth = qCeil(forRect.width() / pxsize);
|
||||
if (takewidth > bg.width()) {
|
||||
takewidth = bg.width();
|
||||
} else if ((bg.width() % 2) != (takewidth % 2)) {
|
||||
++takewidth;
|
||||
}
|
||||
to = QRect(int((forRect.width() - takewidth * pxsize) / 2.), 0, qCeil(takewidth * pxsize), forRect.height());
|
||||
from = QRect((bg.width() - takewidth) / 2, 0, takewidth, bg.height());
|
||||
} else {
|
||||
float64 pxsize = forRect.width() / float64(bg.width());
|
||||
int takeheight = qCeil(forRect.height() / pxsize);
|
||||
if (takeheight > bg.height()) {
|
||||
takeheight = bg.height();
|
||||
} else if ((bg.height() % 2) != (takeheight % 2)) {
|
||||
++takeheight;
|
||||
}
|
||||
to = QRect(0, int((forRect.height() - takeheight * pxsize) / 2.), forRect.width(), qCeil(takeheight * pxsize));
|
||||
from = QRect(0, (bg.height() - takeheight) / 2, bg.width(), takeheight);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWidget::updateScrollColors() {
|
||||
history.updateScrollColors();
|
||||
if (overview) overview->updateScrollColors();
|
||||
}
|
||||
|
||||
void MainWidget::setChatBackground(const App::WallPaper &wp) {
|
||||
_background = new App::WallPaper(wp);
|
||||
_background->full->load();
|
||||
checkChatBackground();
|
||||
}
|
||||
|
||||
bool MainWidget::chatBackgroundLoading() {
|
||||
return !!_background;
|
||||
}
|
||||
|
||||
void MainWidget::checkChatBackground() {
|
||||
if (_background) {
|
||||
if (_background->full->loaded()) {
|
||||
if (_background->full->isNull()) {
|
||||
App::initBackground();
|
||||
} else {
|
||||
App::initBackground(_background->id, _background->full->pix().toImage());
|
||||
}
|
||||
delete _background;
|
||||
_background = 0;
|
||||
QTimer::singleShot(0, this, SLOT(update()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImagePtr MainWidget::newBackgroundThumb() {
|
||||
return _background ? _background->thumb : ImagePtr();
|
||||
}
|
||||
|
||||
void MainWidget::setInnerFocus() {
|
||||
if (hider || !history.peer()) {
|
||||
if (hider && hider->wasOffered()) {
|
||||
@ -1794,6 +1885,8 @@ bool MainWidget::animStep(float64 ms) {
|
||||
}
|
||||
|
||||
void MainWidget::paintEvent(QPaintEvent *e) {
|
||||
if (_background) checkChatBackground();
|
||||
|
||||
QPainter p(this);
|
||||
if (animating()) {
|
||||
p.setOpacity(a_bgAlpha.current());
|
||||
@ -2438,6 +2531,8 @@ int32 MainWidget::dlgsWidth() const {
|
||||
MainWidget::~MainWidget() {
|
||||
if (App::main() == this) history.showPeer(0, 0, true);
|
||||
|
||||
delete _background;
|
||||
|
||||
delete hider;
|
||||
MTP::clearGlobalHandlers();
|
||||
App::deinitMedia(false);
|
||||
|
@ -315,6 +315,16 @@ public:
|
||||
bool serviceHistoryFail(const RPCError &error);
|
||||
|
||||
bool isIdle() const;
|
||||
|
||||
void clearCachedBackground();
|
||||
QPixmap cachedBackground(const QRect &forRect, int &x, int &y);
|
||||
void backgroundParams(const QRect &forRect, QRect &to, QRect &from) const;
|
||||
void updateScrollColors();
|
||||
|
||||
void setChatBackground(const App::WallPaper &wp);
|
||||
bool chatBackgroundLoading();
|
||||
void checkChatBackground();
|
||||
ImagePtr newBackgroundThumb();
|
||||
|
||||
~MainWidget();
|
||||
|
||||
@ -368,6 +378,8 @@ public slots:
|
||||
void onResendAsDocument();
|
||||
void onCancelResend();
|
||||
|
||||
void onCacheBackground();
|
||||
|
||||
private:
|
||||
|
||||
void partWasRead(PeerData *peer, const MTPmessages_AffectedHistory &result);
|
||||
@ -453,4 +465,12 @@ private:
|
||||
SingleTimer _failDifferenceTimer;
|
||||
|
||||
uint64 _lastUpdateTime;
|
||||
|
||||
QPixmap _cachedBackground;
|
||||
QRect _cachedFor, _willCacheFor;
|
||||
int _cachedX, _cachedY;
|
||||
SingleTimer _cacheBackgroundTimer;
|
||||
|
||||
App::WallPaper *_background;
|
||||
|
||||
};
|
||||
|
@ -576,7 +576,7 @@ void OverviewInner::paintEvent(QPaintEvent *e) {
|
||||
|
||||
if (_hist->_overview[_type].isEmpty()) {
|
||||
QPoint dogPos((_width - st::msgDogImg.pxWidth()) / 2, ((height() - st::msgDogImg.pxHeight()) * 4) / 9);
|
||||
p.drawPixmap(dogPos, App::sprite(), st::msgDogImg);
|
||||
p.drawPixmap(dogPos, *cChatDogImage());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -721,7 +721,7 @@ void OverviewInner::paintEvent(QPaintEvent *e) {
|
||||
width = strwidth;
|
||||
|
||||
QRect r(left, st::msgServiceMargin.top(), width, height);
|
||||
p.setBrush(st::msgServiceBG->b);
|
||||
p.setBrush(App::msgServiceBG()->b);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.drawRoundedRect(r, st::msgServiceRadius, st::msgServiceRadius);
|
||||
|
||||
@ -1533,10 +1533,9 @@ OverviewInner::~OverviewInner() {
|
||||
}
|
||||
|
||||
OverviewWidget::OverviewWidget(QWidget *parent, const PeerData *peer, MediaOverviewType type) : QWidget(parent)
|
||||
, _scroll(this, st::setScroll, false)
|
||||
, _scroll(this, st::historyScroll, false)
|
||||
, _inner(this, &_scroll, peer, type)
|
||||
, _noDropResizeIndex(false)
|
||||
, _bg(st::msgBG)
|
||||
, _showing(false)
|
||||
, _scrollSetAfterShow(0)
|
||||
, _scrollDelta(0)
|
||||
@ -1591,19 +1590,36 @@ void OverviewWidget::paintEvent(QPaintEvent *e) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool hasTopBar = !App::main()->topBar()->isHidden();
|
||||
QRect r(e->rect());
|
||||
if (type() == OverviewPhotos) {
|
||||
p.fillRect(r, st::white->b);
|
||||
} else if (cCatsAndDogs()) {
|
||||
int32 i_from = r.left() / _bg.width(), i_to = (r.left() + r.width() - 1) / _bg.width() + 1;
|
||||
int32 j_from = r.top() / _bg.height(), j_to = (r.top() + r.height() - 1) / _bg.height() + 1;
|
||||
for (int32 i = i_from; i < i_to; ++i) {
|
||||
for (int32 j = j_from; j < j_to; ++j) {
|
||||
p.drawPixmap(i * _bg.width(), j * _bg.height(), _bg);
|
||||
}
|
||||
} else if (cTileBackground()) {
|
||||
int left = r.left(), top = r.top(), right = r.left() + r.width(), bottom = r.top() + r.height();
|
||||
if (right > 0 && bottom > 0) {
|
||||
QRect fill(left, top + (hasTopBar ? st::topBarHeight : 0), right, bottom + (hasTopBar ? st::topBarHeight : 0));
|
||||
|
||||
if (hasTopBar) p.translate(0, -st::topBarHeight);
|
||||
p.fillRect(fill, QBrush(*cChatBackground()));
|
||||
if (hasTopBar) p.translate(0, st::topBarHeight);
|
||||
}
|
||||
} else {
|
||||
p.fillRect(r, st::historyBG->b);
|
||||
QRect fill(0, 0, width(), App::main()->height());
|
||||
int fromy = hasTopBar ? (-st::topBarHeight) : 0, x = 0, y = 0;
|
||||
QPixmap cached = App::main()->cachedBackground(fill, x, y);
|
||||
if (cached.isNull()) {
|
||||
bool smooth = p.renderHints().testFlag(QPainter::SmoothPixmapTransform);
|
||||
p.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
|
||||
QRect to, from;
|
||||
App::main()->backgroundParams(fill, to, from);
|
||||
to.moveTop(to.top() + fromy);
|
||||
p.drawPixmap(to, *cChatBackground(), from);
|
||||
|
||||
if (!smooth) p.setRenderHint(QPainter::SmoothPixmapTransform, false);
|
||||
} else {
|
||||
p.drawPixmap(x, fromy + y, cached);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1772,6 +1788,10 @@ void OverviewWidget::fillSelectedItems(SelectedItemSet &sel, bool forDelete) {
|
||||
_inner.fillSelectedItems(sel, forDelete);
|
||||
}
|
||||
|
||||
void OverviewWidget::updateScrollColors() {
|
||||
_scroll.updateColors(App::historyScrollBarColor(), App::historyScrollBgColor(), App::historyScrollBarOverColor(), App::historyScrollBgOverColor());
|
||||
}
|
||||
|
||||
OverviewWidget::~OverviewWidget() {
|
||||
onClearSelected();
|
||||
updateTopBarSelection();
|
||||
|
@ -225,6 +225,8 @@ public:
|
||||
|
||||
void fillSelectedItems(SelectedItemSet &sel, bool forDelete);
|
||||
|
||||
void updateScrollColors();
|
||||
|
||||
~OverviewWidget();
|
||||
|
||||
public slots:
|
||||
@ -246,8 +248,6 @@ private:
|
||||
OverviewInner _inner;
|
||||
bool _noDropResizeIndex;
|
||||
|
||||
QPixmap _bg;
|
||||
|
||||
QString _header;
|
||||
|
||||
bool _showing;
|
||||
|
@ -65,7 +65,12 @@ QString gDownloadPath;
|
||||
bool gNeedConfigResave = false;
|
||||
|
||||
bool gCtrlEnter = false;
|
||||
bool gCatsAndDogs = true;
|
||||
|
||||
QPixmapPointer gChatBackground = 0;
|
||||
int32 gChatBackgroundId = 0;
|
||||
QPixmapPointer gChatDogImage = 0;
|
||||
bool gTileBackground = true;
|
||||
QColor gBackgroundColor = QColor(0, 0, 0);
|
||||
|
||||
uint32 gConnectionsInSession = 1;
|
||||
QString gLoggedPhoneNumber;
|
||||
|
@ -63,7 +63,14 @@ inline const QString &cDialogHelperPathFinal() {
|
||||
return cDialogHelperPath().isEmpty() ? cExeDir() : cDialogHelperPath();
|
||||
}
|
||||
DeclareSetting(bool, CtrlEnter);
|
||||
DeclareSetting(bool, CatsAndDogs);
|
||||
|
||||
typedef QPixmap *QPixmapPointer;
|
||||
DeclareSetting(QPixmapPointer, ChatBackground);
|
||||
DeclareSetting(int32, ChatBackgroundId);
|
||||
DeclareSetting(QPixmapPointer, ChatDogImage);
|
||||
DeclareSetting(bool, TileBackground);
|
||||
DeclareSetting(QColor, BackgroundColor);
|
||||
|
||||
DeclareSetting(bool, SoundNotify);
|
||||
DeclareSetting(bool, NeedConfigResave);
|
||||
DeclareSetting(bool, DesktopNotify);
|
||||
|
@ -24,6 +24,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
||||
#include "application.h"
|
||||
#include "boxes/photocropbox.h"
|
||||
#include "boxes/connectionbox.h"
|
||||
#include "boxes/backgroundbox.h"
|
||||
#include "boxes/addcontactbox.h"
|
||||
#include "boxes/emojibox.h"
|
||||
#include "boxes/confirmbox.h"
|
||||
@ -158,7 +159,11 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent),
|
||||
_tempDirClearedWidth(st::linkFont->m.width(lang(lng_download_path_cleared))),
|
||||
_tempDirClearFailedWidth(st::linkFont->m.width(lang(lng_download_path_clear_failed))),
|
||||
|
||||
_catsAndDogs(this, lang(lng_settings_cats_and_dogs), cCatsAndDogs()),
|
||||
// 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)),
|
||||
@ -248,7 +253,12 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent),
|
||||
connect(App::wnd(), SIGNAL(tempDirCleared(int)), this, SLOT(onTempDirCleared(int)));
|
||||
connect(App::wnd(), SIGNAL(tempDirClearFailed(int)), this, SLOT(onTempDirClearFailed(int)));
|
||||
|
||||
connect(&_catsAndDogs, SIGNAL(changed()), this, SLOT(onCatsAndDogs()));
|
||||
// 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()));
|
||||
@ -309,6 +319,18 @@ void SettingsInner::peerUpdated(PeerData *data) {
|
||||
}
|
||||
|
||||
void SettingsInner::paintEvent(QPaintEvent *e) {
|
||||
bool animateBackground = false;
|
||||
if (App::main() && App::main()->chatBackgroundLoading()) {
|
||||
App::main()->checkChatBackground();
|
||||
if (App::main()->chatBackgroundLoading()) {
|
||||
animateBackground = true;
|
||||
} else {
|
||||
updateChatBackground();
|
||||
}
|
||||
} else if (_needBackgroundUpdate) {
|
||||
updateChatBackground();
|
||||
}
|
||||
|
||||
QPainter p(this);
|
||||
|
||||
p.setClipRect(e->rect());
|
||||
@ -477,7 +499,44 @@ void SettingsInner::paintEvent(QPaintEvent *e) {
|
||||
}
|
||||
top += st::setSectionSkip;
|
||||
|
||||
top += _catsAndDogs.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);
|
||||
@ -607,7 +666,15 @@ void SettingsInner::resizeEvent(QResizeEvent *e) {
|
||||
top += _downloadPathEdit.height();
|
||||
}
|
||||
top += st::setSectionSkip;
|
||||
_catsAndDogs.move(_left, top); top += _catsAndDogs.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);
|
||||
@ -717,6 +784,10 @@ void SettingsInner::updateConnectionType() {
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsInner::updateBackgroundRect() {
|
||||
update(_left, _tileBackground.y() - st::setLittleSkip - st::setBackgroundSize, st::setBackgroundSize, st::setBackgroundSize);
|
||||
}
|
||||
|
||||
void SettingsInner::gotFullSelf(const MTPUserFull &selfFull) {
|
||||
if (!self()) return;
|
||||
App::feedPhoto(selfFull.c_userFull().vprofile_photo);
|
||||
@ -820,7 +891,6 @@ void SettingsInner::showAll() {
|
||||
}
|
||||
_enterSend.show();
|
||||
_ctrlEnterSend.show();
|
||||
_catsAndDogs.show();
|
||||
_dontAskDownloadPath.show();
|
||||
if (cAskDownloadPath()) {
|
||||
_downloadPathEdit.hide();
|
||||
@ -839,12 +909,22 @@ void SettingsInner::showAll() {
|
||||
_viewEmojis.hide();
|
||||
_enterSend.hide();
|
||||
_ctrlEnterSend.hide();
|
||||
_catsAndDogs.hide();
|
||||
_dontAskDownloadPath.hide();
|
||||
_downloadPathEdit.hide();
|
||||
_downloadPathClear.hide();
|
||||
}
|
||||
|
||||
// chat background
|
||||
if (self()) {
|
||||
_backFromGallery.show();
|
||||
_backFromFile.show();
|
||||
_tileBackground.show();
|
||||
} else {
|
||||
_backFromGallery.hide();
|
||||
_backFromFile.hide();
|
||||
_tileBackground.hide();
|
||||
}
|
||||
|
||||
// local storage
|
||||
if (self() && _storageClearState == TempDirExists) {
|
||||
_localStorageClear.show();
|
||||
@ -1195,9 +1275,67 @@ void SettingsInner::onCtrlEnterSend() {
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsInner::onCatsAndDogs() {
|
||||
cSetCatsAndDogs(_catsAndDogs.checked());
|
||||
App::writeUserConfig();
|
||||
void SettingsInner::onBackFromGallery() {
|
||||
BackgroundBox *box = new BackgroundBox();
|
||||
App::wnd()->showLayer(box);
|
||||
}
|
||||
|
||||
void SettingsInner::onBackFromFile() {
|
||||
QStringList imgExtensions(cImgExtensions());
|
||||
QString filter(qsl("Image files (*") + imgExtensions.join(qsl(" *")) + qsl(");;All files (*.*)"));
|
||||
|
||||
QImage img;
|
||||
QString file;
|
||||
QByteArray remoteContent;
|
||||
if (filedialogGetOpenFile(file, remoteContent, lang(lng_choose_images), filter)) {
|
||||
if (!remoteContent.isEmpty()) {
|
||||
img = App::readImage(remoteContent);
|
||||
} else {
|
||||
if (!file.isEmpty()) {
|
||||
img = App::readImage(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (img.isNull() || img.width() <= 0 || img.height() <= 0) return;
|
||||
|
||||
if (img.width() > 4096 * img.height()) {
|
||||
img = img.copy((img.width() - 4096 * img.height()) / 2, 0, 4096 * img.height(), img.height());
|
||||
} else if (img.height() > 4096 * img.width()) {
|
||||
img = img.copy(0, (img.height() - 4096 * img.width()) / 2, img.width(), 4096 * img.width());
|
||||
}
|
||||
|
||||
App::initBackground(-1, img);
|
||||
_tileBackground.setChecked(false);
|
||||
updateChatBackground();
|
||||
}
|
||||
|
||||
void SettingsInner::updateChatBackground() {
|
||||
QImage back(st::setBackgroundSize, st::setBackgroundSize, QImage::Format_ARGB32_Premultiplied);
|
||||
{
|
||||
QPainter p(&back);
|
||||
const QPixmap &pix(*cChatBackground());
|
||||
int sx = (pix.width() > pix.height()) ? ((pix.width() - pix.height()) / 2) : 0;
|
||||
int sy = (pix.height() > pix.width()) ? ((pix.height() - pix.width()) / 2) : 0;
|
||||
int s = (pix.width() > pix.height()) ? pix.height() : pix.width();
|
||||
p.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
p.drawPixmap(0, 0, st::setBackgroundSize, st::setBackgroundSize, pix, sx, sy, s, s);
|
||||
}
|
||||
_background = QPixmap::fromImage(back);
|
||||
_needBackgroundUpdate = false;
|
||||
}
|
||||
|
||||
void SettingsInner::needBackgroundUpdate(bool tile) {
|
||||
_needBackgroundUpdate = true;
|
||||
_tileBackground.setChecked(tile);
|
||||
updateChatBackground();
|
||||
}
|
||||
|
||||
void SettingsInner::onTileBackground() {
|
||||
if (cTileBackground() != _tileBackground.checked()) {
|
||||
cSetTileBackground(_tileBackground.checked());
|
||||
App::writeUserConfig();
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsInner::onDontAskDownloadPath() {
|
||||
@ -1470,6 +1608,14 @@ void SettingsWidget::usernameChanged() {
|
||||
_inner.usernameChanged();
|
||||
}
|
||||
|
||||
void SettingsWidget::setInnerFocus() {
|
||||
_inner.setFocus();
|
||||
}
|
||||
|
||||
void SettingsWidget::needBackgroundUpdate(bool tile) {
|
||||
_inner.needBackgroundUpdate(tile);
|
||||
}
|
||||
|
||||
SettingsWidget::~SettingsWidget() {
|
||||
if (App::wnd()) App::wnd()->noSettings(this);
|
||||
}
|
||||
|
@ -78,11 +78,16 @@ public:
|
||||
|
||||
void showAll();
|
||||
|
||||
void updateChatBackground();
|
||||
void needBackgroundUpdate(bool tile);
|
||||
|
||||
public slots:
|
||||
|
||||
void usernameChanged();
|
||||
void updateConnectionType();
|
||||
|
||||
void updateBackgroundRect();
|
||||
|
||||
void peerUpdated(PeerData *data);
|
||||
|
||||
void onUpdatePhoto();
|
||||
@ -125,7 +130,9 @@ public slots:
|
||||
void onTempDirCleared(int task);
|
||||
void onTempDirClearFailed(int task);
|
||||
|
||||
void onCatsAndDogs();
|
||||
void onBackFromGallery();
|
||||
void onBackFromFile();
|
||||
void onTileBackground();
|
||||
|
||||
void onLocalStorageClear();
|
||||
|
||||
@ -222,7 +229,12 @@ private:
|
||||
TempDirCleared = 4,
|
||||
};
|
||||
TempDirClearState _tempDirClearState;
|
||||
FlatCheckbox _catsAndDogs;
|
||||
|
||||
// chat background
|
||||
QPixmap _background;
|
||||
LinkButton _backFromGallery, _backFromFile;
|
||||
FlatCheckbox _tileBackground;
|
||||
bool _needBackgroundUpdate;
|
||||
|
||||
// local storage
|
||||
LinkButton _localStorageClear;
|
||||
@ -267,6 +279,9 @@ public:
|
||||
void rpcInvalidate();
|
||||
void usernameChanged();
|
||||
|
||||
void setInnerFocus();
|
||||
void needBackgroundUpdate(bool tile);
|
||||
|
||||
~SettingsWidget();
|
||||
|
||||
public slots:
|
||||
|
@ -256,6 +256,7 @@ enum DataBlockId {
|
||||
dbiCompressPastedImage = 30,
|
||||
dbiLang = 31,
|
||||
dbiLangFile = 32,
|
||||
dbiTileBackground = 33,
|
||||
|
||||
dbiEncryptedWithSalt = 333,
|
||||
dbiEncrypted = 444,
|
||||
|
@ -740,7 +740,11 @@ void Window::layerHidden() {
|
||||
}
|
||||
layerBG = 0;
|
||||
if (_mediaView && !_mediaView->isHidden()) _mediaView->hide();
|
||||
if (main) main->setInnerFocus();
|
||||
if (settings) {
|
||||
settings->setInnerFocus();
|
||||
} else if (main) {
|
||||
main->setInnerFocus();
|
||||
}
|
||||
}
|
||||
|
||||
QRect Window::clientRect() const {
|
||||
|
@ -170,6 +170,10 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GeneratedFiles\Debug\moc_backgroundbox.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GeneratedFiles\Debug\moc_button.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
@ -394,6 +398,10 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GeneratedFiles\Deploy\moc_backgroundbox.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GeneratedFiles\Deploy\moc_button.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
@ -627,6 +635,10 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GeneratedFiles\Release\moc_backgroundbox.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GeneratedFiles\Release\moc_button.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
@ -834,6 +846,7 @@
|
||||
<ClCompile Include="SourceFiles\boxes\aboutbox.cpp" />
|
||||
<ClCompile Include="SourceFiles\boxes\addcontactbox.cpp" />
|
||||
<ClCompile Include="SourceFiles\boxes\addparticipantbox.cpp" />
|
||||
<ClCompile Include="SourceFiles\boxes\backgroundbox.cpp" />
|
||||
<ClCompile Include="SourceFiles\boxes\confirmbox.cpp" />
|
||||
<ClCompile Include="SourceFiles\boxes\connectionbox.cpp" />
|
||||
<ClCompile Include="SourceFiles\boxes\contactsbox.cpp" />
|
||||
@ -1164,6 +1177,20 @@
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/boxes/languagebox.h" -DAL_LIBTYPE_STATIC -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.3.1\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.3.1\QtGui"</Command>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="SourceFiles\boxes\backgroundbox.h">
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">Moc%27ing backgroundbox.h...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/boxes/backgroundbox.h" -DAL_LIBTYPE_STATIC -DCUSTOM_API_ID -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.3.1\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.3.1\QtGui"</Command>
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Moc%27ing backgroundbox.h...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/boxes/backgroundbox.h" -DAL_LIBTYPE_STATIC -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.3.1\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.3.1\QtGui"</Command>
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Moc%27ing backgroundbox.h...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/boxes/backgroundbox.h" -DAL_LIBTYPE_STATIC -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.3.1\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.3.1\QtGui"</Command>
|
||||
</CustomBuild>
|
||||
<ClInclude Include="SourceFiles\config.h" />
|
||||
<CustomBuild Include="SourceFiles\gui\animation.h">
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Moc%27ing animation.h...</Message>
|
||||
|
@ -777,6 +777,18 @@
|
||||
<ClCompile Include="GeneratedFiles\Release\moc_languagebox.cpp">
|
||||
<Filter>Generated Files\Release</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SourceFiles\boxes\backgroundbox.cpp">
|
||||
<Filter>boxes</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GeneratedFiles\Deploy\moc_backgroundbox.cpp">
|
||||
<Filter>Generated Files\Deploy</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GeneratedFiles\Debug\moc_backgroundbox.cpp">
|
||||
<Filter>Generated Files\Debug</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GeneratedFiles\Release\moc_backgroundbox.cpp">
|
||||
<Filter>Generated Files\Release</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="SourceFiles\stdafx.h">
|
||||
@ -1037,6 +1049,9 @@
|
||||
<CustomBuild Include="SourceFiles\boxes\languagebox.h">
|
||||
<Filter>boxes</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="SourceFiles\boxes\backgroundbox.h">
|
||||
<Filter>boxes</Filter>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="SourceFiles\art\icon256.ico" />
|
||||
|
Loading…
Reference in New Issue
Block a user