mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
This allows themes to be incomplete (with missing values), which leads to following benefits: - Older themes that have not been updated to have the latest colors will not result in compilation errors - If you only want to change one single color you don't have to copy the whole json file which makes it much more readable
228 lines
8.2 KiB
Python
228 lines
8.2 KiB
Python
# themes_manager.py
|
|
# Authors:
|
|
# - Maxime "M4x1m3" FRIESS
|
|
# - Quentin Guidee
|
|
|
|
import sys
|
|
import argparse
|
|
import os
|
|
import json
|
|
import shutil
|
|
import subprocess
|
|
|
|
|
|
def check_for_git():
|
|
try:
|
|
output = subprocess.check_output(["git", "--version"])
|
|
return True
|
|
except FileNotFoundError:
|
|
print("ERROR: Git not found! Can't download theme from the internet.", file=sys.stderr)
|
|
return False
|
|
|
|
|
|
def check_git_remote(remote_url):
|
|
try:
|
|
output = subprocess.check_output(["git", "ls-remote", remote_url], env=dict(os.environ, GIT_ASKPASS="/bin/true"), stderr=subprocess.PIPE)
|
|
return True
|
|
except subprocess.CalledProcessError:
|
|
print("ERROR: Invalid remote " + remote_url + "!", file=os.stderr)
|
|
return False
|
|
|
|
|
|
def git_pull(folder):
|
|
try:
|
|
print("Updating " + folder + "...", file=sys.stderr)
|
|
output = subprocess.check_output(["git", "-C", folder, "pull"], env=dict(os.environ, GIT_ASKPASS="/bin/true"), stderr=subprocess.PIPE)
|
|
return True
|
|
except subprocess.CalledProcessError:
|
|
return False
|
|
|
|
|
|
def git_clone(url, folder):
|
|
try:
|
|
print("Cloning " + url + " into " + folder + "...", file=sys.stderr)
|
|
output = subprocess.check_output(["git", "clone", url, folder, "--recurse-submodules"], env=dict(os.environ, GIT_ASKPASS="/bin/true"), stderr=subprocess.PIPE)
|
|
return True
|
|
except subprocess.CalledProcessError:
|
|
return False
|
|
|
|
|
|
def get_icons_list():
|
|
"""
|
|
Load icon list from file
|
|
"""
|
|
with open(os.path.dirname(os.path.realpath(__file__)) + os.path.sep + "icons.json", "r") as json_file:
|
|
data = json.load(json_file)
|
|
|
|
return data
|
|
|
|
|
|
def get_data(theme, path):
|
|
"""
|
|
Load theme from file
|
|
"""
|
|
try:
|
|
with open(path + os.path.sep + theme + ".json", "r") as json_file:
|
|
data = json.load(json_file)
|
|
except FileNotFoundError:
|
|
print("ERROR: Theme " + theme + " doesn't exist!", file=sys.stderr)
|
|
sys.exit(3)
|
|
|
|
return data
|
|
|
|
def theme_to_dict(data):
|
|
r = {}
|
|
for key in data["colors"].keys():
|
|
if type(data["colors"][key]) is str:
|
|
r[key]=data["colors"][key]
|
|
else:
|
|
for sub_key in data["colors"][key].keys():
|
|
r[key+sub_key] = data["colors"][key][sub_key]
|
|
return r
|
|
|
|
def write_palette_h(data, file_p):
|
|
"""
|
|
Write the header to file_p
|
|
"""
|
|
file_p.write("#ifndef ESCHER_PALETTE_H\n")
|
|
file_p.write("#define ESCHER_PALETTE_H\n\n")
|
|
file_p.write("#include <kandinsky/color.h>\n")
|
|
file_p.write("#include <stddef.h>\n\n")
|
|
file_p.write("class Palette {\n")
|
|
file_p.write("public:\n")
|
|
|
|
# Default values - sometimes never used
|
|
defaults = {
|
|
"YellowDark": "ffb734",
|
|
"YellowLight": "ffcc7b",
|
|
"PurpleBright": "656975",
|
|
"PurpleDark": "414147",
|
|
"GrayWhite": "f5f5f5",
|
|
"GrayBright": "ececec",
|
|
"GrayMiddle": "d9d9d9",
|
|
"GrayDark": "a7a7a7",
|
|
"GrayVeryDark": "8c8c8c",
|
|
"Select": "d4d7e0",
|
|
"SelectDark": "b0b8d8",
|
|
"WallScreen": "f7f9fa",
|
|
"WallScreenDark": "e0e6ed",
|
|
"SubTab": "b8bbc5",
|
|
"LowBattery": "f30211",
|
|
"Red": "ff000c",
|
|
"RedLight": "fe6363",
|
|
"Magenta": "ff0588",
|
|
"Turquoise": "60c1ec",
|
|
"Pink": "ffabb6",
|
|
"Blue": "5075f2",
|
|
"BlueLight": "718fee",
|
|
"Orange": "fe871f",
|
|
"Green": "50c102",
|
|
"GreenLight": "52db8f",
|
|
"Brown": "8d7350",
|
|
"Purple": "6e2d79",
|
|
"BlueishGrey": "919ea4",
|
|
"Cyan": "00ffff",
|
|
}
|
|
|
|
# First apply a fallback theme to ensure backwards compatibility
|
|
defaults.update(theme_to_dict(get_data("upsilon_light",os.path.dirname(os.path.realpath(__file__)) + os.path.sep + "themes" + os.path.sep + "local")))
|
|
defaults.update(theme_to_dict(data))
|
|
for key in defaults.keys():
|
|
file_p.write(" constexpr static KDColor " + key + " = KDColor::RGB24(0x" + defaults[key] + ");\n")
|
|
|
|
file_p.write(" constexpr static KDColor DataColor[] = {Red, Blue, Green, YellowDark, Magenta, Turquoise, Pink, Orange};\n")
|
|
file_p.write(" constexpr static KDColor DataColorLight[] = {RedLight, BlueLight, GreenLight, YellowLight};\n")
|
|
|
|
file_p.write(" constexpr static KDColor AtomColor[] = {\n")
|
|
file_p.write(" AtomUnknown, AtomAlkaliMetal, AtomAlkaliEarthMetal, AtomLanthanide, AtomActinide, AtomTransitionMetal,\n")
|
|
file_p.write(" AtomPostTransitionMetal, AtomMetalloid, AtomHalogen, AtomReactiveNonmetal, AtomNobleGas\n")
|
|
file_p.write(" };\n\n")
|
|
|
|
file_p.write(" constexpr static size_t numberOfDataColors() { return sizeof(DataColor)/sizeof(KDColor); }\n")
|
|
file_p.write(" constexpr static size_t numberOfLightDataColors() { return sizeof(DataColorLight)/sizeof(KDColor); }\n")
|
|
file_p.write(" static KDColor nextDataColor(int * colorIndex);\n")
|
|
file_p.write("};\n\n")
|
|
|
|
file_p.write("#endif\n")
|
|
|
|
|
|
def handle_git(args):
|
|
output_folder = os.path.basename(args.repo)
|
|
output_folder = output_folder[:-4] if output_folder.endswith(".git") else output_folder # Remove .git extension if present.
|
|
|
|
output_path = os.path.dirname(os.path.realpath(__file__)) + os.path.sep + "themes" + os.path.sep + "git" + os.path.sep + output_folder
|
|
|
|
if (not args.icon): # Assume .h is called before icons, avoiding lot of pull for nothing.
|
|
if (os.path.exists(output_path)): # If directory exists, try to pull
|
|
if (not git_pull(output_path)): # If can't pull, delete and re-clone.
|
|
shutil.rmtree(output_path)
|
|
git_clone(args.repo, output_path)
|
|
else: # If directory doesn't exist, clone.
|
|
git_clone(args.repo, output_path)
|
|
|
|
handle_theme(args, output_path)
|
|
|
|
|
|
def handle_theme(args, path):
|
|
data = get_data(args.theme, path)
|
|
|
|
if (args.icon):
|
|
# Get the icon in the icon theme folder
|
|
icons = get_icons_list()
|
|
|
|
icon_path = path + os.path.sep + data["icons"] + os.path.sep + icons[args.output.replace(args.build_dir, "")]
|
|
|
|
# Check if the file exists
|
|
if os.path.isfile(icon_path):
|
|
# If yes, copy from theme
|
|
shutil.copyfile(icon_path, args.output)
|
|
else:
|
|
# If no, copy from src
|
|
print(" (!!) Icon " + icons[args.output.replace(args.build_dir, "")] + " not found in icon theme " + data["icons"] + ". Using default!")
|
|
shutil.copyfile(args.output.replace(args.build_dir, ""), args.output)
|
|
else:
|
|
if (args.stdout):
|
|
write_palette_h(data, sys.stdout)
|
|
else:
|
|
with open(args.output, "w") as palette_file:
|
|
write_palette_h(data, palette_file)
|
|
|
|
|
|
def main(args):
|
|
if (args.list):
|
|
print(" ==== Local themes ====")
|
|
for file_info in os.listdir(os.path.dirname(os.path.realpath(__file__)) + os.path.sep + "themes" + os.path.sep + "local"):
|
|
if (file_info.endswith(".json")):
|
|
filename = os.path.splitext(file_info)[0]
|
|
print(filename)
|
|
sys.exit(0)
|
|
else:
|
|
if (args.theme == None or args.repo == None):
|
|
print("Please specify repo and theme or use --list!", file=sys.stderr)
|
|
sys.exit(2)
|
|
|
|
if args.repo == "local":
|
|
handle_theme(args, os.path.dirname(os.path.realpath(__file__)) + os.path.sep + "themes" + os.path.sep + "local")
|
|
else:
|
|
if check_for_git():
|
|
if (check_git_remote(args.repo)):
|
|
handle_git(args)
|
|
else:
|
|
sys.exit(5)
|
|
else:
|
|
sys.exit(6)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(description="Process the themes.")
|
|
parser.add_argument("repo", nargs="?", help="git remote from wtich to get the themes from. Set to \"local\" for included themes")
|
|
parser.add_argument("theme", nargs="?", help="the name of the theme")
|
|
parser.add_argument("output", nargs="?", help="path to the output header file")
|
|
parser.add_argument("build_dir", nargs="?", help="path to the output folder")
|
|
parser.add_argument("-l", "--list", help="list locals themes", action="store_true")
|
|
parser.add_argument("-i", "--icon", help="outputs an icon instead of a header", action="store_true")
|
|
parser.add_argument("--stdout", help="print palette.h to stdout", action="store_true")
|
|
|
|
args = parser.parse_args()
|
|
main(args)
|