From cedb2d31afd40ae7206b285d5694d6edb37c36aa Mon Sep 17 00:00:00 2001 From: John Preston Date: Sun, 8 Sep 2019 16:40:15 +0300 Subject: [PATCH] Check palette changes on editor cancel. --- .../window/themes/window_theme.cpp | 1 - .../SourceFiles/window/themes/window_theme.h | 1 + .../window/themes/window_theme_editor.cpp | 33 ++-- .../window/themes/window_theme_editor.h | 1 + .../window/themes/window_theme_editor_box.cpp | 163 +++++++++++++----- .../window/themes/window_theme_editor_box.h | 4 + 6 files changed, 151 insertions(+), 52 deletions(-) diff --git a/Telegram/SourceFiles/window/themes/window_theme.cpp b/Telegram/SourceFiles/window/themes/window_theme.cpp index 42e8477e0..c9aaf4c0d 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme.cpp @@ -34,7 +34,6 @@ namespace Theme { namespace { constexpr auto kThemeFileSizeLimit = 5 * 1024 * 1024; -constexpr auto kThemeBackgroundSizeLimit = 4 * 1024 * 1024; constexpr auto kBackgroundSizeLimit = 25 * 1024 * 1024; constexpr auto kNightThemeFile = str_const(":/gui/night.tdesktop-theme"); constexpr auto kMinimumTiledSize = 512; diff --git a/Telegram/SourceFiles/window/themes/window_theme.h b/Telegram/SourceFiles/window/themes/window_theme.h index e139a1ed4..693bd79a9 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.h +++ b/Telegram/SourceFiles/window/themes/window_theme.h @@ -18,6 +18,7 @@ namespace Window { namespace Theme { inline constexpr auto kThemeSchemeSizeLimit = 1024 * 1024; +inline constexpr auto kThemeBackgroundSizeLimit = 4 * 1024 * 1024; [[nodiscard]] bool IsEmbeddedTheme(const QString &path); diff --git a/Telegram/SourceFiles/window/themes/window_theme_editor.cpp b/Telegram/SourceFiles/window/themes/window_theme_editor.cpp index 0ce2018ab..711269516 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_editor.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme_editor.cpp @@ -665,18 +665,7 @@ Editor::Editor( _scroll->scrollToY(top, bottom); }); _close->setClickedCallback([=] { - const auto box = std::make_shared>(); - const auto close = crl::guard(this, [=] { - Background()->clearEditingTheme(ClearEditing::RevertChanges); - closeEditor(); - if (*box) { - (*box)->closeBox(); - } - }); - *box = _window->show(Box( - tr::lng_theme_editor_sure_close(tr::now), - tr::lng_close(tr::now), - close)); + closeWithConfirmation(); }); _close->show(anim::type::instant); @@ -791,6 +780,26 @@ void Editor::paintEvent(QPaintEvent *e) { // } //} +void Editor::closeWithConfirmation() { + if (!PaletteChanged(_inner->paletteContent(), _cloud)) { + Background()->clearEditingTheme(ClearEditing::KeepChanges); + closeEditor(); + return; + } + const auto box = std::make_shared>(); + const auto close = crl::guard(this, [=] { + Background()->clearEditingTheme(ClearEditing::RevertChanges); + closeEditor(); + if (*box) { + (*box)->closeBox(); + } + }); + *box = _window->show(Box( + tr::lng_theme_editor_sure_close(tr::now), + tr::lng_close(tr::now), + close)); +} + void Editor::closeEditor() { if (const auto window = App::wnd()) { window->showRightColumn(nullptr); diff --git a/Telegram/SourceFiles/window/themes/window_theme_editor.h b/Telegram/SourceFiles/window/themes/window_theme_editor.h index db8e94530..aed50cd28 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_editor.h +++ b/Telegram/SourceFiles/window/themes/window_theme_editor.h @@ -49,6 +49,7 @@ protected: private: void save(); void closeEditor(); + void closeWithConfirmation(); const not_null _window; const Data::CloudTheme _cloud; diff --git a/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp b/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp index 022f26303..135b8a171 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp @@ -56,12 +56,29 @@ enum class SaveErrorType { Link, }; +struct ParsedTheme { + QByteArray palette; + QByteArray background; + bool isPng = false; + bool tiled = false; +}; + struct PreparedBackground { QByteArray content; bool tile = false; bool isPng = false; + bool changed = false; }; +template +QByteArray qba(const char(&string)[Size]) { + return QByteArray::fromRawData(string, Size - 1); +} + +QByteArray qba(QLatin1String string) { + return QByteArray::fromRawData(string.data(), string.size()); +} + class BackgroundSelector : public Ui::RpWidget { public: BackgroundSelector( @@ -86,6 +103,7 @@ private: QImage _background; QByteArray _backgroundContent; bool _isPng = false; + bool _changed = false; QString _imageText; int _thumbnailSize = 0; QPixmap _thumbnail; @@ -185,6 +203,7 @@ void BackgroundSelector::chooseBackgroundFromFile() { _background = image; _backgroundContent = content; _isPng = (format == "png"); + _changed = true; const auto phrase = _isPng ? tr::lng_theme_editor_read_from_png : tr::lng_theme_editor_read_from_jpg; @@ -209,6 +228,7 @@ PreparedBackground BackgroundSelector::result() const { _backgroundContent, _tileBackground->checked(), _isPng, + _changed, }; } @@ -239,27 +259,69 @@ void ImportFromFile( return QString::fromUtf8(string.data(), string.size()); } -[[nodiscard]] bool CopyColorsToPalette( - const QString &destination, - const QString &themePath, +[[nodiscard]] ParsedTheme ParseTheme( const QByteArray &themeContent, - const Data::CloudTheme &cloud) { - auto paletteContent = themeContent; + bool onlyPalette) { + auto result = ParsedTheme(); + result.palette = themeContent; zlib::FileToRead file(themeContent); unz_global_info globalInfo = { 0 }; file.getGlobalInfo(&globalInfo); - if (file.error() == UNZ_OK) { - paletteContent = file.readFileContent("colors.tdesktop-theme", zlib::kCaseInsensitive, kThemeSchemeSizeLimit); - if (file.error() == UNZ_END_OF_LIST_OF_FILE) { + if (file.error() != UNZ_OK) { + return result; + } + result.palette = file.readFileContent("colors.tdesktop-theme", zlib::kCaseInsensitive, kThemeSchemeSizeLimit); + if (file.error() == UNZ_END_OF_LIST_OF_FILE) { + file.clearError(); + result.palette = file.readFileContent("colors.tdesktop-palette", zlib::kCaseInsensitive, kThemeSchemeSizeLimit); + } + if (file.error() != UNZ_OK) { + LOG(("Theme Error: could not read 'colors.tdesktop-theme' or 'colors.tdesktop-palette' in the theme file.")); + return ParsedTheme(); + } else if (onlyPalette) { + return result; + } + + const auto fromFile = [&](const char *filename) { + result.background = file.readFileContent(filename, zlib::kCaseInsensitive, kThemeBackgroundSizeLimit); + if (file.error() == UNZ_OK) { + return true; + } else if (file.error() == UNZ_END_OF_LIST_OF_FILE) { file.clearError(); - paletteContent = file.readFileContent("colors.tdesktop-palette", zlib::kCaseInsensitive, kThemeSchemeSizeLimit); - } - if (file.error() != UNZ_OK) { - LOG(("Theme Error: could not read 'colors.tdesktop-theme' or 'colors.tdesktop-palette' in the theme file, while copying to '%1'.").arg(destination)); - return false; + return true; } + LOG(("Theme Error: could not read '%1' in the theme file.").arg(filename)); + return false; + }; + + if (!fromFile("background.jpg") || !result.background.isEmpty()) { + return result.background.isEmpty() ? ParsedTheme() : result; + } + result.isPng = true; + if (!fromFile("background.png") || !result.background.isEmpty()) { + return result.background.isEmpty() ? ParsedTheme() : result; + } + result.tiled = true; + if (!fromFile("tiled.png") || !result.background.isEmpty()) { + return result.background.isEmpty() ? ParsedTheme() : result; + } + result.isPng = false; + if (!fromFile("background.jpg") || !result.background.isEmpty()) { + return result.background.isEmpty() ? ParsedTheme() : result; + } + return result; +} + +[[nodiscard]] bool CopyColorsToPalette( + const QString &destination, + const QString &themePath, + const QByteArray &themeContent, + const Data::CloudTheme &cloud) { + auto parsed = ParseTheme(themeContent, true); + if (parsed.palette.isEmpty()) { + return false; } QFile f(destination); @@ -269,18 +331,40 @@ void ImportFromFile( } if (const auto colorizer = ColorizerForTheme(themePath)) { - paletteContent = Editor::ColorizeInContent( - std::move(paletteContent), + parsed.palette = Editor::ColorizeInContent( + std::move(parsed.palette), colorizer); } - paletteContent = WriteCloudToText(cloud) + paletteContent; - if (f.write(paletteContent) != paletteContent.size()) { + const auto content = WriteCloudToText(cloud) + parsed.palette; + if (f.write(content) != content.size()) { LOG(("Theme Error: could not write palette to '%1'").arg(destination)); return false; } return true; } +QByteArray GenerateDefaultPalette() { + auto result = QByteArray(); + const auto rows = style::main_palette::data(); + for (const auto &row : std::as_const(rows)) { + result.append(qba(row.name) + ).append(": " + ).append(qba(row.value) + ).append("; // " + ).append( + qba( + row.description + ).replace( + '\n', + ' ' + ).replace( + '\r', + ' ') + ).append('\n'); + } + return result; +} + bool WriteDefaultPalette( const QString &path, const Data::CloudTheme &cloud) { @@ -290,27 +374,10 @@ bool WriteDefaultPalette( return false; } - QTextStream stream(&f); - stream.setCodec("UTF-8"); - - stream << QString::fromLatin1(WriteCloudToText(cloud)); - - auto rows = style::main_palette::data(); - for (const auto &row : std::as_const(rows)) { - stream - << BytesToUTF8(row.name) - << ": " - << BytesToUTF8(row.value) - << "; // " - << BytesToUTF8( - row.description - ).replace( - '\n', - ' ' - ).replace( - '\r', - ' ') - << "\n"; + const auto content = WriteCloudToText(cloud) + GenerateDefaultPalette(); + if (f.write(content) != content.size()) { + LOG(("Theme Error: could not write palette to '%1'").arg(path)); + return false; } return true; } @@ -623,7 +690,11 @@ void StartEditor( auto object = Local::ReadThemeContent(); const auto written = object.content.isEmpty() ? WriteDefaultPalette(path, cloud) - : CopyColorsToPalette(path, object.pathAbsolute, object.content, cloud); + : CopyColorsToPalette( + path, + object.pathAbsolute, + object.content, + cloud); if (!written) { window->show(Box(tr::lng_theme_editor_error(tr::now))); return; @@ -730,7 +801,11 @@ void SaveThemeBox( const QByteArray &palette) { Expects(window->account().sessionExists()); + //Local::ReadThemeContent() const auto background = Background()->createCurrentImage(); + //if (Data::IsThemeWallPaper(Background()->paper())) { + + //} auto backgroundContent = QByteArray(); const auto tiled = Background()->tile(); { @@ -854,5 +929,15 @@ void SaveThemeBox( box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); } +bool PaletteChanged( + const QByteArray &editorPalette, + const Data::CloudTheme &cloud) { + auto object = Local::ReadThemeContent(); + const auto real = object.content.isEmpty() + ? GenerateDefaultPalette() + : ParseTheme(object.content, true).palette; + return (editorPalette != WriteCloudToText(cloud) + real); +} + } // namespace Theme } // namespace Window diff --git a/Telegram/SourceFiles/window/themes/window_theme_editor_box.h b/Telegram/SourceFiles/window/themes/window_theme_editor_box.h index 128082201..1a4fe76b9 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_editor_box.h +++ b/Telegram/SourceFiles/window/themes/window_theme_editor_box.h @@ -40,5 +40,9 @@ void SaveThemeBox( const Data::CloudTheme &cloud, const QByteArray &palette); +[[nodiscard]] bool PaletteChanged( + const QByteArray &editorPalette, + const Data::CloudTheme &cloud); + } // namespace Theme } // namespace Window