/* 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 */ #pragma once class Image; namespace Data { struct WallPaper { WallPaperId id = WallPaperId(); uint64 accessHash = 0; MTPDwallPaper::Flags flags; QString slug; Image *thumb = nullptr; DocumentData *document = nullptr; }; } // namespace Data namespace Window { namespace Theme { namespace details { 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 kLegacyBackgroundId = int32(-111); } // namespace details constexpr auto kThemeBackground = details::FromLegacyBackgroundId(-2); constexpr auto kCustomBackground = details::FromLegacyBackgroundId(-1); constexpr auto kInitialBackground = details::FromLegacyBackgroundId(0); constexpr auto kDefaultBackground = details::FromLegacyBackgroundId(105); constexpr auto kMinimumTiledSize = 512; struct Cached { QByteArray colors; QByteArray background; bool tiled = false; int32 paletteChecksum = 0; int32 contentChecksum = 0; }; struct Saved { QString pathRelative; QString pathAbsolute; QByteArray content; Cached cache; }; bool Load(Saved &&saved); void Unload(); struct Instance { style::palette palette; QImage background; Cached cached; bool tiled = false; }; struct Preview { QString pathRelative; QString pathAbsolute; Instance instance; QByteArray content; QImage preview; }; bool Apply(const QString &filepath); bool Apply(std::unique_ptr preview); void ApplyDefaultWithPath(const QString &themePath); bool ApplyEditedPalette(const QString &path, const QByteArray &content); void KeepApplied(); QString NightThemePath(); [[nodiscard]] bool IsNightMode(); void SetNightModeValue(bool nightMode); void ToggleNightMode(); void ToggleNightMode(const QString &themePath); [[nodiscard]] bool IsNonDefaultBackground(); void Revert(); bool LoadFromFile(const QString &file, Instance *out, QByteArray *outContent); bool IsPaletteTestingPath(const QString &path); [[nodiscard]] std::optional GetWallPaperColor(const QString &slug); struct BackgroundUpdate { enum class Type { New, Changed, Start, TestingTheme, RevertingTheme, ApplyingTheme, }; BackgroundUpdate(Type type, bool tiled) : type(type), tiled(tiled) { } bool paletteChanged() const { return (type == Type::TestingTheme || type == Type::RevertingTheme); } Type type; bool tiled; }; class ChatBackground : public base::Observable { public: ChatBackground(); // This method is allowed to (and should) be called before start(). void setThemeData(QImage &&themeImage, bool themeTile); // This method is setting the default (themed) image if none was set yet. void start(); void setImage(const Data::WallPaper &paper, QImage &&image = QImage()); void setTile(bool tile); void setTileDayValue(bool tile); void setTileNightValue(bool tile); void setThemeAbsolutePath(const QString &path); [[nodiscard]] QString themeAbsolutePath() const; void reset(); void setTestingTheme(Instance &&theme); void saveAdjustableColors(); void setTestingDefaultTheme(); void revert(); [[nodiscard]] WallPaperId id() const; [[nodiscard]] const QPixmap &pixmap() const { return _pixmap; } [[nodiscard]] const QPixmap &pixmapForTiled() const { return _pixmapForTiled; } [[nodiscard]] std::optional color() const { return _paperColor; } [[nodiscard]] QImage createCurrentImage() const; [[nodiscard]] bool tile() const; [[nodiscard]] bool tileDay() const; [[nodiscard]] bool tileNight() const; private: struct AdjustableColor { AdjustableColor(style::color data); style::color item; QColor original; }; void ensureStarted(); void saveForRevert(); void setPreparedImage(QImage &&image); void writeNewBackgroundSettings(); void setPaper(const Data::WallPaper &paper); [[nodiscard]] bool adjustPaletteRequired(); void adjustPaletteUsingBackground(const QImage &img); void adjustPaletteUsingColor(QColor color); void restoreAdjustableColors(); void setNightModeValue(bool nightMode); [[nodiscard]] bool nightMode() const; void toggleNightMode(std::optional themePath); void keepApplied(const QString &path, bool write); [[nodiscard]] bool isNonDefaultThemeOrBackground(); [[nodiscard]] bool isNonDefaultBackground(); friend bool IsNightMode(); friend void SetNightModeValue(bool nightMode); friend void ToggleNightMode(); friend void ToggleNightMode(const QString &themePath); friend void KeepApplied(); friend bool IsNonDefaultBackground(); Data::WallPaper _paper = { details::kUninitializedBackground }; std::optional _paperColor; QPixmap _pixmap; QPixmap _pixmapForTiled; bool _nightMode = false; bool _tileDayValue = false; bool _tileNightValue = true; QString _themeAbsolutePath; QImage _themeImage; bool _themeTile = false; Data::WallPaper _paperForRevert = { details::kUninitializedBackground }; QImage _imageForRevert; bool _tileForRevert = false; std::vector _adjustableColors; }; ChatBackground *Background(); void ComputeBackgroundRects(QRect wholeFill, QSize imageSize, QRect &to, QRect &from); bool CopyColorsToPalette(const QString &path, const QByteArray &themeContent); bool ReadPaletteValues(const QByteArray &content, Fn callback); } // namespace Theme } // namespace Window