mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
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 witch 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)
|