[themes] Make it possible to merge themes to get "icon themes"
Add code that allows themes to be merged (i.e. if certain elements are not present in a theme, another theme can be "overlaid" to add missing elements). Effectively, this is used to create the logical concept of an "icon theme", which is loaded after the main theme. So, the main theme can define colors, and the icon theme fills in any missing elements (practically, all the icons in the form of prefixes and suffixes). Icon sets are defined in a theme using the "icons" directive, which should be an array. see #17
This commit is contained in:
parent
f6db8b0a85
commit
209fa83324
10 changed files with 296 additions and 600 deletions
|
@ -1,4 +1,5 @@
|
|||
import os
|
||||
import copy
|
||||
import json
|
||||
import yaml
|
||||
import glob
|
||||
|
@ -14,16 +15,44 @@ class Theme:
|
|||
def __init__(self, config):
|
||||
self._config = config
|
||||
|
||||
if os.path.isfile("{}/{}.yaml".format(getpath(), config.theme())):
|
||||
with open("{}/{}.yaml".format(getpath(), config.theme())) as f:
|
||||
self._data = yaml.load(f)
|
||||
else:
|
||||
with open("{}/{}.json".format(getpath(), config.theme())) as f:
|
||||
self._data = json.load(f)
|
||||
self._data = self.get_theme(config.theme())
|
||||
|
||||
for iconset in self._data.get("icons", []):
|
||||
self.merge(self._data, self.get_theme(iconset))
|
||||
|
||||
self._defaults = self._data.get("defaults", {})
|
||||
self._cycles = self._defaults.get("cycle", [])
|
||||
self.begin()
|
||||
|
||||
def get_theme(self, name):
|
||||
for path in [ getpath(), "{}/icons/".format(getpath()) ]:
|
||||
if os.path.isfile("{}/{}.yaml".format(path, name)):
|
||||
with open("{}/{}.yaml".format(path, name)) as f:
|
||||
return yaml.load(f)
|
||||
if os.path.isfile("{}/{}.json".format(path, name)):
|
||||
with open("{}/{}.json".format(path, name)) as f:
|
||||
return json.load(f)
|
||||
return None
|
||||
|
||||
# algorithm copied from
|
||||
# http://blog.impressiver.com/post/31434674390/deep-merge-multiple-python-dicts
|
||||
# nicely done :)
|
||||
def merge(self, target, *args):
|
||||
if len(args) > 1:
|
||||
for item in args:
|
||||
self.merge(item)
|
||||
return target
|
||||
|
||||
item = args[0]
|
||||
if not isinstance(item, dict):
|
||||
return item
|
||||
for key, value in item.iteritems():
|
||||
if key in target and isinstance(target[key], dict):
|
||||
self.merge(target[key], value)
|
||||
else:
|
||||
target[key] = copy.deepcopy(value)
|
||||
return target
|
||||
|
||||
def begin(self):
|
||||
self._config.set("theme.cycleidx", 0)
|
||||
self._cycle = self._cycles[0] if len(self._cycles) > 0 else {}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue