From dfd63e66ff833d21d540149eff9d1d8af69c5986 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 9 Sep 2019 23:58:41 +0300 Subject: [PATCH] Add import theme to the editor. --- Telegram/Resources/langs/lang.strings | 2 +- .../window/themes/window_theme_editor.cpp | 96 +++++++++++-- .../window/themes/window_theme_editor.h | 2 + .../window/themes/window_theme_editor_box.cpp | 135 +++++++++--------- .../window/themes/window_theme_editor_box.h | 8 ++ 5 files changed, 162 insertions(+), 81 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 1d79e1058..f8bde8210 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1616,7 +1616,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_theme_editor_need_unlock" = "You need to unlock Telegram to save your theme."; "lng_theme_editor_done" = "Theme exported successfully!"; "lng_theme_editor_title" = "Edit color palette"; -"lng_theme_editor_export_button" = "Export theme"; "lng_theme_editor_save_button" = "Save theme"; "lng_theme_editor_create_title" = "Create theme"; @@ -1630,6 +1629,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_theme_editor_link_about" = "Your theme will be updated for all users each time you change it. Anyone can install it using this link.\n\nTheme links must be longer than 5 characters and use a-z, 0-9 and underscores."; "lng_theme_editor_menu_export" = "Export theme"; +"lng_theme_editor_menu_import" = "Import theme"; "lng_theme_editor_menu_show" = "Show palette file"; "lng_payments_not_supported" = "Sorry, Telegram Desktop doesn't support payments yet. Please use one of our mobile apps to do this."; diff --git a/Telegram/SourceFiles/window/themes/window_theme_editor.cpp b/Telegram/SourceFiles/window/themes/window_theme_editor.cpp index 851d691ed..9498194de 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_editor.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme_editor.cpp @@ -220,6 +220,9 @@ public: void selectSkip(int direction); void selectSkipPage(int delta, int direction); + void applyNewPalette(const QByteArray &newContent); + void recreateRows(); + ~Inner() { if (_context.box) _context.box->closeBox(); } @@ -418,7 +421,32 @@ Editor::Inner::Inner(QWidget *parent, const QString &path) : TWidget(parent) }); } +void Editor::Inner::recreateRows() { + _existingRows.create(this, EditorBlock::Type::Existing, &_context); + _existingRows->show(); + _newRows.create(this, EditorBlock::Type::New, &_context); + _newRows->show(); + if (!readData()) { + error(); + } +} + void Editor::Inner::prepare() { + QFile f(_path); + if (!f.open(QIODevice::ReadOnly)) { + LOG(("Theme Error: could not open color palette file '%1'").arg(_path)); + error(); + return; + } + + _paletteContent = f.readAll(); + if (f.error() != QFileDevice::NoError) { + LOG(("Theme Error: could not read content from palette file '%1'").arg(_path)); + error(); + return; + } + f.close(); + if (!readData()) { error(); } @@ -551,19 +579,6 @@ void Editor::Inner::sortByAccentDistance() { } bool Editor::Inner::readExistingRows() { - QFile f(_path); - if (!f.open(QIODevice::ReadOnly)) { - LOG(("Theme Error: could not open color palette file '%1'").arg(_path)); - return false; - } - - _paletteContent = f.readAll(); - if (f.error() != QFileDevice::NoError) { - LOG(("Theme Error: could not read content from palette file '%1'").arg(_path)); - return false; - } - f.close(); - return ReadPaletteValues(_paletteContent, [this](QLatin1String name, QLatin1String value) { return feedExistingRow(name, value); }); @@ -598,6 +613,10 @@ void Editor::Inner::applyEditing(const QString &name, const QString ©Of, QCo auto addedline = (_paletteContent.endsWith('\n') ? "" : newline); newContent = _paletteContent + addedline + plainName + ": " + plainValue + ";" + newline; } + applyNewPalette(newContent); +} + +void Editor::Inner::applyNewPalette(const QByteArray &newContent) { QFile f(_path); if (!f.open(QIODevice::WriteOnly)) { LOG(("Theme Error: could not open '%1' for writing a palette update.").arg(_path)); @@ -704,6 +723,11 @@ void Editor::showMenu() { exportTheme(); }); }); + _menu->addAction(tr::lng_theme_editor_menu_import(tr::now), [=] { + App::CallDelayed(st::defaultRippleAnimation.hideDuration, this, [=] { + importTheme(); + }); + }); _menu->addAction(tr::lng_theme_editor_menu_show(tr::now), [=] { File::ShowInFolder(EditingPalettePath()); }); @@ -732,6 +756,48 @@ void Editor::exportTheme() { })); } +void Editor::importTheme() { + auto filters = QStringList( + qsl("Theme files (*.tdesktop-theme *.tdesktop-palette)")); + filters.push_back(FileDialog::AllFilesFilter()); + const auto callback = crl::guard(this, [=]( + const FileDialog::OpenResult &result) { + const auto path = result.paths.isEmpty() + ? QString() + : result.paths.front(); + if (path.isEmpty()) { + return; + } + auto f = QFile(path); + if (!f.open(QIODevice::ReadOnly)) { + return; + } + auto object = Object(); + object.pathAbsolute = QFileInfo(path).absoluteFilePath(); + object.pathRelative = QDir().relativeFilePath(path); + object.content = f.readAll(); + if (object.content.isEmpty()) { + return; + } + _select->clearQuery(); + const auto parsed = ParseTheme(object, false, false); + _inner->applyNewPalette(parsed.palette); + _inner->recreateRows(); + updateControlsGeometry(); + auto image = App::readImage(parsed.background); + if (!image.isNull() && !image.size().isEmpty()) { + Background()->set(Data::CustomWallPaper(), std::move(image)); + Background()->setTile(parsed.tiled); + Ui::ForceFullRepaint(_window->widget()); + } + }); + FileDialog::GetOpenPath( + this, + tr::lng_theme_editor_menu_import(tr::now), + filters.join(qsl(";;")), + crl::guard(this, callback)); +} + QByteArray Editor::ColorizeInContent( QByteArray content, const Colorizer &colorizer) { @@ -754,6 +820,10 @@ void Editor::save() { } void Editor::resizeEvent(QResizeEvent *e) { + updateControlsGeometry(); +} + +void Editor::updateControlsGeometry() { _save->resizeToWidth(width()); _close->moveToRight(0, 0); _menuToggle->moveToRight(_close->width(), 0); diff --git a/Telegram/SourceFiles/window/themes/window_theme_editor.h b/Telegram/SourceFiles/window/themes/window_theme_editor.h index f7ed3fab5..8a246af08 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_editor.h +++ b/Telegram/SourceFiles/window/themes/window_theme_editor.h @@ -65,8 +65,10 @@ private: void save(); void showMenu(); void exportTheme(); + void importTheme(); void closeEditor(); void closeWithConfirmation(); + void updateControlsGeometry(); 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 81fde320e..eea50c5cb 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp @@ -224,7 +224,6 @@ bool PaletteChanged( void ImportFromFile( not_null session, not_null parent) { - const auto &imgExtensions = cImgExtensions(); auto filters = QStringList( qsl("Theme files (*.tdesktop-theme *.tdesktop-palette)")); filters.push_back(FileDialog::AllFilesFilter()); @@ -239,7 +238,7 @@ void ImportFromFile( }); FileDialog::GetOpenPath( parent.get(), - tr::lng_choose_image(tr::now), + tr::lng_theme_editor_menu_import(tr::now), filters.join(qsl(";;")), crl::guard(parent, callback)); } @@ -278,71 +277,6 @@ void ImportFromFile( return data; } -// Only is valid for current theme, pass Local::ReadThemeContent() here. -[[nodiscard]] ParsedTheme ParseTheme( - const Object &theme, - bool onlyPalette = false) { - auto raw = ParsedTheme(); - raw.palette = theme.content; - const auto result = [&] { - if (const auto colorizer = ColorizerForTheme(theme.pathAbsolute)) { - raw.palette = Editor::ColorizeInContent( - std::move(raw.palette), - colorizer); - } - raw.palette = ReplaceAdjustableColors(std::move(raw.palette)); - return raw; - }; - - zlib::FileToRead file(theme.content); - - unz_global_info globalInfo = { 0 }; - file.getGlobalInfo(&globalInfo); - if (file.error() != UNZ_OK) { - return result(); - } - raw.palette = file.readFileContent("colors.tdesktop-theme", zlib::kCaseInsensitive, kThemeSchemeSizeLimit); - if (file.error() == UNZ_END_OF_LIST_OF_FILE) { - file.clearError(); - raw.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) { - raw.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(); - return true; - } - LOG(("Theme Error: could not read '%1' in the theme file.").arg(filename)); - return false; - }; - - if (!fromFile("background.jpg") || !raw.background.isEmpty()) { - return raw.background.isEmpty() ? ParsedTheme() : result(); - } - raw.isPng = true; - if (!fromFile("background.png") || !raw.background.isEmpty()) { - return raw.background.isEmpty() ? ParsedTheme() : result(); - } - raw.tiled = true; - if (!fromFile("tiled.png") || !raw.background.isEmpty()) { - return raw.background.isEmpty() ? ParsedTheme() : result(); - } - raw.isPng = false; - if (!fromFile("background.jpg") || !raw.background.isEmpty()) { - return raw.background.isEmpty() ? ParsedTheme() : result(); - } - return result(); -} - QByteArray GenerateDefaultPalette() { auto result = QByteArray(); const auto rows = style::main_palette::data(); @@ -994,5 +928,72 @@ void SaveThemeBox( box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); } +ParsedTheme ParseTheme( + const Object &theme, + bool onlyPalette, + bool parseCurrent) { + auto raw = ParsedTheme(); + raw.palette = theme.content; + const auto result = [&] { + if (const auto colorizer = ColorizerForTheme(theme.pathAbsolute)) { + raw.palette = Editor::ColorizeInContent( + std::move(raw.palette), + colorizer); + } + if (parseCurrent) { + raw.palette = ReplaceAdjustableColors(std::move(raw.palette)); + } + return raw; + }; + + zlib::FileToRead file(theme.content); + + unz_global_info globalInfo = { 0 }; + file.getGlobalInfo(&globalInfo); + if (file.error() != UNZ_OK) { + return result(); + } + raw.palette = file.readFileContent("colors.tdesktop-theme", zlib::kCaseInsensitive, kThemeSchemeSizeLimit); + if (file.error() == UNZ_END_OF_LIST_OF_FILE) { + file.clearError(); + raw.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) { + raw.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(); + return true; + } + LOG(("Theme Error: could not read '%1' in the theme file.").arg(filename)); + return false; + }; + + if (!fromFile("background.jpg") || !raw.background.isEmpty()) { + return raw.background.isEmpty() ? ParsedTheme() : result(); + } + raw.isPng = true; + if (!fromFile("background.png") || !raw.background.isEmpty()) { + return raw.background.isEmpty() ? ParsedTheme() : result(); + } + raw.tiled = true; + if (!fromFile("tiled.png") || !raw.background.isEmpty()) { + return raw.background.isEmpty() ? ParsedTheme() : result(); + } + raw.isPng = false; + if (!fromFile("background.jpg") || !raw.background.isEmpty()) { + return raw.background.isEmpty() ? ParsedTheme() : result(); + } + return result(); +} + } // 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 150600ccb..6accd3005 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_editor_box.h +++ b/Telegram/SourceFiles/window/themes/window_theme_editor_box.h @@ -19,6 +19,9 @@ class Controller; namespace Theme { +struct Object; +struct ParsedTheme; + void StartEditor( not_null window, const Data::CloudTheme &cloud); @@ -46,5 +49,10 @@ void SaveThemeBox( [[nodiscard]] QByteArray CollectForExport(const QByteArray &palette); +[[nodiscard]] ParsedTheme ParseTheme( + const Object &theme, + bool onlyPalette = false, + bool parseCurrent = true); + } // namespace Theme } // namespace Window