diff --git a/.gitignore b/.gitignore index d4a829b..dba0963 100644 --- a/.gitignore +++ b/.gitignore @@ -65,7 +65,7 @@ lib/ lib64/ parts/ sdist/ -var/ +update_files.txt/ wheels/ *.egg-info/ .installed.cfg @@ -140,3 +140,6 @@ ENV/ .ropeproject .idea/ /run.sh +/reupload.sh +/update.sh +/update_files.txt diff --git a/clock.json b/clock.json index 069c625..e930081 100644 --- a/clock.json +++ b/clock.json @@ -1,26 +1,40 @@ [ { "surf": "panel_script::time", - "anchor": "0.5,0.5" + "anchor": "0.5,0.4", + "args": { + "size": 360 + } }, { - "surf": "500 500", - "anchor": "0.5,0.5", + "surf": "1280 500", + "anchor": "0.5,0.4", "position": "0 250", "children": [ { - "surf": "panel_script::date", + "surf": "panel_script::time", + "args": { + "fmt": "%A, %B %d", + "size": 60 + }, "position": "0 -60", "anchor": ".5 .5" }, { - "surf": "panel_script::icon", + "surf": "panel_script::image", + "args": { + "path": "'res/png/'+str(get_weather().current_conditions.icon)+'.png'", + "do_eval": true + }, "position": "0 80", "anchor": ".5 .5", "pivot": "1 .5" }, { - "surf": "panel_script::temperature", + "surf": "panel_script::weather", + "args": { + "fmt": "{current_conditions.temperature}\u00b0{units.temperature}" + }, "position": "0 80", "anchor": ".5 .5", "pivot": "0 .5" diff --git a/infodisplay.py b/infodisplay.py index 2b32364..472b12e 100755 --- a/infodisplay.py +++ b/infodisplay.py @@ -14,7 +14,7 @@ pygame.init() pygame.mouse.set_visible(False) SIZE = (1280, 1024) -mode = pygame.display.set_mode(SIZE, 1) +screen = pygame.display.set_mode(SIZE, pygame.HWSURFACE | pygame.DOUBLEBUF) pygame.display.set_caption("weather clock") clock = pygame.time.Clock() @@ -24,6 +24,8 @@ def game_loop(): parent = None while True: + clock.tick(1) + for event in pygame.event.get(): if event.type == pygame.KEYDOWN: if event.key == pygame.K_q: @@ -35,13 +37,13 @@ def game_loop(): panel_time = os.stat(CONFIG_PATH).st_mtime_ns if panel_time != panel_load: - parent = panel.Panel(SIZE, children=panel.load(CONFIG_PATH)) + parent = panel.Panel(lambda: pygame.Surface(SIZE), children=panel.load(CONFIG_PATH)) panel_load = panel_time - mode.blit(parent.surf, (0, 0)) + screen.fill((0, 0, 0)) + screen.blit(parent.surf, (0, 0)) - pygame.display.update() - clock.tick(8) + pygame.display.flip() game_loop() diff --git a/panel.py b/panel.py index d8e1fca..b3397d4 100644 --- a/panel.py +++ b/panel.py @@ -6,7 +6,7 @@ import pygame class Panel(object): - def __init__(self, surf, position=None, anchor=None, pivot=None, children=None): + def __init__(self, surf, position=None, anchor=None, pivot=None, children=None, args=None): if isinstance(surf, tuple) or not surf: self.__surf = pygame.Surface(surf or (0, 0), flags=pygame.SRCALPHA) else: @@ -16,13 +16,14 @@ class Panel(object): self.anchor = anchor or (0, 0) self.pivot = pivot or self.anchor self.children = children or [] + self.args = args or {} @property def size(self): surf = self.__surf if callable(surf): - surf = surf() + surf = surf(**self.args) if isinstance(surf, Panel): return surf.size @@ -33,7 +34,7 @@ class Panel(object): surf = self.__surf if callable(surf): - surf = surf() + surf = surf(**self.args) elif isinstance(surf, Panel): surf = surf.surf else: @@ -49,11 +50,6 @@ class Panel(object): position = tuple(int(a * s - v * c + p) for a, v, s, c, p in zip(child.anchor, child.pivot, self.size, child.size, child.position)) - if callable(c_surf): - c_surf = c_surf() - if isinstance(c_surf, Panel): - c_surf=c_surf.surf - surf.blit(c_surf, position) return surf @@ -114,6 +110,7 @@ def load(file): anchor = d.get('anchor', None) pivot = d.get('pivot', None) children = d.get('children', []) + args = d.get('args', {}) surf = ordered_pair(surf, int) or script(surf) position = ordered_pair(position, int) @@ -121,7 +118,7 @@ def load(file): pivot = ordered_pair(pivot) children = [from_dict(d) for d in children] - return Panel(surf, position, anchor, pivot, children) + return Panel(surf, position, anchor, pivot, children, args) with open(file) as f: j = json.load(f) diff --git a/panel_script.py b/panel_script.py index 23fa50b..fbde3ee 100644 --- a/panel_script.py +++ b/panel_script.py @@ -12,39 +12,56 @@ WHITE = (255, 255, 255) GRAY = (175, 175, 175) BLACK = (0, 0, 0) -font = { - 'RobotoSlab': { - 30: pygame.font.Font("res/RobotoSlab-Regular.ttf", 30), - 45: pygame.font.Font("res/RobotoSlab-Regular.ttf", 45), - 60: pygame.font.Font("res/RobotoSlab-Regular.ttf", 60), - 90: pygame.font.Font("res/RobotoSlab-Regular.ttf", 90), - 360: pygame.font.Font("res/RobotoSlab-Regular.ttf", 360), - } -} + +class Font(object): + def __init__(self, name): + self.file = name + self.fonts = {} + + def __getitem__(self, size): + if size not in self.fonts: + self.fonts[size] = pygame.font.Font(self.file, size) + return self.fonts[size] -def time(): - return font['RobotoSlab'][360].render(format(datetime.now(), '%I:%H').lstrip('0'), True, WHITE) +roboto = Font('res/RobotoSlab-Regular.ttf') -def date(): - return font['RobotoSlab'][60].render(format(datetime.now(), '%A, %B %d'), True, GRAY) +def __do_eval(text): + try: + return eval(text) + except: + return text -def temperature(): - f = font['RobotoSlab'][90] - return f.render('{0[current_conditions][temperature]}\u00b0'.format(get_weather()), True, WHITE) +def text(size=60, t="", do_eval=False): + if do_eval: + t = __do_eval(t) + return roboto[size].render(t, True, WHITE) -def icon(): - return pygame.image.load('res/png/12.png') +def time(size=60, fmt='%I:%H', strip='0'): + return roboto[size].render(format(datetime.now(), fmt).lstrip(strip), True, WHITE) + + +def weather(size=60, fmt='{current_conditions.temperature}\u00b0'): + return roboto[size].render(fmt.format(**get_weather()), True, WHITE) + + +def image(path="", do_eval=False): + if do_eval: + path = __do_eval(path) + try: + return pygame.image.load(path) + except: + return text(size=15, t=path) def header(): es = get_events() def item(i): - f = font['RobotoSlab'][30] + f = roboto[30] e = es[i] l = e.label t = '{days}d {hours}h {minutes}m'.format(**e.time) diff --git a/wxget.py b/wxget.py index 9426683..4b5961d 100755 --- a/wxget.py +++ b/wxget.py @@ -12,6 +12,25 @@ UPDATE_INTERVAL = 60 * 20 __weather = {} +class AttrDict(dict): + """ Dictionary subclass whose entries can be accessed by attributes + (as well as normally). + """ + + def __init__(self, *args, **kwargs): + super(AttrDict, self).__init__(*args, **kwargs) + self.__dict__ = self + + @staticmethod + def from_nested_dict(data): + """ Construct nested AttrDicts from nested dictionaries. """ + if not isinstance(data, dict): + return data + else: + return AttrDict({key: AttrDict.from_nested_dict(data[key]) + for key in data}) + + def update_weather(force=False): global __weather now = datetime.now() @@ -22,6 +41,7 @@ def update_weather(force=False): if force or interval <= 0 or interval > UPDATE_INTERVAL: __weather = pywapi.get_weather_from_weather_com(LOCATION, UNITS) __weather.setdefault('current_conditions', {}).setdefault('last_checked', str(now)) + __weather = AttrDict.from_nested_dict(__weather) print('updated weather at', now) @@ -33,4 +53,4 @@ def get_weather(force_update=False): if __name__ == '__main__': while True: - print('{0[current_conditions][temperature]}\u00b0{0[units][temperature]}'.format(get_weather())) + print('{current_conditions.temperature}\u00b0{units.temperature}'.format(**get_weather()))