Cache the json files to disentangle them from Tuhi
Tuhi caches the json data but has no guarantee about storage. So we cache the json we get from Tuhi and store it in our settings dir through our Config backend. Then we use those cached values to generate the SVG files.
This commit is contained in:
parent
b34dbcf899
commit
ff35e5bfc5
|
@ -17,6 +17,7 @@ from gi.repository import GObject
|
||||||
import xdg.BaseDirectory
|
import xdg.BaseDirectory
|
||||||
import configparser
|
import configparser
|
||||||
import logging
|
import logging
|
||||||
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
logger = logging.getLogger('config')
|
logger = logging.getLogger('config')
|
||||||
|
@ -33,7 +34,9 @@ class Config(GObject.Object):
|
||||||
self.config = configparser.ConfigParser()
|
self.config = configparser.ConfigParser()
|
||||||
# Don't lowercase options
|
# Don't lowercase options
|
||||||
self.config.optionxform = str
|
self.config.optionxform = str
|
||||||
|
self._drawings = []
|
||||||
self._load()
|
self._load()
|
||||||
|
self._load_cached_drawings()
|
||||||
|
|
||||||
def _load(self):
|
def _load(self):
|
||||||
if not self.path.exists():
|
if not self.path.exists():
|
||||||
|
@ -42,6 +45,15 @@ class Config(GObject.Object):
|
||||||
logger.debug(f'configuration found')
|
logger.debug(f'configuration found')
|
||||||
self.config.read(self.path)
|
self.config.read(self.path)
|
||||||
|
|
||||||
|
def _load_cached_drawings(self):
|
||||||
|
if not ROOT_PATH.exists():
|
||||||
|
return
|
||||||
|
|
||||||
|
for filename in ROOT_PATH.glob('*.json'):
|
||||||
|
with open(filename) as fd:
|
||||||
|
self._drawings.append(json.load(fd))
|
||||||
|
self.notify('drawings')
|
||||||
|
|
||||||
def _write(self):
|
def _write(self):
|
||||||
self.path.resolve().parent.mkdir(parents=True, exist_ok=True)
|
self.path.resolve().parent.mkdir(parents=True, exist_ok=True)
|
||||||
with open(self.path, 'w') as fd:
|
with open(self.path, 'w') as fd:
|
||||||
|
@ -65,6 +77,25 @@ class Config(GObject.Object):
|
||||||
assert(orientation in ['landscape', 'portrait'])
|
assert(orientation in ['landscape', 'portrait'])
|
||||||
self._add_key('Device', 'Orientation', orientation)
|
self._add_key('Device', 'Orientation', orientation)
|
||||||
|
|
||||||
|
@GObject.property
|
||||||
|
def drawings(self):
|
||||||
|
return self._drawings
|
||||||
|
|
||||||
|
def add_drawing(self, timestamp, json_string):
|
||||||
|
'''Add a drawing JSON with the given timestamp to the backend
|
||||||
|
storage. This will update self.drawings.'''
|
||||||
|
ROOT_PATH.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
path = Path(ROOT_PATH, f'{timestamp}.json')
|
||||||
|
if path.exists():
|
||||||
|
return
|
||||||
|
|
||||||
|
with open(path, 'w') as fd:
|
||||||
|
fd.write(json_string)
|
||||||
|
|
||||||
|
self._drawings.append(json.loads(json_string))
|
||||||
|
self.notify('drawings')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls):
|
def load(cls):
|
||||||
if cls._config_obj is None:
|
if cls._config_obj is None:
|
||||||
|
|
|
@ -51,6 +51,7 @@ class Drawing(Gtk.Box):
|
||||||
self.label_timestamp.set_text(f'{day} {hour}')
|
self.label_timestamp.set_text(f'{day} {hour}')
|
||||||
self.image_svg.set_from_file(svg.filename)
|
self.image_svg.set_from_file(svg.filename)
|
||||||
self.image_completed.set_visible(False)
|
self.image_completed.set_visible(False)
|
||||||
|
self.timestamp = svg.timestamp
|
||||||
|
|
||||||
@GObject.Property
|
@GObject.Property
|
||||||
def name(self):
|
def name(self):
|
||||||
|
|
|
@ -16,7 +16,6 @@ from .drawing import Drawing
|
||||||
from .svg import JsonSvg
|
from .svg import JsonSvg
|
||||||
from .config import Config
|
from .config import Config
|
||||||
|
|
||||||
import json
|
|
||||||
import time
|
import time
|
||||||
import gi
|
import gi
|
||||||
import logging
|
import logging
|
||||||
|
@ -73,18 +72,35 @@ class DrawingPerspective(Gtk.Stack):
|
||||||
self.flowbox_drawings.remove(child)
|
self.flowbox_drawings.remove(child)
|
||||||
child = self.flowbox_drawings.get_child_at_index(0)
|
child = self.flowbox_drawings.get_child_at_index(0)
|
||||||
|
|
||||||
self._update_drawings(self.device, None)
|
self._update_drawings(Config.load(), None)
|
||||||
|
|
||||||
def _update_drawings(self, device, pspec):
|
def _cache_drawings(self, device, pspec):
|
||||||
for ts in reversed(sorted(self.device.drawings_available)):
|
# The config backend filters duplicates anyway, so don't care here
|
||||||
if ts in self.known_drawings:
|
for ts in self.device.drawings_available:
|
||||||
|
json_string = self.device.json(ts)
|
||||||
|
Config.load().add_drawing(ts, json_string)
|
||||||
|
|
||||||
|
def _update_drawings(self, config, pspec):
|
||||||
|
for js in config.drawings:
|
||||||
|
if js in self.known_drawings:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self.known_drawings.append(ts)
|
self.known_drawings.append(js)
|
||||||
js = json.loads(self.device.json(ts))
|
|
||||||
svg = JsonSvg(js)
|
svg = JsonSvg(js)
|
||||||
drawing = Drawing(svg)
|
drawing = Drawing(svg)
|
||||||
self.flowbox_drawings.add(drawing)
|
|
||||||
|
# We don't know which order we get drawings from the device, so
|
||||||
|
# let's do a sorted insert here
|
||||||
|
index = 0
|
||||||
|
child = self.flowbox_drawings.get_child_at_index(index)
|
||||||
|
while child is not None:
|
||||||
|
if child.get_child().timestamp < drawing.timestamp:
|
||||||
|
break
|
||||||
|
index += 1
|
||||||
|
child = self.flowbox_drawings.get_child_at_index(index)
|
||||||
|
|
||||||
|
self.flowbox_drawings.insert(drawing, index)
|
||||||
|
|
||||||
@GObject.Property
|
@GObject.Property
|
||||||
def device(self):
|
def device(self):
|
||||||
|
@ -99,11 +115,20 @@ class DrawingPerspective(Gtk.Stack):
|
||||||
device.connect('notify::sync-state', self._on_sync_state)
|
device.connect('notify::sync-state', self._on_sync_state)
|
||||||
device.connect('notify::battery-percent', self._on_battery_changed)
|
device.connect('notify::battery-percent', self._on_battery_changed)
|
||||||
device.connect('notify::battery-state', self._on_battery_changed)
|
device.connect('notify::battery-state', self._on_battery_changed)
|
||||||
device.connect('notify::drawings-available', self._update_drawings)
|
|
||||||
|
# This is a bit convoluted. We need to cache all drawings
|
||||||
|
# because Tuhi doesn't have guaranteed storage. So any json that
|
||||||
|
# comes in from Tuhi, we pass to our config backend to save
|
||||||
|
# somewhere.
|
||||||
|
# The config backend adds the json file and emits a notify for the
|
||||||
|
# json itself (once cached) that we then actually use for SVG
|
||||||
|
# generation.
|
||||||
|
device.connect('notify::drawings-available', self._cache_drawings)
|
||||||
|
Config.load().connect('notify::drawings', self._update_drawings)
|
||||||
|
|
||||||
self._on_battery_changed(device, None)
|
self._on_battery_changed(device, None)
|
||||||
|
|
||||||
self._update_drawings(self.device, None)
|
self._update_drawings(Config.load(), None)
|
||||||
|
|
||||||
# We always want to sync on startup
|
# We always want to sync on startup
|
||||||
logger.debug(f'{device.name} - starting to listen')
|
logger.debug(f'{device.name} - starting to listen')
|
||||||
|
|
Loading…
Reference in New Issue