2019-02-08 16:20:08 +00:00
|
|
|
/*
|
|
|
|
This file is part of Telegram Desktop,
|
|
|
|
the official desktop application for the Telegram messaging service.
|
|
|
|
|
|
|
|
For license and copyright information please follow this link:
|
|
|
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|
|
|
*/
|
|
|
|
#include "data/data_wall_paper.h"
|
|
|
|
|
|
|
|
#include "data/data_document.h"
|
|
|
|
#include "data/data_file_origin.h"
|
|
|
|
#include "data/data_session.h"
|
|
|
|
#include "storage/serialize_common.h"
|
2021-08-27 11:32:18 +00:00
|
|
|
#include "ui/chat/chat_theme.h"
|
2022-10-05 07:42:44 +00:00
|
|
|
#include "ui/color_int_conversion.h"
|
2019-02-08 16:20:08 +00:00
|
|
|
#include "core/application.h"
|
2019-07-24 11:45:24 +00:00
|
|
|
#include "main/main_session.h"
|
2019-02-08 16:20:08 +00:00
|
|
|
|
2022-10-05 07:42:44 +00:00
|
|
|
namespace Ui {
|
|
|
|
|
|
|
|
QColor ColorFromSerialized(MTPint serialized) {
|
|
|
|
return ColorFromSerialized(serialized.v);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<QColor> MaybeColorFromSerialized(
|
|
|
|
const tl::conditional<MTPint> &mtp) {
|
|
|
|
return mtp ? ColorFromSerialized(*mtp) : std::optional<QColor>();
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace Ui
|
|
|
|
|
2019-02-08 16:20:08 +00:00
|
|
|
namespace Data {
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
constexpr auto FromLegacyBackgroundId(int32 legacyId) -> WallPaperId {
|
|
|
|
return uint64(0xFFFFFFFF00000000ULL) | uint64(uint32(legacyId));
|
|
|
|
}
|
|
|
|
|
|
|
|
constexpr auto kUninitializedBackground = FromLegacyBackgroundId(-999);
|
|
|
|
constexpr auto kTestingThemeBackground = FromLegacyBackgroundId(-666);
|
|
|
|
constexpr auto kTestingDefaultBackground = FromLegacyBackgroundId(-665);
|
|
|
|
constexpr auto kTestingEditorBackground = FromLegacyBackgroundId(-664);
|
|
|
|
constexpr auto kThemeBackground = FromLegacyBackgroundId(-2);
|
|
|
|
constexpr auto kCustomBackground = FromLegacyBackgroundId(-1);
|
|
|
|
constexpr auto kLegacy1DefaultBackground = FromLegacyBackgroundId(0);
|
2021-07-23 09:16:33 +00:00
|
|
|
constexpr auto kLegacy2DefaultBackground = 5947530738516623361;
|
2021-08-31 19:10:39 +00:00
|
|
|
constexpr auto kLegacy3DefaultBackground = 5778236420632084488;
|
|
|
|
constexpr auto kLegacy4DefaultBackground = 5945087215657811969;
|
|
|
|
constexpr auto kDefaultBackground = 5933856211186221059;
|
2019-02-08 16:20:08 +00:00
|
|
|
constexpr auto kIncorrectDefaultBackground = FromLegacyBackgroundId(105);
|
|
|
|
|
2021-08-12 09:32:30 +00:00
|
|
|
constexpr auto kVersionTag = qint32(0x7FFFFFFF);
|
|
|
|
constexpr auto kVersion = 1;
|
|
|
|
|
2022-10-05 07:42:44 +00:00
|
|
|
using Ui::MaybeColorFromSerialized;
|
|
|
|
|
2021-08-12 09:32:30 +00:00
|
|
|
[[nodiscard]] quint32 SerializeColor(const QColor &color) {
|
|
|
|
return (quint32(std::clamp(color.red(), 0, 255)) << 16)
|
|
|
|
| (quint32(std::clamp(color.green(), 0, 255)) << 8)
|
|
|
|
| quint32(std::clamp(color.blue(), 0, 255));
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] quint32 SerializeMaybeColor(std::optional<QColor> color) {
|
|
|
|
return color ? SerializeColor(*color) : quint32(-1);
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
|
2021-08-12 09:32:30 +00:00
|
|
|
[[nodiscard]] std::vector<QColor> ColorsFromMTP(
|
|
|
|
const MTPDwallPaperSettings &data) {
|
|
|
|
auto result = std::vector<QColor>();
|
|
|
|
const auto c1 = MaybeColorFromSerialized(data.vbackground_color());
|
|
|
|
if (!c1) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
result.reserve(4);
|
|
|
|
result.push_back(*c1);
|
2022-10-05 07:42:44 +00:00
|
|
|
const auto c2 = MaybeColorFromSerialized(
|
|
|
|
data.vsecond_background_color());
|
2021-08-12 09:32:30 +00:00
|
|
|
if (!c2) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
result.push_back(*c2);
|
|
|
|
const auto c3 = MaybeColorFromSerialized(data.vthird_background_color());
|
|
|
|
if (!c3) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
result.push_back(*c3);
|
2022-10-05 07:42:44 +00:00
|
|
|
const auto c4 = MaybeColorFromSerialized(
|
|
|
|
data.vfourth_background_color());
|
2021-08-12 09:32:30 +00:00
|
|
|
if (!c4) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
result.push_back(*c4);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] std::optional<QColor> ColorFromString(QStringView string) {
|
2019-02-08 16:20:08 +00:00
|
|
|
if (string.size() != 6) {
|
|
|
|
return {};
|
2020-05-18 19:33:14 +00:00
|
|
|
} else if (ranges::any_of(string, [](QChar ch) {
|
2019-02-08 16:20:08 +00:00
|
|
|
return (ch < 'a' || ch > 'f')
|
|
|
|
&& (ch < 'A' || ch > 'F')
|
|
|
|
&& (ch < '0' || ch > '9');
|
2020-05-18 19:33:14 +00:00
|
|
|
})) {
|
2019-02-08 16:20:08 +00:00
|
|
|
return {};
|
|
|
|
}
|
2021-08-12 09:32:30 +00:00
|
|
|
const auto component = [](QStringView text, int index) {
|
2019-02-08 16:20:08 +00:00
|
|
|
const auto decimal = [](QChar hex) {
|
|
|
|
const auto code = hex.unicode();
|
|
|
|
return (code >= '0' && code <= '9')
|
|
|
|
? int(code - '0')
|
|
|
|
: (code >= 'a' && code <= 'f')
|
|
|
|
? int(code - 'a' + 0x0a)
|
|
|
|
: int(code - 'A' + 0x0a);
|
|
|
|
};
|
|
|
|
index *= 2;
|
|
|
|
return decimal(text[index]) * 0x10 + decimal(text[index + 1]);
|
|
|
|
};
|
|
|
|
return QColor(
|
|
|
|
component(string, 0),
|
|
|
|
component(string, 1),
|
|
|
|
component(string, 2),
|
|
|
|
255);
|
|
|
|
}
|
|
|
|
|
2021-08-12 09:32:30 +00:00
|
|
|
[[nodiscard]] std::vector<QColor> ColorsFromString(const QString &string) {
|
2021-08-16 10:24:15 +00:00
|
|
|
constexpr auto kMaxColors = 4;
|
2021-08-12 09:32:30 +00:00
|
|
|
const auto view = QStringView(string);
|
|
|
|
const auto count = int(view.size() / 6);
|
|
|
|
if (!count || count > kMaxColors || view.size() != count * 7 - 1) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
auto result = std::vector<QColor>();
|
|
|
|
result.reserve(count);
|
|
|
|
for (auto i = 0; i != count; ++i) {
|
2021-08-13 15:11:28 +00:00
|
|
|
if (i + 1 < count
|
|
|
|
&& view[i * 7 + 6] != '~'
|
|
|
|
&& (count > 2 || view[i * 7 + 6] != '-')) {
|
2021-08-12 09:32:30 +00:00
|
|
|
return {};
|
|
|
|
} else if (const auto parsed = ColorFromString(view.mid(i * 7, 6))) {
|
|
|
|
result.push_back(*parsed);
|
|
|
|
} else {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] QString StringFromColor(QColor color) {
|
2019-02-08 16:20:08 +00:00
|
|
|
const auto component = [](int value) {
|
|
|
|
const auto hex = [](int value) {
|
|
|
|
value = std::clamp(value, 0, 15);
|
|
|
|
return (value > 9)
|
|
|
|
? ('a' + (value - 10))
|
|
|
|
: ('0' + value);
|
|
|
|
};
|
|
|
|
return QString() + hex(value / 16) + hex(value % 16);
|
|
|
|
};
|
|
|
|
return component(color.red())
|
|
|
|
+ component(color.green())
|
|
|
|
+ component(color.blue());
|
|
|
|
}
|
|
|
|
|
2021-08-12 09:32:30 +00:00
|
|
|
[[nodiscard]] QString StringFromColors(const std::vector<QColor> &colors) {
|
|
|
|
Expects(!colors.empty());
|
|
|
|
|
|
|
|
auto strings = QStringList();
|
|
|
|
strings.reserve(colors.size());
|
|
|
|
for (const auto &color : colors) {
|
|
|
|
strings.push_back(StringFromColor(color));
|
|
|
|
}
|
|
|
|
const auto separator = (colors.size() > 2) ? '~' : '-';
|
|
|
|
return strings.join(separator);
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] qint32 RawFromLegacyFlags(qint32 legacyFlags) {
|
|
|
|
using Flag = WallPaperFlag;
|
|
|
|
return ((legacyFlags & (1 << 0)) ? qint32(Flag::Creator) : 0)
|
|
|
|
| ((legacyFlags & (1 << 1)) ? qint32(Flag::Default) : 0)
|
|
|
|
| ((legacyFlags & (1 << 3)) ? qint32(Flag::Pattern) : 0)
|
|
|
|
| ((legacyFlags & (1 << 4)) ? qint32(Flag::Dark) : 0);
|
|
|
|
}
|
|
|
|
|
2019-02-08 16:20:08 +00:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
WallPaper::WallPaper(WallPaperId id) : _id(id) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void WallPaper::setLocalImageAsThumbnail(std::shared_ptr<Image> image) {
|
|
|
|
Expects(IsDefaultWallPaper(*this)
|
|
|
|
|| IsLegacy1DefaultWallPaper(*this)
|
|
|
|
|| IsCustomWallPaper(*this));
|
|
|
|
Expects(_thumbnail == nullptr);
|
|
|
|
|
|
|
|
_thumbnail = std::move(image);
|
|
|
|
}
|
|
|
|
|
|
|
|
WallPaperId WallPaper::id() const {
|
|
|
|
return _id;
|
|
|
|
}
|
|
|
|
|
2021-08-12 09:32:30 +00:00
|
|
|
const std::vector<QColor> WallPaper::backgroundColors() const {
|
|
|
|
return _backgroundColors;
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DocumentData *WallPaper::document() const {
|
|
|
|
return _document;
|
|
|
|
}
|
|
|
|
|
2020-04-15 14:06:34 +00:00
|
|
|
Image *WallPaper::localThumbnail() const {
|
|
|
|
return _thumbnail.get();
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool WallPaper::isPattern() const {
|
2021-08-12 09:32:30 +00:00
|
|
|
return _flags & WallPaperFlag::Pattern;
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool WallPaper::isDefault() const {
|
2021-08-12 09:32:30 +00:00
|
|
|
return _flags & WallPaperFlag::Default;
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool WallPaper::isCreator() const {
|
2021-08-12 09:32:30 +00:00
|
|
|
return _flags & WallPaperFlag::Creator;
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool WallPaper::isDark() const {
|
2021-08-12 09:32:30 +00:00
|
|
|
return _flags & WallPaperFlag::Dark;
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool WallPaper::isLocal() const {
|
2020-04-15 14:06:34 +00:00
|
|
|
return !document() && _thumbnail;
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool WallPaper::isBlurred() const {
|
2021-08-12 09:32:30 +00:00
|
|
|
return _blurred;
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int WallPaper::patternIntensity() const {
|
|
|
|
return _intensity;
|
|
|
|
}
|
|
|
|
|
2021-08-12 14:51:44 +00:00
|
|
|
float64 WallPaper::patternOpacity() const {
|
|
|
|
return _intensity / 100.;
|
|
|
|
}
|
|
|
|
|
|
|
|
int WallPaper::gradientRotation() const {
|
2021-08-16 10:24:15 +00:00
|
|
|
// In case of complex gradients rotation value is dynamic.
|
|
|
|
return (_backgroundColors.size() < 3) ? _rotation : 0;
|
2021-08-12 14:51:44 +00:00
|
|
|
}
|
|
|
|
|
2019-02-08 16:20:08 +00:00
|
|
|
bool WallPaper::hasShareUrl() const {
|
|
|
|
return !_slug.isEmpty();
|
|
|
|
}
|
|
|
|
|
2020-06-17 09:36:25 +00:00
|
|
|
QString WallPaper::shareUrl(not_null<Main::Session*> session) const {
|
2019-02-08 16:20:08 +00:00
|
|
|
if (!hasShareUrl()) {
|
|
|
|
return QString();
|
|
|
|
}
|
2020-06-17 09:36:25 +00:00
|
|
|
const auto base = session->createInternalLinkFull("bg/" + _slug);
|
2019-02-08 16:20:08 +00:00
|
|
|
auto params = QStringList();
|
|
|
|
if (isPattern()) {
|
2021-08-12 09:32:30 +00:00
|
|
|
if (!backgroundColors().empty()) {
|
|
|
|
params.push_back(
|
|
|
|
"bg_color=" + StringFromColors(backgroundColors()));
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
if (_intensity) {
|
|
|
|
params.push_back("intensity=" + QString::number(_intensity));
|
|
|
|
}
|
|
|
|
}
|
2021-08-13 15:11:28 +00:00
|
|
|
if (_rotation && backgroundColors().size() == 2) {
|
|
|
|
params.push_back("rotation=" + QString::number(_rotation));
|
|
|
|
}
|
2019-02-08 16:20:08 +00:00
|
|
|
auto mode = QStringList();
|
2021-08-12 09:32:30 +00:00
|
|
|
if (_blurred) {
|
2019-02-08 16:20:08 +00:00
|
|
|
mode.push_back("blur");
|
|
|
|
}
|
|
|
|
if (!mode.isEmpty()) {
|
|
|
|
params.push_back("mode=" + mode.join('+'));
|
|
|
|
}
|
|
|
|
return params.isEmpty()
|
|
|
|
? base
|
|
|
|
: base + '?' + params.join('&');
|
|
|
|
}
|
|
|
|
|
2020-04-15 14:06:34 +00:00
|
|
|
void WallPaper::loadDocumentThumbnail() const {
|
2019-02-08 16:20:08 +00:00
|
|
|
if (_document) {
|
|
|
|
_document->loadThumbnail(fileOrigin());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void WallPaper::loadDocument() const {
|
|
|
|
if (_document) {
|
|
|
|
_document->save(fileOrigin(), QString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FileOrigin WallPaper::fileOrigin() const {
|
2020-06-19 15:14:55 +00:00
|
|
|
return FileOriginWallpaper(_id, _accessHash, _ownerId, _slug);
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
|
2020-06-19 15:14:55 +00:00
|
|
|
UserId WallPaper::ownerId() const {
|
|
|
|
return _ownerId;
|
|
|
|
}
|
|
|
|
|
|
|
|
MTPInputWallPaper WallPaper::mtpInput(not_null<Main::Session*> session) const {
|
|
|
|
return (_ownerId && _ownerId != session->userId() && !_slug.isEmpty())
|
|
|
|
? MTP_inputWallPaperSlug(MTP_string(_slug))
|
|
|
|
: MTP_inputWallPaper(MTP_long(_id), MTP_long(_accessHash));
|
2019-02-08 16:47:02 +00:00
|
|
|
}
|
|
|
|
|
2019-02-08 16:20:08 +00:00
|
|
|
MTPWallPaperSettings WallPaper::mtpSettings() const {
|
2021-08-12 09:32:30 +00:00
|
|
|
const auto serializeForIndex = [&](int index) {
|
|
|
|
return (_backgroundColors.size() > index)
|
|
|
|
? MTP_int(SerializeColor(_backgroundColors[index]))
|
|
|
|
: MTP_int(0);
|
|
|
|
};
|
|
|
|
using Flag = MTPDwallPaperSettings::Flag;
|
|
|
|
const auto flagForIndex = [&](int index) {
|
|
|
|
return (_backgroundColors.size() <= index)
|
|
|
|
? Flag(0)
|
|
|
|
: (index == 0)
|
|
|
|
? Flag::f_background_color
|
|
|
|
: (index == 1)
|
|
|
|
? Flag::f_second_background_color
|
|
|
|
: (index == 2)
|
|
|
|
? Flag::f_third_background_color
|
|
|
|
: Flag::f_fourth_background_color;
|
|
|
|
};
|
2019-02-08 16:20:08 +00:00
|
|
|
return MTP_wallPaperSettings(
|
2021-08-12 09:32:30 +00:00
|
|
|
MTP_flags((_blurred ? Flag::f_blur : Flag(0))
|
|
|
|
| flagForIndex(0)
|
|
|
|
| flagForIndex(1)
|
|
|
|
| flagForIndex(2)
|
|
|
|
| flagForIndex(3)),
|
|
|
|
serializeForIndex(0),
|
|
|
|
serializeForIndex(1),
|
|
|
|
serializeForIndex(2),
|
|
|
|
serializeForIndex(3),
|
2019-12-29 11:41:10 +00:00
|
|
|
MTP_int(_intensity),
|
2021-08-12 09:32:30 +00:00
|
|
|
MTP_int(_rotation));
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
WallPaper WallPaper::withUrlParams(
|
|
|
|
const QMap<QString, QString> ¶ms) const {
|
|
|
|
auto result = *this;
|
2021-08-12 09:32:30 +00:00
|
|
|
result._blurred = false;
|
|
|
|
result._backgroundColors = ColorsFromString(_slug);
|
2019-02-08 16:20:08 +00:00
|
|
|
result._intensity = kDefaultIntensity;
|
|
|
|
if (auto mode = params.value("mode"); !mode.isEmpty()) {
|
|
|
|
const auto list = mode.replace('+', ' ').split(' ');
|
|
|
|
for (const auto &change : list) {
|
2022-11-26 21:20:17 +00:00
|
|
|
if (change == u"blur"_q) {
|
2021-08-12 09:32:30 +00:00
|
|
|
result._blurred = true;
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-08-12 09:32:30 +00:00
|
|
|
if (result._backgroundColors.empty()) {
|
|
|
|
result._backgroundColors = ColorsFromString(params.value("bg_color"));
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
2021-08-13 15:11:28 +00:00
|
|
|
if (result._backgroundColors.empty()) {
|
|
|
|
result._backgroundColors = ColorsFromString(params.value("gradient"));
|
|
|
|
}
|
|
|
|
if (result._backgroundColors.empty()) {
|
|
|
|
result._backgroundColors = ColorsFromString(params.value("color"));
|
|
|
|
}
|
2021-08-20 10:57:55 +00:00
|
|
|
if (result._backgroundColors.empty()) {
|
|
|
|
result._backgroundColors = ColorsFromString(params.value("slug"));
|
|
|
|
}
|
2019-02-08 16:20:08 +00:00
|
|
|
if (const auto string = params.value("intensity"); !string.isEmpty()) {
|
|
|
|
auto ok = false;
|
|
|
|
const auto intensity = string.toInt(&ok);
|
2021-08-17 14:35:10 +00:00
|
|
|
if (ok && base::in_range(intensity, -100, 101)) {
|
2019-02-08 16:20:08 +00:00
|
|
|
result._intensity = intensity;
|
|
|
|
}
|
|
|
|
}
|
2021-08-12 14:51:44 +00:00
|
|
|
result._rotation = params.value("rotation").toInt();
|
|
|
|
result._rotation = (std::clamp(result._rotation, 0, 315) / 45) * 45;
|
2019-02-08 16:20:08 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
WallPaper WallPaper::withBlurred(bool blurred) const {
|
|
|
|
auto result = *this;
|
2021-08-12 09:32:30 +00:00
|
|
|
result._blurred = blurred;
|
2019-02-08 16:20:08 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
WallPaper WallPaper::withPatternIntensity(int intensity) const {
|
|
|
|
auto result = *this;
|
|
|
|
result._intensity = intensity;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2021-08-12 09:32:30 +00:00
|
|
|
WallPaper WallPaper::withGradientRotation(int rotation) const {
|
|
|
|
auto result = *this;
|
|
|
|
result._rotation = rotation;
|
|
|
|
return result;
|
|
|
|
}
|
2019-02-08 16:20:08 +00:00
|
|
|
|
2021-08-12 09:32:30 +00:00
|
|
|
WallPaper WallPaper::withBackgroundColors(std::vector<QColor> colors) const {
|
2019-02-08 16:20:08 +00:00
|
|
|
auto result = *this;
|
2021-08-12 09:32:30 +00:00
|
|
|
result._backgroundColors = std::move(colors);
|
|
|
|
if (!ColorsFromString(_slug).empty()) {
|
|
|
|
result._slug = StringFromColors(result._backgroundColors);
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
WallPaper WallPaper::withParamsFrom(const WallPaper &other) const {
|
|
|
|
auto result = *this;
|
2021-08-12 09:32:30 +00:00
|
|
|
result._blurred = other._blurred;
|
2021-08-31 19:10:39 +00:00
|
|
|
if (!other._backgroundColors.empty()) {
|
2021-08-12 09:32:30 +00:00
|
|
|
result._backgroundColors = other._backgroundColors;
|
|
|
|
if (!ColorsFromString(_slug).empty()) {
|
|
|
|
result._slug = StringFromColors(result._backgroundColors);
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
result._intensity = other._intensity;
|
2021-08-31 19:10:39 +00:00
|
|
|
if (other.isPattern()) {
|
|
|
|
result._flags |= WallPaperFlag::Pattern;
|
|
|
|
}
|
2019-02-08 16:20:08 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
WallPaper WallPaper::withoutImageData() const {
|
|
|
|
auto result = *this;
|
|
|
|
result._thumbnail = nullptr;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-06-08 09:06:50 +00:00
|
|
|
std::optional<WallPaper> WallPaper::Create(
|
|
|
|
not_null<Main::Session*> session,
|
|
|
|
const MTPWallPaper &data) {
|
|
|
|
return data.match([&](const MTPDwallPaper &data) {
|
|
|
|
return Create(session, data);
|
2019-12-29 11:41:10 +00:00
|
|
|
}, [](const MTPDwallPaperNoFile &data) {
|
2021-08-12 09:32:30 +00:00
|
|
|
return Create(data);
|
2019-02-08 16:20:08 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-06-08 09:06:50 +00:00
|
|
|
std::optional<WallPaper> WallPaper::Create(
|
|
|
|
not_null<Main::Session*> session,
|
|
|
|
const MTPDwallPaper &data) {
|
|
|
|
const auto document = session->data().processDocument(
|
2019-07-05 13:38:38 +00:00
|
|
|
data.vdocument());
|
2019-02-08 16:20:08 +00:00
|
|
|
if (!document->checkWallPaperProperties()) {
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
2019-07-05 13:38:38 +00:00
|
|
|
auto result = WallPaper(data.vid().v);
|
|
|
|
result._accessHash = data.vaccess_hash().v;
|
2020-06-19 15:14:55 +00:00
|
|
|
result._ownerId = session->userId();
|
2021-08-12 09:32:30 +00:00
|
|
|
result._flags = (data.is_dark() ? WallPaperFlag::Dark : WallPaperFlag(0))
|
|
|
|
| (data.is_pattern() ? WallPaperFlag::Pattern : WallPaperFlag(0))
|
|
|
|
| (data.is_default() ? WallPaperFlag::Default : WallPaperFlag(0))
|
|
|
|
| (data.is_creator() ? WallPaperFlag::Creator : WallPaperFlag(0));
|
2019-07-05 13:38:38 +00:00
|
|
|
result._slug = qs(data.vslug());
|
2019-02-08 16:20:08 +00:00
|
|
|
result._document = document;
|
2019-07-05 13:38:38 +00:00
|
|
|
if (const auto settings = data.vsettings()) {
|
|
|
|
settings->match([&](const MTPDwallPaperSettings &data) {
|
2021-08-12 09:32:30 +00:00
|
|
|
result._blurred = data.is_blur();
|
|
|
|
if (result.isPattern()) {
|
|
|
|
result._backgroundColors = ColorsFromMTP(data);
|
|
|
|
if (const auto intensity = data.vintensity()) {
|
|
|
|
result._intensity = intensity->v;
|
|
|
|
}
|
|
|
|
if (const auto rotation = data.vrotation()) {
|
|
|
|
result._rotation = rotation->v;
|
|
|
|
}
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
2021-08-12 09:32:30 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<WallPaper> WallPaper::Create(const MTPDwallPaperNoFile &data) {
|
|
|
|
auto result = WallPaper(data.vid().v);
|
|
|
|
result._flags = (data.is_dark() ? WallPaperFlag::Dark : WallPaperFlag(0))
|
|
|
|
| (data.is_default() ? WallPaperFlag::Default : WallPaperFlag(0));
|
|
|
|
result._blurred = false;
|
|
|
|
result._backgroundColors.clear();
|
|
|
|
if (const auto settings = data.vsettings()) {
|
|
|
|
settings->match([&](const MTPDwallPaperSettings &data) {
|
|
|
|
result._blurred = data.is_blur();
|
|
|
|
result._backgroundColors = ColorsFromMTP(data);
|
|
|
|
if (const auto rotation = data.vrotation()) {
|
|
|
|
result._rotation = rotation->v;
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
QByteArray WallPaper::serialize() const {
|
|
|
|
auto size = sizeof(quint64) // _id
|
|
|
|
+ sizeof(quint64) // _accessHash
|
2021-08-12 09:32:30 +00:00
|
|
|
+ sizeof(qint32) // version tag
|
|
|
|
+ sizeof(qint32) // version
|
2019-02-08 16:20:08 +00:00
|
|
|
+ sizeof(qint32) // _flags
|
|
|
|
+ Serialize::stringSize(_slug)
|
|
|
|
+ sizeof(qint32) // _settings
|
2021-08-12 09:32:30 +00:00
|
|
|
+ sizeof(qint32) // _backgroundColors.size()
|
|
|
|
+ (_backgroundColors.size() * sizeof(quint32)) // _backgroundColors
|
2021-04-01 21:04:10 +00:00
|
|
|
+ sizeof(qint32) // _intensity
|
2021-08-12 09:32:30 +00:00
|
|
|
+ sizeof(qint32) // _rotation
|
|
|
|
+ sizeof(quint64); // ownerId
|
2019-02-08 16:20:08 +00:00
|
|
|
|
|
|
|
auto result = QByteArray();
|
|
|
|
result.reserve(size);
|
|
|
|
{
|
|
|
|
auto stream = QDataStream(&result, QIODevice::WriteOnly);
|
|
|
|
stream.setVersion(QDataStream::Qt_5_1);
|
|
|
|
stream
|
|
|
|
<< quint64(_id)
|
|
|
|
<< quint64(_accessHash)
|
2021-08-12 09:32:30 +00:00
|
|
|
<< qint32(kVersionTag)
|
|
|
|
<< qint32(kVersion)
|
2019-02-08 16:20:08 +00:00
|
|
|
<< qint32(_flags)
|
|
|
|
<< _slug
|
2021-08-12 09:32:30 +00:00
|
|
|
<< qint32(_blurred ? 1 : 0)
|
|
|
|
<< qint32(_backgroundColors.size());
|
|
|
|
for (const auto &color : _backgroundColors) {
|
|
|
|
stream << SerializeMaybeColor(color);
|
|
|
|
}
|
|
|
|
stream
|
2020-06-19 15:14:55 +00:00
|
|
|
<< qint32(_intensity)
|
2021-08-12 09:32:30 +00:00
|
|
|
<< qint32(_rotation)
|
|
|
|
<< quint64(_ownerId.bare);
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<WallPaper> WallPaper::FromSerialized(
|
|
|
|
const QByteArray &serialized) {
|
|
|
|
if (serialized.isEmpty()) {
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto id = quint64();
|
|
|
|
auto accessHash = quint64();
|
2021-08-12 09:32:30 +00:00
|
|
|
auto versionTag = qint32();
|
|
|
|
auto version = qint32(0);
|
2019-02-08 16:20:08 +00:00
|
|
|
|
|
|
|
auto stream = QDataStream(serialized);
|
|
|
|
stream.setVersion(QDataStream::Qt_5_1);
|
|
|
|
stream
|
|
|
|
>> id
|
|
|
|
>> accessHash
|
2021-08-12 09:32:30 +00:00
|
|
|
>> versionTag;
|
|
|
|
|
|
|
|
auto flags = qint32();
|
|
|
|
auto ownerId = UserId();
|
|
|
|
auto slug = QString();
|
|
|
|
auto blurred = qint32();
|
|
|
|
auto backgroundColors = std::vector<QColor>();
|
|
|
|
auto intensity = qint32();
|
|
|
|
auto rotation = qint32();
|
|
|
|
if (versionTag == kVersionTag) {
|
|
|
|
auto bareOwnerId = quint64();
|
|
|
|
auto backgroundColorsCount = qint32();
|
|
|
|
stream
|
|
|
|
>> version
|
|
|
|
>> flags
|
|
|
|
>> slug
|
|
|
|
>> blurred
|
|
|
|
>> backgroundColorsCount;
|
2021-08-16 10:24:15 +00:00
|
|
|
if (backgroundColorsCount < 0 || backgroundColorsCount > 4) {
|
2021-08-12 09:32:30 +00:00
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
backgroundColors.reserve(backgroundColorsCount);
|
|
|
|
for (auto i = 0; i != backgroundColorsCount; ++i) {
|
|
|
|
auto serialized = quint32();
|
|
|
|
stream >> serialized;
|
|
|
|
const auto color = MaybeColorFromSerialized(serialized);
|
|
|
|
if (!color) {
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
backgroundColors.push_back(*color);
|
|
|
|
}
|
|
|
|
stream
|
|
|
|
>> intensity
|
|
|
|
>> rotation
|
|
|
|
>> bareOwnerId;
|
|
|
|
ownerId = UserId(BareId(bareOwnerId));
|
|
|
|
} else {
|
|
|
|
auto settings = qint32();
|
|
|
|
auto backgroundColor = quint32();
|
|
|
|
stream
|
|
|
|
>> slug
|
|
|
|
>> settings
|
|
|
|
>> backgroundColor
|
|
|
|
>> intensity;
|
2021-04-01 21:04:10 +00:00
|
|
|
if (!stream.atEnd()) {
|
2021-08-12 09:32:30 +00:00
|
|
|
auto field1 = qint32();
|
|
|
|
auto field2 = qint32();
|
|
|
|
stream >> field1;
|
|
|
|
if (!stream.atEnd()) {
|
|
|
|
stream >> field2;
|
|
|
|
}
|
|
|
|
ownerId = UserId(
|
|
|
|
BareId(uint32(field1)) | (BareId(uint32(field2)) << 32));
|
|
|
|
}
|
|
|
|
flags = RawFromLegacyFlags(versionTag);
|
|
|
|
blurred = (settings & qint32(1U << 1)) ? 1 : 0;
|
|
|
|
if (const auto color = MaybeColorFromSerialized(backgroundColor)) {
|
|
|
|
backgroundColors.push_back(*color);
|
2021-04-01 21:04:10 +00:00
|
|
|
}
|
2020-06-19 15:14:55 +00:00
|
|
|
}
|
2019-02-08 16:20:08 +00:00
|
|
|
if (stream.status() != QDataStream::Ok) {
|
|
|
|
return std::nullopt;
|
2021-08-17 14:35:10 +00:00
|
|
|
} else if (intensity < -100 || intensity > 100) {
|
2019-02-08 16:20:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
auto result = WallPaper(id);
|
|
|
|
result._accessHash = accessHash;
|
2020-06-19 15:14:55 +00:00
|
|
|
result._ownerId = ownerId;
|
2021-08-12 09:32:30 +00:00
|
|
|
result._flags = WallPaperFlags::from_raw(flags);
|
2019-02-08 16:20:08 +00:00
|
|
|
result._slug = slug;
|
2021-08-12 09:32:30 +00:00
|
|
|
result._blurred = (blurred == 1);
|
|
|
|
result._backgroundColors = std::move(backgroundColors);
|
2019-02-08 16:20:08 +00:00
|
|
|
result._intensity = intensity;
|
2021-08-12 09:32:30 +00:00
|
|
|
result._rotation = rotation;
|
2019-02-08 16:20:08 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<WallPaper> WallPaper::FromLegacySerialized(
|
|
|
|
quint64 id,
|
|
|
|
quint64 accessHash,
|
|
|
|
quint32 flags,
|
|
|
|
QString slug) {
|
|
|
|
auto result = WallPaper(id);
|
|
|
|
result._accessHash = accessHash;
|
2021-08-12 09:32:30 +00:00
|
|
|
result._flags = WallPaperFlags::from_raw(RawFromLegacyFlags(flags));
|
2019-02-08 16:20:08 +00:00
|
|
|
result._slug = slug;
|
2021-08-12 09:32:30 +00:00
|
|
|
if (const auto color = ColorFromString(slug)) {
|
|
|
|
result._backgroundColors.push_back(*color);
|
|
|
|
}
|
2019-02-08 16:20:08 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<WallPaper> WallPaper::FromLegacyId(qint32 legacyId) {
|
|
|
|
auto result = WallPaper(FromLegacyBackgroundId(legacyId));
|
|
|
|
if (!IsCustomWallPaper(result)) {
|
2021-08-12 09:32:30 +00:00
|
|
|
result._flags = WallPaperFlag::Default;
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2021-08-12 09:32:30 +00:00
|
|
|
std::optional<WallPaper> WallPaper::FromColorsSlug(const QString &slug) {
|
|
|
|
auto colors = ColorsFromString(slug);
|
|
|
|
if (colors.empty()) {
|
|
|
|
return std::nullopt;
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
2021-08-12 09:32:30 +00:00
|
|
|
auto result = CustomWallPaper();
|
|
|
|
result._slug = slug;
|
|
|
|
result._backgroundColors = std::move(colors);
|
|
|
|
return result;
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
|
2021-08-31 19:10:39 +00:00
|
|
|
WallPaper WallPaper::ConstructDefault() {
|
|
|
|
auto result = WallPaper(
|
|
|
|
kDefaultBackground
|
|
|
|
).withPatternIntensity(50).withBackgroundColors({
|
|
|
|
QColor(219, 221, 187),
|
|
|
|
QColor(107, 165, 135),
|
|
|
|
QColor(213, 216, 141),
|
|
|
|
QColor(136, 184, 132),
|
|
|
|
});
|
|
|
|
result._flags |= WallPaperFlag::Default | WallPaperFlag::Pattern;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2019-02-08 16:20:08 +00:00
|
|
|
WallPaper ThemeWallPaper() {
|
|
|
|
return WallPaper(kThemeBackground);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsThemeWallPaper(const WallPaper &paper) {
|
|
|
|
return (paper.id() == kThemeBackground);
|
|
|
|
}
|
|
|
|
|
|
|
|
WallPaper CustomWallPaper() {
|
|
|
|
return WallPaper(kCustomBackground);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsCustomWallPaper(const WallPaper &paper) {
|
|
|
|
return (paper.id() == kCustomBackground);
|
|
|
|
}
|
|
|
|
|
|
|
|
WallPaper Legacy1DefaultWallPaper() {
|
|
|
|
return WallPaper(kLegacy1DefaultBackground);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsLegacy1DefaultWallPaper(const WallPaper &paper) {
|
|
|
|
return (paper.id() == kLegacy1DefaultBackground);
|
|
|
|
}
|
|
|
|
|
2021-07-23 09:16:33 +00:00
|
|
|
bool IsLegacy2DefaultWallPaper(const WallPaper &paper) {
|
|
|
|
return (paper.id() == kLegacy2DefaultBackground)
|
|
|
|
|| (paper.id() == kIncorrectDefaultBackground);
|
|
|
|
}
|
|
|
|
|
2021-08-31 19:10:39 +00:00
|
|
|
bool IsLegacy3DefaultWallPaper(const WallPaper &paper) {
|
|
|
|
return (paper.id() == kLegacy3DefaultBackground);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsLegacy4DefaultWallPaper(const WallPaper &paper) {
|
|
|
|
return (paper.id() == kLegacy4DefaultBackground);
|
|
|
|
}
|
|
|
|
|
2019-02-08 16:20:08 +00:00
|
|
|
WallPaper DefaultWallPaper() {
|
2021-08-31 19:10:39 +00:00
|
|
|
return WallPaper::ConstructDefault();
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool IsDefaultWallPaper(const WallPaper &paper) {
|
2021-07-23 09:16:33 +00:00
|
|
|
return (paper.id() == kDefaultBackground);
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
|
2019-02-08 16:47:02 +00:00
|
|
|
bool IsCloudWallPaper(const WallPaper &paper) {
|
|
|
|
return (paper.id() != kIncorrectDefaultBackground)
|
|
|
|
&& !IsThemeWallPaper(paper)
|
|
|
|
&& !IsCustomWallPaper(paper)
|
|
|
|
&& !IsLegacy1DefaultWallPaper(paper)
|
|
|
|
&& !details::IsUninitializedWallPaper(paper)
|
|
|
|
&& !details::IsTestingThemeWallPaper(paper)
|
|
|
|
&& !details::IsTestingDefaultWallPaper(paper)
|
|
|
|
&& !details::IsTestingEditorWallPaper(paper);
|
|
|
|
}
|
|
|
|
|
2021-08-12 14:51:44 +00:00
|
|
|
QImage GenerateDitheredGradient(const Data::WallPaper &paper) {
|
2021-08-27 11:32:18 +00:00
|
|
|
return Ui::GenerateDitheredGradient(
|
2021-08-12 14:51:44 +00:00
|
|
|
paper.backgroundColors(),
|
|
|
|
paper.gradientRotation());
|
|
|
|
}
|
|
|
|
|
2019-02-08 16:20:08 +00:00
|
|
|
namespace details {
|
|
|
|
|
|
|
|
WallPaper UninitializedWallPaper() {
|
|
|
|
return WallPaper(kUninitializedBackground);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsUninitializedWallPaper(const WallPaper &paper) {
|
|
|
|
return (paper.id() == kUninitializedBackground);
|
|
|
|
}
|
|
|
|
|
|
|
|
WallPaper TestingThemeWallPaper() {
|
|
|
|
return WallPaper(kTestingThemeBackground);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsTestingThemeWallPaper(const WallPaper &paper) {
|
|
|
|
return (paper.id() == kTestingThemeBackground);
|
|
|
|
}
|
|
|
|
|
|
|
|
WallPaper TestingDefaultWallPaper() {
|
2021-08-31 19:10:39 +00:00
|
|
|
return WallPaper(
|
|
|
|
kTestingDefaultBackground
|
|
|
|
).withParamsFrom(DefaultWallPaper());
|
2019-02-08 16:20:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool IsTestingDefaultWallPaper(const WallPaper &paper) {
|
|
|
|
return (paper.id() == kTestingDefaultBackground);
|
|
|
|
}
|
|
|
|
|
|
|
|
WallPaper TestingEditorWallPaper() {
|
|
|
|
return WallPaper(kTestingEditorBackground);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsTestingEditorWallPaper(const WallPaper &paper) {
|
|
|
|
return (paper.id() == kTestingEditorBackground);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace details
|
|
|
|
} // namespace Data
|