2020-02-15 14:05:27 +01:00
|
|
|
import os
|
|
|
|
import io
|
|
|
|
import json
|
2020-03-08 14:18:10 +01:00
|
|
|
import logging
|
2020-04-05 14:57:52 +02:00
|
|
|
import copy
|
2020-02-15 14:05:27 +01:00
|
|
|
|
2020-02-16 14:39:10 +01:00
|
|
|
import core.event
|
2020-02-22 14:07:24 +01:00
|
|
|
import util.algorithm
|
2020-02-16 14:39:10 +01:00
|
|
|
|
2020-03-08 14:18:10 +01:00
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
2020-02-15 14:05:27 +01:00
|
|
|
THEME_BASE_DIR=os.path.dirname(os.path.realpath(__file__))
|
|
|
|
PATHS=[
|
|
|
|
'.',
|
|
|
|
os.path.join(THEME_BASE_DIR, '../themes'),
|
|
|
|
os.path.expanduser('~/.config/bumblebee-status/themes'),
|
|
|
|
]
|
2020-02-09 13:46:56 +01:00
|
|
|
|
2020-04-05 14:57:52 +02:00
|
|
|
def merge_replace(value, new_value, key):
|
|
|
|
if not isinstance(value, dict):
|
|
|
|
return new_value
|
|
|
|
if isinstance(new_value, dict):
|
|
|
|
util.algorithm.merge(value, new_value)
|
|
|
|
return value
|
|
|
|
# right now, merging needs explicit pango support :(
|
|
|
|
if 'pango' in value:
|
|
|
|
value['pango']['full_text'] = new_value
|
|
|
|
return value
|
|
|
|
|
2020-02-09 13:46:56 +01:00
|
|
|
class Theme(object):
|
2020-02-22 14:11:10 +01:00
|
|
|
def __init__(self, name='default', iconset='auto', raw_data=None):
|
2020-02-15 14:05:27 +01:00
|
|
|
self.name = name
|
2020-02-16 14:39:10 +01:00
|
|
|
self.__widget_count = 0
|
2020-02-23 14:31:30 +01:00
|
|
|
self.__previous = {}
|
|
|
|
self.__current = {}
|
2020-03-08 14:18:10 +01:00
|
|
|
self.__keywords = {}
|
2020-04-12 14:01:51 +02:00
|
|
|
self.__value_idx = {}
|
2020-03-28 14:03:50 +01:00
|
|
|
self.__data = raw_data if raw_data else self.load(name)
|
|
|
|
for icons in self.__data.get('icons', []):
|
|
|
|
util.algorithm.merge(self.__data, self.load(icons, 'icons'))
|
|
|
|
if iconset != 'auto':
|
|
|
|
util.algorithm.merge(self.__data, self.load(iconset, 'icons'))
|
|
|
|
for colors in self.__data.get('colors', []):
|
|
|
|
util.algorithm.merge(self.__keywords, self.load_keywords(colors))
|
2020-02-22 14:07:24 +01:00
|
|
|
|
2020-04-12 20:11:02 +02:00
|
|
|
core.event.register('draw', self.__start)
|
2020-02-16 14:39:10 +01:00
|
|
|
core.event.register('next-widget', self.__next_widget)
|
2020-02-15 14:05:27 +01:00
|
|
|
|
2020-03-28 14:03:50 +01:00
|
|
|
def keywords(self):
|
|
|
|
return self.__keywords
|
|
|
|
|
2020-04-26 10:33:41 +02:00
|
|
|
def color(self, name, default=None):
|
|
|
|
return self.keywords().get(name, default)
|
|
|
|
|
2020-02-22 14:07:24 +01:00
|
|
|
def load(self, name, subdir=''):
|
2020-03-28 14:51:48 +01:00
|
|
|
if isinstance(name, dict): return name # support plain data
|
2020-02-15 14:05:27 +01:00
|
|
|
for path in PATHS:
|
2020-02-22 14:07:24 +01:00
|
|
|
theme_file = os.path.join(path, subdir, '{}.json'.format(name))
|
2020-04-10 16:56:15 +02:00
|
|
|
result = self.__load_json(theme_file)
|
|
|
|
if result != {}: return result
|
2020-02-15 14:05:27 +01:00
|
|
|
raise RuntimeError('unable to find theme {}'.format(name))
|
|
|
|
|
2020-04-10 16:56:15 +02:00
|
|
|
def __load_json(self, filename):
|
|
|
|
filename = os.path.expanduser(filename)
|
|
|
|
if not os.path.isfile(filename): return {}
|
|
|
|
with io.open(filename) as data:
|
|
|
|
return json.load(data)
|
2020-03-08 14:18:10 +01:00
|
|
|
|
|
|
|
def load_keywords(self, name):
|
|
|
|
try:
|
|
|
|
if isinstance(name, dict):
|
|
|
|
return name
|
|
|
|
if name.lower() == 'wal':
|
2020-04-10 16:56:15 +02:00
|
|
|
wal = self.__load_json('~/.cache/wal/colors.json')
|
|
|
|
result = {}
|
|
|
|
for field in ['special', 'colors']:
|
|
|
|
for key in wal.get(field, {}):
|
|
|
|
result[key] = wal[field][key]
|
|
|
|
return result
|
2020-03-08 14:18:10 +01:00
|
|
|
except Exception as e:
|
|
|
|
log.error('failed to load colors: {}', e)
|
|
|
|
|
2020-02-16 14:39:10 +01:00
|
|
|
def __start(self):
|
|
|
|
self.__widget_count = 0
|
2020-02-23 14:31:30 +01:00
|
|
|
self.__current.clear()
|
|
|
|
self.__previous.clear()
|
2020-02-22 13:42:44 +01:00
|
|
|
|
2020-04-12 14:01:51 +02:00
|
|
|
for key, value in self.__value_idx.items():
|
|
|
|
self.__value_idx[key] = value + 1
|
|
|
|
|
2020-02-16 14:39:10 +01:00
|
|
|
def __next_widget(self):
|
|
|
|
self.__widget_count = self.__widget_count + 1
|
2020-02-23 14:31:30 +01:00
|
|
|
self.__previous = dict(self.__current)
|
|
|
|
self.__current.clear()
|
2020-02-16 14:39:10 +01:00
|
|
|
|
2020-04-05 10:53:17 +02:00
|
|
|
def get(self, key, widget=None, default=None):
|
2020-02-23 21:13:49 +01:00
|
|
|
if not widget:
|
|
|
|
widget = core.widget.Widget('')
|
2020-04-07 21:00:55 +02:00
|
|
|
# special handling
|
|
|
|
if widget == 'previous':
|
|
|
|
return self.__previous.get(key, None)
|
2020-02-23 14:31:30 +01:00
|
|
|
|
2020-02-15 14:05:27 +01:00
|
|
|
value = default
|
|
|
|
|
2020-02-16 14:02:21 +01:00
|
|
|
for option in ['defaults', 'cycle']:
|
2020-02-16 14:39:10 +01:00
|
|
|
if option in self.__data:
|
|
|
|
tmp = self.__data[option]
|
2020-02-16 14:02:21 +01:00
|
|
|
if isinstance(tmp, list):
|
2020-02-16 14:39:10 +01:00
|
|
|
tmp = tmp[self.__widget_count % len(tmp)]
|
2020-04-05 14:57:52 +02:00
|
|
|
value = merge_replace(value, tmp.get(key, value), key)
|
|
|
|
|
|
|
|
if isinstance(value, dict):
|
|
|
|
value = copy.deepcopy(value)
|
2020-02-23 14:31:30 +01:00
|
|
|
|
2020-04-05 14:57:52 +02:00
|
|
|
value = merge_replace(value, self.__data.get(key, value), key)
|
2020-02-24 14:54:11 +01:00
|
|
|
|
|
|
|
if widget.module():
|
2020-04-07 20:41:09 +02:00
|
|
|
value = merge_replace(value, self.get(widget.module().name(), None, {}).get(key, value), key)
|
2020-02-24 14:54:11 +01:00
|
|
|
|
2020-02-23 21:13:49 +01:00
|
|
|
if not key in widget.state():
|
|
|
|
for state in widget.state():
|
2020-04-07 20:41:09 +02:00
|
|
|
theme = self.get(state, widget, {})
|
2020-04-05 14:57:52 +02:00
|
|
|
value = merge_replace(value, theme.get(key, value), key)
|
2020-02-23 21:13:49 +01:00
|
|
|
|
2020-03-08 14:18:10 +01:00
|
|
|
if not type(value) in (list, dict):
|
|
|
|
value = self.__keywords.get(value, value)
|
2020-04-02 12:51:08 +02:00
|
|
|
|
|
|
|
if isinstance(value, list):
|
2020-04-12 14:01:51 +02:00
|
|
|
idx = self.__value_idx.get('{}::{}'.format(widget.id, key), 0) % len(value)
|
|
|
|
self.__value_idx['{}::{}'.format(widget.id, key)] = idx
|
|
|
|
widget.set(key, idx)
|
2020-04-02 12:51:08 +02:00
|
|
|
value = value[idx]
|
2020-02-23 14:31:30 +01:00
|
|
|
self.__current[key] = value
|
2020-02-15 14:05:27 +01:00
|
|
|
return value
|
2020-02-09 13:46:56 +01:00
|
|
|
|
|
|
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|