base: add a flag to control the config directory

For testing it's a lot easier to just provide a /tmp/ directory than having to
clear out the normal one that may contain useful drawings for debugging.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
pull/153/head
Peter Hutterer 2019-08-09 14:44:51 +10:00
parent a323ba9aeb
commit 16c22a95ec
5 changed files with 63 additions and 24 deletions

View File

@ -11,6 +11,7 @@
# GNU General Public License for more details. # GNU General Public License for more details.
# #
import sys
import os import os
import subprocess import subprocess
@ -21,9 +22,10 @@ tuhi_gui = os.path.join('@libexecdir@', 'tuhi-gui')
@devel@ # NOQA @devel@ # NOQA
if __name__ == '__main__': if __name__ == '__main__':
tuhi = subprocess.Popen(tuhi_server) args = sys.argv[1:]
tuhi = subprocess.Popen([tuhi_server] + args)
try: try:
subprocess.run(tuhi_gui) subprocess.run([tuhi_gui] + args)
except KeyboardInterrupt: except KeyboardInterrupt:
pass pass
tuhi.terminate() tuhi.terminate()

View File

@ -288,7 +288,7 @@ class Tuhi(GObject.Object):
(GObject.SignalFlags.RUN_FIRST, None, ()), (GObject.SignalFlags.RUN_FIRST, None, ()),
} }
def __init__(self): def __init__(self, config_dir=None):
GObject.Object.__init__(self) GObject.Object.__init__(self)
self.server = TuhiDBusServer() self.server = TuhiDBusServer()
self.server.connect('bus-name-acquired', self._on_tuhi_bus_name_acquired) self.server.connect('bus-name-acquired', self._on_tuhi_bus_name_acquired)
@ -299,7 +299,7 @@ class Tuhi(GObject.Object):
self.bluez.connect('discovery-started', self._on_bluez_discovery_started) self.bluez.connect('discovery-started', self._on_bluez_discovery_started)
self.bluez.connect('discovery-stopped', self._on_bluez_discovery_stopped) self.bluez.connect('discovery-stopped', self._on_bluez_discovery_stopped)
self.config = TuhiConfig() self.config = TuhiConfig(config_dir)
self.devices = {} self.devices = {}
@ -427,6 +427,10 @@ def main(args=sys.argv):
help='Show some debugging informations', help='Show some debugging informations',
action='store_true', action='store_true',
default=False) default=False)
parser.add_argument('--config-dir',
help='Base directory for configuration',
type=str,
default=None)
ns = parser.parse_args(args[1:]) ns = parser.parse_args(args[1:])
if ns.verbose: if ns.verbose:
@ -434,7 +438,7 @@ def main(args=sys.argv):
try: try:
mainloop = GLib.MainLoop() mainloop = GLib.MainLoop()
tuhi = Tuhi() tuhi = Tuhi(config_dir=ns.config_dir)
tuhi.connect('terminate', lambda tuhi: mainloop.quit()) tuhi.connect('terminate', lambda tuhi: mainloop.quit())
mainloop.run() mainloop.run()
except KeyboardInterrupt: except KeyboardInterrupt:

View File

