Add import theme to the editor.

This commit is contained in:
John Preston 2019-09-09 23:58:41 +03:00
parent d85f162bff
commit dfd63e66ff
5 changed files with 162 additions and 81 deletions

View File

@ -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.";

View File

@ -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 &copyOf, 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);

View File

@ -65,8 +65,10 @@ private:
void save();
void showMenu();
void exportTheme();
void importTheme();
void closeEditor();
void closeWithConfirmation();
void updateControlsGeometry();
const not_null<Window::Controller*> _window;
const Data::CloudTheme _cloud;

View File

@ -224,7 +224,6 @@ bool PaletteChanged(
void ImportFromFile(
not_null<Main::Session*> session,
not_null<QWidget*> 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

View File

@ -19,6 +19,9 @@ class Controller;
namespace Theme {
struct Object;
struct ParsedTheme;
void StartEditor(
not_null<Window::Controller*> 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