Refactored db setup; extended layout to add header widget zone
This commit is contained in:
parent
f9707c8d6e
commit
1986bab879
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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}")
|
||||||
|
|
|
@ -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())
|
|
@ -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!")
|
|
@ -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")
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
|
@ -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()
|
|
||||||
|
|
Loading…
Reference in New Issue