@ -23,7 +23,7 @@ from .wacom import Protocol
logger = logging.getLogger('tuhi.config') logger = logging.getLogger('tuhi.config')
ROOT_PATH = os.path.join(xdg.BaseDirectory.xdg_data_home, 'tuhi') DEFAULT_CONFIG_PATH = os.path.join(xdg.BaseDirectory.xdg_data_home, 'tuhi')
def is_btaddr(addr): def is_btaddr(addr):
@ -31,10 +31,14 @@ def is_btaddr(addr):
class TuhiConfig(GObject.Object): class TuhiConfig(GObject.Object):
def __init__(self): def __init__(self, config_dir=None):
GObject.Object.__init__(self) GObject.Object.__init__(self)
if config_dir is None:
config_dir = DEFAULT_CONFIG_PATH
self.config_dir = config_dir
logger.debug(f'Using config directory: {self.config_dir}')
try: try:
os.mkdir(ROOT_PATH) os.mkdir(config_dir)
except FileExistsError: except FileExistsError:
pass pass
@ -49,7 +53,7 @@ class TuhiConfig(GObject.Object):
return self._devices return self._devices
def _scan_config_dir(self): def _scan_config_dir(self):
with os.scandir(ROOT_PATH) as it: with os.scandir(self.config_dir) as it:
for entry in it: for entry in it:
if entry.is_file(): if entry.is_file():
continue continue
@ -78,7 +82,7 @@ class TuhiConfig(GObject.Object):
assert protocol != Protocol.UNKNOWN assert protocol != Protocol.UNKNOWN
logger.debug(f'{address}: adding new config, UUID {uuid}') logger.debug(f'{address}: adding new config, UUID {uuid}')
path = os.path.join(ROOT_PATH, address) path = os.path.join(self.config_dir, address)
try: try:
os.mkdir(path) os.mkdir(path)
except FileExistsError: except FileExistsError:
@ -115,7 +119,7 @@ class TuhiConfig(GObject.Object):
return return
logger.debug(f'{address}: adding new drawing, timestamp {drawing.timestamp}') logger.debug(f'{address}: adding new drawing, timestamp {drawing.timestamp}')
path = os.path.join(ROOT_PATH, address, f'{drawing.timestamp}.json') path = os.path.join(self.config_dir, address, f'{drawing.timestamp}.json')
with open(path, 'w') as f: with open(path, 'w') as f:
f.write(drawing.to_json()) f.write(drawing.to_json())
@ -127,7 +131,7 @@ class TuhiConfig(GObject.Object):
if address not in self.devices: if address not in self.devices:
return drawings return drawings
configdir = os.path.join(ROOT_PATH, address) configdir = os.path.join(self.config_dir, address)
with os.scandir(configdir) as it: with os.scandir(configdir) as it:
for entry in it: for entry in it:
if not entry.is_file(): if not entry.is_file():

View File

