Refactored db setup; extended layout to add header widget zone

This commit is contained in:
itdominator 2023-11-19 15:37:11 -06:00
parent f9707c8d6e
commit 1986bab879
10 changed files with 155 additions and 41 deletions

View File

@ -8,6 +8,8 @@ A template project for Python with Gtk applications.
* sqlmodel (SQL databases and is powered by Pydantic and SQLAlchemy) * sqlmodel (SQL databases and is powered by Pydantic and SQLAlchemy)
### Note ### Note
* Move respetive sub folder content under user_config to the same places in Linux. Though, user/share/<app name> can go to ~/.config folder if prefered.
* In additiion, place the plugins folder in the same app folder you moved to /usr/share/<app name> or ~/.config/<app name> .
There are a "\<change_me\>" strings and files that need to be set according to your app's name located at: There are a "\<change_me\>" strings and files that need to be set according to your app's name located at:
* \_\_builtins\_\_.py * \_\_builtins\_\_.py
* user_config/bin/app_name * user_config/bin/app_name

View File

@ -6,7 +6,7 @@ import sys
# Lib imports # Lib imports
# Application imports # Application imports
from utils.models import engine from utils.db import DB
from utils.event_system import EventSystem from utils.event_system import EventSystem
from utils.endpoint_registry import EndpointRegistry from utils.endpoint_registry import EndpointRegistry
from utils.keybindings import Keybindings from utils.keybindings import Keybindings
@ -18,13 +18,17 @@ from utils.settings_manager.manager import SettingsManager
# NOTE: Threads WILL NOT die with parent's destruction. # NOTE: Threads WILL NOT die with parent's destruction.
def threaded_wrapper(fn): def threaded_wrapper(fn):
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=False).start() thread = threading.Thread(target = fn, args = args, kwargs = kwargs, daemon = False)
thread.start()
return thread
return wrapper return wrapper
# NOTE: Threads WILL die with parent's destruction. # NOTE: Threads WILL die with parent's destruction.
def daemon_threaded_wrapper(fn): def daemon_threaded_wrapper(fn):
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start() thread = threading.Thread(target = fn, args = args, kwargs = kwargs, daemon = True)
thread.start()
return thread
return wrapper return wrapper
@ -32,12 +36,12 @@ def daemon_threaded_wrapper(fn):
# NOTE: Just reminding myself we can add to builtins two different ways... # NOTE: Just reminding myself we can add to builtins two different ways...
# __builtins__.update({"event_system": Builtins()}) # __builtins__.update({"event_system": Builtins()})
builtins.app_name = "<change_me>" builtins.app_name = "<change_me>"
builtins.db = engine
builtins.keybindings = Keybindings() builtins.keybindings = Keybindings()
builtins.event_system = EventSystem() builtins.event_system = EventSystem()
builtins.endpoint_registry = EndpointRegistry() builtins.endpoint_registry = EndpointRegistry()
builtins.settings_manager = SettingsManager() builtins.settings_manager = SettingsManager()
builtins.db = DB()
settings_manager.load_settings() settings_manager.load_settings()

View File

@ -15,6 +15,7 @@ class AppLaunchException(Exception):
... ...
class Application(IPCServer): class Application(IPCServer):
""" docstring for Application. """ """ docstring for Application. """
@ -30,7 +31,7 @@ class Application(IPCServer):
message = f"FILE|{arg}" message = f"FILE|{arg}"
self.send_ipc_message(message) self.send_ipc_message(message)
raise AppLaunchException(f"{app_name} IPC Server Exists: Will send path(s) to it and close...") raise AppLaunchException(f"{app_name} IPC Server Exists: Have sent path(s) to it and closing...")
self.setup_debug_hook() self.setup_debug_hook()
Window(args, unknownargs) Window(args, unknownargs)

View File

@ -6,9 +6,8 @@ gi.require_version('Gtk', '3.0')
from gi.repository import Gtk from gi.repository import Gtk
# Application imports # Application imports
from .left_container import LeftContainer from .header_container import HeaderContainer
from .center_container import CenterContainer from .body_container import BodyContainer
from .right_container import RightContainer
@ -38,9 +37,8 @@ class BaseContainer(Gtk.Box):
event_system.subscribe("remove_transparency", self._remove_transparency) event_system.subscribe("remove_transparency", self._remove_transparency)
def _load_widgets(self): def _load_widgets(self):
self.add(LeftContainer()) self.add(HeaderContainer())
self.add(CenterContainer()) self.add(BodyContainer())
self.add(RightContainer())
def _update_transparency(self): def _update_transparency(self):
self.ctx.add_class(f"mw_transparency_{settings.theming.transparency}") self.ctx.add_class(f"mw_transparency_{settings.theming.transparency}")

View File

@ -0,0 +1,44 @@
# Python imports
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
# Application imports
from .left_container import LeftContainer
from .center_container import CenterContainer
from .right_container import RightContainer
class BodyContainer(Gtk.Box):
def __init__(self):
super(BodyContainer, self).__init__()
self.ctx = self.get_style_context()
self._setup_styling()
self._setup_signals()
self._subscribe_to_events()
self._load_widgets()
self.show_all()
def _setup_styling(self):
self.set_orientation(Gtk.Orientation.HORIZONTAL)
self.ctx.add_class("body-container")
self.set_homogeneous(True)
def _setup_signals(self):
...
def _subscribe_to_events(self):
...
def _load_widgets(self):
self.add(LeftContainer())
self.add(CenterContainer())
self.add(RightContainer())

View File

@ -6,7 +6,7 @@ gi.require_version('Gtk', '3.0')
from gi.repository import Gtk from gi.repository import Gtk
# Application imports # Application imports
from ..widgets.transparency_scale import TransparencyScale
class CenterContainer(Gtk.Box): class CenterContainer(Gtk.Box):
@ -35,21 +35,12 @@ class CenterContainer(Gtk.Box):
def _load_widgets(self): def _load_widgets(self):
glade_box = self._builder.get_object("glade_box") glade_box = self._builder.get_object("glade_box")
glade_box = self._builder.get_object("glade_box") button = Gtk.Button(label = "Click Me!")
button = Gtk.Button(label = "Interactive Debug")
button2 = Gtk.Button(label = "Click Me!")
button.connect("clicked", self._interactive_debug) button.connect("clicked", self._hello_world)
button2.connect("clicked", self._hello_world)
self.add(TransparencyScale())
self.add(button) self.add(button)
self.add(button2)
self.add(glade_box) self.add(glade_box)
def _interactive_debug(self, widget = None, eve = None):
event_system.emit("load_interactive_debug")
def _hello_world(self, widget = None, eve = None): def _hello_world(self, widget = None, eve = None):
logger.debug("Hello, World!") logger.debug("Hello, World!")

View File

@ -0,0 +1,46 @@
# Python imports
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
# Application imports
from ..widgets.transparency_scale import TransparencyScale
class HeaderContainer(Gtk.Box):
def __init__(self):
super(HeaderContainer, self).__init__()
self.ctx = self.get_style_context()
self._setup_styling()
self._setup_signals()
self._subscribe_to_events()
self._load_widgets()
self.show_all()
def _setup_styling(self):
self.set_orientation(Gtk.Orientation.HORIZONTAL)
self.ctx.add_class("header-container")
def _setup_signals(self):
...
def _subscribe_to_events(self):
...
def _load_widgets(self):
button = Gtk.Button(label = "Interactive Debug")
button.connect("clicked", self._interactive_debug)
self.add(TransparencyScale())
self.add(button)
def _interactive_debug(self, widget = None, eve = None):
event_system.emit("load_interactive_debug")

View File

@ -26,7 +26,7 @@ class TransparencyScale(Gtk.Scale):
self.set_digits(0) self.set_digits(0)
self.set_value_pos(Gtk.PositionType.RIGHT) self.set_value_pos(Gtk.PositionType.RIGHT)
self.add_mark(50.0, Gtk.PositionType.TOP, "50%") self.add_mark(50.0, Gtk.PositionType.TOP, "50%")
self.set_hexpand(True)
def _setup_signals(self): def _setup_signals(self):
self.connect("value-changed", self._update_transparency) self.connect("value-changed", self._update_transparency)

38
src/utils/db.py Normal file
View File

@ -0,0 +1,38 @@
# Python imports
from typing import Optional
from os import path
# Lib imports
from sqlmodel import Session, create_engine
# Application imports
from .models import SQLModel, User
class DB:
def __init__(self):
super(DB, self).__init__()
self.create_engine()
# NOTE: for sake of example we create an admin user with no password set.
self.add_user_entry(name = "Admin", password = "", email = "admin@domain.com")
def create_engine(self):
db_path = f"sqlite:///{settings_manager.get_home_config_path()}/database.db"
self.engine = create_engine(db_path)
SQLModel.metadata.create_all(self.engine)
def _add_entry(self, entry):
with Session(self.engine) as session:
session.add(entry)
session.commit()
def add_user_entry(self, name = None, password = None, email = None):
if not name or not password or not email: return
user = User(name, password, email)
self._add_entry(user)

View File

@ -2,7 +2,7 @@
from typing import Optional from typing import Optional
# Lib imports # Lib imports
from sqlmodel import Field, Session, SQLModel, create_engine from sqlmodel import SQLModel, Field
# Application imports # Application imports
@ -13,13 +13,3 @@ class User(SQLModel, table = True):
name: str name: str
password: str password: str
email: Optional[str] = None email: Optional[str] = None
# NOTE: for sake of example we create an admin user with no password set.
user = User(name = "Admin", password = "", email = "admin@domain.com")
engine = create_engine("sqlite:///database.db")
SQLModel.metadata.create_all(engine)
with Session(engine) as session:
session.add(user)
session.commit()