SyncTk/modules/utils.py

115 lines
3.3 KiB
Python

from json import JSONDecodeError, dumps, loads
from os import path
from os import name as osname
from tkinter import Misc, PhotoImage
from typing import Any, Literal
import darkdetect
def jsonLoad(filename):
"""Loads arg1 as json and returns its contents"""
with open(filename, "r", encoding='utf8') as file:
try:
output = loads(file.read())
except JSONDecodeError:
raise
except FileNotFoundError:
raise
return output
def jsonSave(contents, filename):
"""Dumps dict/list arg1 to file arg2"""
try:
with open(filename, "w", encoding='utf8') as file:
file.write(dumps(contents, ensure_ascii=False, indent=4))
except Exception as exp:
raise
return
def nested_set(dic, keys, value, create_missing=True):
d = dic
for key in keys[:-1]:
if key in d:
d = d[key]
elif create_missing:
d = d.setdefault(key, {})
else:
return dic
if keys[-1] in d or create_missing:
d[keys[-1]] = value
return dic
def configSet(keys: list, value: Any, create_missing=True) -> None:
"""Set config's value to provided one
### Args:
* keys (`list`): List of keys from the highest one to target.
* value (`Any`): Needed value.
* create_missing (`bool`, optional): Create missing items on the way. Defaults to True.
"""
this_dict = jsonLoad("config.json")
this_dict = nested_set(this_dict, keys, value, create_missing=create_missing)
jsonSave(this_dict, "config.json")
return
def configGet(key: str, *args: str) -> Any:
"""Get value of the config key
### Args:
* key (`str`): The last key of the keys path.
* *args (`str`): Path to key like: dict[args][key].
### Returns:
* any: Value of provided key
"""
try:
this_dict = jsonLoad("config.json")
except FileNotFoundError:
print("Config file not found!", flush=True)
exit()
this_key = this_dict
for dict_key in args:
this_key = this_key[dict_key]
return this_key[key]
def use_dark_mode(no_config=False) -> bool:
"""Return whether dark mode should be used
### Returns:
* `bool`: True if yes and False if no
"""
if no_config is True:
return bool(darkdetect.isDark())
if configGet("dark_mode_auto") is True:
return bool(darkdetect.isDark())
else:
return configGet("dark_mode")
def get_string_mode() -> Literal["dark", "light"]:
"""Return whether dark mode is used
### Returns:
* `Literal["dark", "light"]`
"""
return "dark" if use_dark_mode() is True else "light"
def resize_window(me: Misc, width: int, height: int) -> None:
me.window_width = width
me.window_height = height
me.screen_width = me.winfo_screenwidth()
me.screen_height = me.winfo_screenheight()
me.center_x = int(me.screen_width/2 - me.window_width / 2)
me.center_y = int(me.screen_height/2 - me.window_height / 2)
me.geometry(f'{me.window_width}x{me.window_height}+{me.center_x}+{me.center_y}')
def set_icon(me: Misc) -> None:
if osname == "nt":
me.iconbitmap(path.join("assets", "favicon.ico"))
else:
me.iconphoto(True, PhotoImage(file=path.join("assets", "favicon.png")))