@ -13,6 +13,7 @@
from gi.repository import Gio, GLib, Gtk from gi.repository import Gio, GLib, Gtk
from .window import MainWindow from .window import MainWindow
from .config import Config
import gi import gi
gi.require_version("Gio", "2.0") gi.require_version("Gio", "2.0")
@ -22,8 +23,13 @@ gi.require_version("Gtk", "3.0")
class Application(Gtk.Application): class Application(Gtk.Application):
def __init__(self): def __init__(self):
super().__init__(application_id='org.freedesktop.Tuhi', super().__init__(application_id='org.freedesktop.Tuhi',
flags=Gio.ApplicationFlags.FLAGS_NONE) flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE)
GLib.set_application_name('Tuhi') GLib.set_application_name('Tuhi')
self.add_main_option('config-dir', 0,
GLib.OptionFlags.NONE,
GLib.OptionArg.STRING,
'path to configuration directory',
'/path/to/config-dir')
self._tuhi = None self._tuhi = None
def do_startup(self): def do_startup(self):
@ -34,6 +40,19 @@ class Application(Gtk.Application):
window = MainWindow(application=self) window = MainWindow(application=self)
window.present() window.present()
def do_command_line(self, command_line):
options = command_line.get_options_dict()
# convert GVariantDict -> GVariant -> dict
options = options.end().unpack()
try:
Config.set_base_path(options['config-dir'])
except KeyError:
pass
self.activate()
return 0
def _build_app_menu(self): def _build_app_menu(self):
actions = [('about', self._about), actions = [('about', self._about),
('quit', self._quit), ('quit', self._quit),

View File

@ -22,15 +22,17 @@ from pathlib import Path
logger = logging.getLogger('tuhi.gui.config') logger = logging.getLogger('tuhi.gui.config')
ROOT_PATH = Path(xdg.BaseDirectory.xdg_data_home, 'tuhi') DEFAULT_CONFIG_PATH = Path(xdg.BaseDirectory.xdg_data_home, 'tuhi')
class Config(GObject.Object): class Config(GObject.Object):
_config_obj = None _config_obj = None
_base_path = DEFAULT_CONFIG_PATH
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.path = Path(ROOT_PATH, 'tuhigui.ini') self.path = Path(self._base_path, 'tuhigui.ini')
self.base_path = self._base_path
self.config = configparser.ConfigParser() self.config = configparser.ConfigParser()
# Don't lowercase options # Don't lowercase options
self.config.optionxform = str self.config.optionxform = str
@ -46,10 +48,10 @@ class Config(GObject.Object):
self.config.read(self.path) self.config.read(self.path)
def _load_cached_drawings(self): def _load_cached_drawings(self):
if not ROOT_PATH.exists(): if not self.base_path.exists():
return return
for filename in ROOT_PATH.glob('*.json'): for filename in self.base_path.glob('*.json'):
with open(filename) as fd: with open(filename) as fd:
self._drawings.append(json.load(fd)) self._drawings.append(json.load(fd))
self.notify('drawings') self.notify('drawings')
@ -84,15 +86,15 @@ class Config(GObject.Object):
def add_drawing(self, timestamp, json_string): def add_drawing(self, timestamp, json_string):
'''Add a drawing JSON with the given timestamp to the backend '''Add a drawing JSON with the given timestamp to the backend
storage. This will update self.drawings.''' storage. This will update self.drawings.'''
ROOT_PATH.mkdir(parents=True, exist_ok=True) self.base_path.mkdir(parents=True, exist_ok=True)
path = Path(ROOT_PATH, f'{timestamp}.json') path = Path(self.base_path, f'{timestamp}.json')
if path.exists(): if path.exists():
return return
# Tuhi may still cache files we've 'deleted' locally. These need to # Tuhi may still cache files we've 'deleted' locally. These need to
# be ignored because they're still technically deleted. # be ignored because they're still technically deleted.
deleted = Path(ROOT_PATH, f'{timestamp}.json.deleted') deleted = Path(self.base_path, f'{timestamp}.json.deleted')
if deleted.exists(): if deleted.exists():
return return
@ -105,22 +107,30 @@ class Config(GObject.Object):
def delete_drawing(self, timestamp): def delete_drawing(self, timestamp):
# We don't delete json files immediately, we just rename them # We don't delete json files immediately, we just rename them
# so we can resurrect them in the future if need be. # so we can resurrect them in the future if need be.
path = Path(ROOT_PATH, f'{timestamp}.json') path = Path(self.base_path, f'{timestamp}.json')
target = Path(ROOT_PATH, f'{timestamp}.json.deleted') target = Path(self.base_path, f'{timestamp}.json.deleted')
path.rename(target) path.rename(target)
self._drawings = [d for d in self._drawings if d['timestamp'] != timestamp] self._drawings = [d for d in self._drawings if d['timestamp'] != timestamp]
self.notify('drawings') self.notify('drawings')
def undelete_drawing(self, timestamp): def undelete_drawing(self, timestamp):
path = Path(ROOT_PATH, f'{timestamp}.json') path = Path(self.base_path, f'{timestamp}.json')
target = Path(ROOT_PATH, f'{timestamp}.json.deleted') target = Path(self.base_path, f'{timestamp}.json.deleted')
target.rename(path) target.rename(path)
with open(path) as fd: with open(path) as fd:
self._drawings.append(json.load(fd)) self._drawings.append(json.load(fd))
self.notify('drawings') self.notify('drawings')
@classmethod
def set_base_path(cls, path):
if cls._config_obj is not None:
logger.error('Trying to set config base path but we already have the singleton object')
return
cls._base_path = Path(path)
@classmethod @classmethod
def instance(cls): def instance(cls):
if cls._config_obj is None: if cls._config_obj is None: