This repository has been archived on 2023-02-02. You can view files and clone it, but cannot push or open issues or pull requests.
barkshark-web/barkshark_web/base.py
2022-09-04 11:22:14 -04:00

214 lines
4.3 KiB
Python

from .functions import (
connect,
set_image
)
class PropertyBase:
_app = None
_db = None
_window = None
@property
def app(self):
return self._app or Gio.Application.get_default()
@app.setter
def app(self, value):
self._app = value
@property
def db(self):
return self._db or self.app.db
@db.setter
def db(self, value):
self._db = value
@property
def window(self):
return self._window or self.app.window
@window.setter
def window(self, value):
self._window = value
class BuilderBase(PropertyBase):
def __init__(self, path):
self._path = path
self._builder = Gtk.Builder.new_from_file(path)
self._connected_sigs = {}
def __getitem__(self, name):
if not (widget := self._builder.get_object(name)):
raise KeyError(f'Widget with ID "{name}" does not exist.')
return widget
def __setitem__(self, name, widget):
try:
self[name]
raise KeyError(f'Widget ID already exists: {name}')
except KeyError:
self._builder.expose_object(name, widget)
return widget
def __delitem__(self, name):
self[name].destroy()
def __del__(self):
self.destroy()
@property
def path(self):
return self._path
def block_signals(self, *names):
signals = {name: self.get_signals(name) for name in names}
return SignalBlock(self, signals)
def connect(self, name, signal, callback, *args, **kwargs):
widget = self[name]
if not self._connected_sigs.get(name):
self._connected_sigs[name] = {}
if signal in self._connected_sigs[name]:
raise KeyError(f'Signal for "{name}" already connected: {signal}')
self._connected_sigs[name][signal] = connect(widget, signal, callback, *args, **kwargs)
return self._connected_sigs[name][signal]
def disconnect(self, name, signal):
try:
sigid = self._connected_sigs[name].pop(signal)
self[name].disconnect(sigid)
except KeyError:
raise KeyError(f'Signal for "{name}" not connected: {signal}')
def destroy(self):
for widget in self._builder.get_objects():
try: widget.destroy()
except: pass
self._connected_sigs = {}
def get_signals(self, name):
return self._connected_sigs[name]
def reload(self):
self.destroy(False)
self._builder.add_from_file(self.path)
def set_icon(self, name, obj, size=16, keep='width'):
set_image(self[name], obj, size, keep)
def set_icon_from_resource(self, name, filename, size=16, keep='width'):
path = self.app.path.resources.join('icons').join(f'{filename}')
self.set_icon(name, path, size, keep)
class ComponentBase(PropertyBase):
signals = {}
def __init__(self, prefix=None):
self._prefix = prefix
def __getitem__(self, key):
key = f'{self._prefix}-{key}' if self._prefix else key
return self.window[key]
def __setitem__(self, key, widget):
key = f'{self._prefix}-{key}' if self._prefix else key
self.window[key] = widget
def __delitem__(self, key):
key = f'{self._prefix}-{key}' if self._prefix else key
del self.window[key]
def block_signals(self, *names):
return BuilderBase.block_signals(self, *names)
def connect(self, name, signal, callback, *args, **kwargs):
name = f'{self._prefix}-{name}' if self._prefix else name
return self.window.connect(name, signal, callback, *args, **kwargs)
def disconnect(self, name, signal):
name = f'{self._prefix}-{name}' if self._prefix else name
return self.window.disconnect(name, signal)
def get_signals(self, name):
return self._window._connected_sigs[f'{self._prefix}-{name}']
def set_icon(self, name, obj, size=16):
BuilderBase.set_icon(self, name, obj, size)
def set_icon_from_resource(self, name, filename, size=16):
Builder.set_icon_from_resource(self, name, filename, size)
def setup_signals(self):
for name, sigs in self.signals.items():
for data in sigs:
data = DotDict(data)
if name.startswith('menu'):
data.args.append('menu')
self.connect(name, data.signal, data.callback, *data.get('args', []), **data.get('kwargs', {}))
class SignalBlock:
def __init__(self, parent, signals):
self.parent = parent
self.signals = signals
def __enter__(self):
self.set_block(True)
def __exit__(self, *args):
self.set_block(False)
def set_block(self, block):
for name, signals in self.signals.items():
for signame, sigid in signals.items():
if block:
self.parent[name].handler_block(sigid)
else:
self.parent[name].handler_unblock(sigid)