[core/theme] Add support for icon themes
Allow sub-themes ("iconsets") to be merged into the "main" theme. That way, effectively, it's possible to define colors and icons in separate JSON files. see #23
This commit is contained in:
parent
394ef61760
commit
562fd85ca2
5 changed files with 71 additions and 15 deletions
|
@ -1,6 +1,7 @@
|
|||
"""Theme support"""
|
||||
|
||||
import os
|
||||
import copy
|
||||
import json
|
||||
|
||||
import bumblebee.error
|
||||
|
@ -12,11 +13,13 @@ def theme_path():
|
|||
class Theme(object):
|
||||
"""Represents a collection of icons and colors"""
|
||||
def __init__(self, name):
|
||||
theme = self.load(name)
|
||||
self._init(self.load(name))
|
||||
|
||||
def _init(self, data):
|
||||
"""Initialize theme from data structure"""
|
||||
for iconset in data.get("icons", []):
|
||||
self._merge(data, self._load_icons(iconset))
|
||||
self._theme = data
|
||||
self._defaults = data.get("defaults", {})
|
||||
|
||||
def prefix(self, widget):
|
||||
|
@ -31,10 +34,14 @@ class Theme(object):
|
|||
theme = json.loads(data)
|
||||
self._init(theme)
|
||||
|
||||
def load(self, name):
|
||||
def _load_icons(self, name):
|
||||
path = "{}/icons/".format(theme_path())
|
||||
return self.load(name, path=path)
|
||||
|
||||
def load(self, name, path=theme_path()):
|
||||
"""Load and parse a theme file"""
|
||||
path = theme_path()
|
||||
themefile = "{}/{}.json".format(path, name)
|
||||
|
||||
if os.path.isfile(themefile):
|
||||
try:
|
||||
with open(themefile) as data:
|
||||
|
@ -44,10 +51,32 @@ class Theme(object):
|
|||
else:
|
||||
raise bumblebee.error.ThemeLoadError("no such theme: {}".format(name))
|
||||
|
||||
def _get(self, widget, name,default=None):
|
||||
value = default
|
||||
value = self._defaults.get(name, value)
|
||||
def _get(self, widget, name, default=None):
|
||||
|
||||
module_theme = self._theme.get(widget.module(), {})
|
||||
|
||||
value = self._defaults.get(name, default)
|
||||
value = module_theme.get(name, value)
|
||||
|
||||
return value
|
||||
|
||||
# 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.items():
|
||||
if key in target and isinstance(target[key], dict):
|
||||
self._merge(target[key], value)
|
||||
else:
|
||||
target[key] = copy.deepcopy(value)
|
||||
return target
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue