mirror of https://github.com/procxx/kepka.git
				
				
				
			Add import theme to the editor.
This commit is contained in:
		
							parent
							
								
									d85f162bff
								
							
						
					
					
						commit
						dfd63e66ff
					
				|  | @ -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."; | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue