mirror of https://github.com/tuhiproject/tuhi.git
config: store/load device drawing in the device's directory
parent
7a31a994fb
commit
3bc88bbbb6
|
@ -159,6 +159,8 @@ org.freedesktop.tuhi1.Device
|
||||||
or we run out of memory, whichever happens earlier.
|
or we run out of memory, whichever happens earlier.
|
||||||
Use GetJSONData() to retrieve the data from the daemon.
|
Use GetJSONData() to retrieve the data from the daemon.
|
||||||
|
|
||||||
|
DO NOT RELY ON THE DAEMON FOR PERMANENT STORAGE
|
||||||
|
|
||||||
When drawings become available from the device, the DrawingsAvailable
|
When drawings become available from the device, the DrawingsAvailable
|
||||||
property updates to the number of available drawings.
|
property updates to the number of available drawings.
|
||||||
When the button is pressed multiple times, any new data is appended
|
When the button is pressed multiple times, any new data is appended
|
||||||
|
|
|
@ -45,7 +45,6 @@ class TuhiDevice(GObject.Object):
|
||||||
GObject.Object.__init__(self)
|
GObject.Object.__init__(self)
|
||||||
self.config = config
|
self.config = config
|
||||||
self._wacom_device = None
|
self._wacom_device = None
|
||||||
self.drawings = []
|
|
||||||
# We need either uuid or paired as false
|
# We need either uuid or paired as false
|
||||||
assert uuid is not None or paired is False
|
assert uuid is not None or paired is False
|
||||||
self.paired = paired
|
self.paired = paired
|
||||||
|
@ -84,6 +83,12 @@ class TuhiDevice(GObject.Object):
|
||||||
self._tuhi_dbus_device.connect('pair-requested', self._on_pair_requested)
|
self._tuhi_dbus_device.connect('pair-requested', self._on_pair_requested)
|
||||||
self._tuhi_dbus_device.connect('notify::listening', self._on_listening_updated)
|
self._tuhi_dbus_device.connect('notify::listening', self._on_listening_updated)
|
||||||
|
|
||||||
|
drawings = self.config.load_drawings(self.address)
|
||||||
|
if drawings:
|
||||||
|
logger.debug(f'{self.address}: loaded {len(drawings)} drawings from disk')
|
||||||
|
for d in drawings:
|
||||||
|
self._tuhi_dbus_device.add_drawing(d)
|
||||||
|
|
||||||
@GObject.Property
|
@GObject.Property
|
||||||
def listening(self):
|
def listening(self):
|
||||||
return self._tuhi_dbus_device.listening
|
return self._tuhi_dbus_device.listening
|
||||||
|
@ -115,6 +120,7 @@ class TuhiDevice(GObject.Object):
|
||||||
def _on_drawing_received(self, device, drawing):
|
def _on_drawing_received(self, device, drawing):
|
||||||
logger.debug('Drawing received')
|
logger.debug('Drawing received')
|
||||||
self._tuhi_dbus_device.add_drawing(drawing)
|
self._tuhi_dbus_device.add_drawing(drawing)
|
||||||
|
self.config.store_drawing(self.address, drawing)
|
||||||
|
|
||||||
def _on_fetching_finished(self, device, exception, bluez_device):
|
def _on_fetching_finished(self, device, exception, bluez_device):
|
||||||
bluez_device.disconnect_device()
|
bluez_device.disconnect_device()
|
||||||
|
|
|
@ -18,6 +18,7 @@ import os
|
||||||
import configparser
|
import configparser
|
||||||
import re
|
import re
|
||||||
import logging
|
import logging
|
||||||
|
from .drawing import Drawing
|
||||||
|
|
||||||
logger = logging.getLogger('tuhi.config')
|
logger = logging.getLogger('tuhi.config')
|
||||||
|
|
||||||
|
@ -97,3 +98,38 @@ class TuhiConfig(GObject.Object):
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
config.read(path)
|
config.read(path)
|
||||||
self._devices[address] = config['Device']
|
self._devices[address] = config['Device']
|
||||||
|
|
||||||
|
def store_drawing(self, address, drawing):
|
||||||
|
assert is_btaddr(address)
|
||||||
|
assert drawing is not None
|
||||||
|
|
||||||
|
if address not in self.devices:
|
||||||
|
logger.error("{}: cannot store drawings for unknown device".format(address))
|
||||||
|
return
|
||||||
|
|
||||||
|
logger.debug("{}: adding new drawing, timestamp {}".format(address, drawing.timestamp))
|
||||||
|
path = os.path.join(ROOT_PATH, address, "{}.json".format(drawing.timestamp))
|
||||||
|
|
||||||
|
with open(path, "w") as f:
|
||||||
|
f.write(drawing.to_json())
|
||||||
|
|
||||||
|
def load_drawings(self, address):
|
||||||
|
assert is_btaddr(address)
|
||||||
|
|
||||||
|
drawings = []
|
||||||
|
if address not in self.devices:
|
||||||
|
return drawings
|
||||||
|
|
||||||
|
configdir = os.path.join(ROOT_PATH, address)
|
||||||
|
with os.scandir(configdir) as it:
|
||||||
|
for entry in it:
|
||||||
|
if not entry.is_file():
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not entry.name.endswith('.json'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
d = Drawing.from_json(entry)
|
||||||
|
drawings.append(d)
|
||||||
|
|
||||||
|
return drawings
|
||||||
|
|
|
@ -13,6 +13,9 @@
|
||||||
|
|
||||||
from gi.repository import GObject
|
from gi.repository import GObject
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger('tuhi.drawing')
|
||||||
|
|
||||||
|
|
||||||
class Point(GObject.Object):
|
class Point(GObject.Object):
|
||||||
|
@ -73,6 +76,8 @@ class Drawing(GObject.Object):
|
||||||
Abstracts a drawing. The drawing is composed Strokes, each of which has
|
Abstracts a drawing. The drawing is composed Strokes, each of which has
|
||||||
Points.
|
Points.
|
||||||
"""
|
"""
|
||||||
|
JSON_FILE_FORMAT_VERSION = 1
|
||||||
|
|
||||||
def __init__(self, name, dimensions, timestamp):
|
def __init__(self, name, dimensions, timestamp):
|
||||||
GObject.Object.__init__(self)
|
GObject.Object.__init__(self)
|
||||||
self.name = name
|
self.name = name
|
||||||
|
@ -97,13 +102,41 @@ class Drawing(GObject.Object):
|
||||||
return l
|
return l
|
||||||
|
|
||||||
def to_json(self):
|
def to_json(self):
|
||||||
JSON_FILE_FORMAT_VERSION = 1
|
|
||||||
|
|
||||||
json_data = {
|
json_data = {
|
||||||
'version': JSON_FILE_FORMAT_VERSION,
|
'version': self.JSON_FILE_FORMAT_VERSION,
|
||||||
'devicename': self.name,
|
'devicename': self.name,
|
||||||
'dimensions': list(self.dimensions),
|
'dimensions': list(self.dimensions),
|
||||||
'timestamp': self.timestamp,
|
'timestamp': self.timestamp,
|
||||||
'strokes': [s.to_dict() for s in self.strokes]
|
'strokes': [s.to_dict() for s in self.strokes]
|
||||||
}
|
}
|
||||||
return json.dumps(json_data)
|
return json.dumps(json_data)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_json(cls, path):
|
||||||
|
d = None
|
||||||
|
with open(path, 'r') as fp:
|
||||||
|
json_data = json.load(fp)
|
||||||
|
|
||||||
|
try:
|
||||||
|
if json_data['version'] != cls.JSON_FILE_FORMAT_VERSION:
|
||||||
|
logger.error(f'{path}: Invalid file format version')
|
||||||
|
return d
|
||||||
|
|
||||||
|
name = json_data['devicename']
|
||||||
|
dimensions = tuple(json_data['dimensions'])
|
||||||
|
timestamp = json_data['timestamp']
|
||||||
|
d = Drawing(name, dimensions, timestamp)
|
||||||
|
|
||||||
|
for s in json_data['strokes']:
|
||||||
|
stroke = d.new_stroke()
|
||||||
|
for p in s['points']:
|
||||||
|
position = p.get('position', None)
|
||||||
|
pressure = p.get('pressure', None)
|
||||||
|
stroke.new_abs(position, pressure)
|
||||||
|
except KeyError:
|
||||||
|
logger.error(f'{path}: failed to parse json file')
|
||||||
|
|
||||||
|
return d
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f'Drawing from {self.name} at {self.timestamp}, {len(self.strokes)} strokes'
|
||||||
|
|
Loading…
Reference in New Issue