develop #1
@ -8,6 +8,8 @@ A template project for Python with Gtk applications.
|
||||
* sqlmodel (SQL databases and is powered by Pydantic and SQLAlchemy)
|
||||
|
||||
### 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:
|
||||
* \_\_builtins\_\_.py
|
||||
* user_config/bin/app_name
|
||||
@ -18,4 +20,4 @@ There are a "\<change_me\>" strings and files that need to be set according to y
|
||||
|
||||
|
||||
For the user_config, after changing names and files, copy all content to their respective destinations.
|
||||
The logic follows Debian Dpkg packaging and its placement logic.
|
||||
The logic follows Debian Dpkg packaging and its placement logic.
|
@ -6,7 +6,7 @@ import sys
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from utils.models import engine
|
||||
from utils.db import DB
|
||||
from utils.event_system import EventSystem
|
||||
from utils.endpoint_registry import EndpointRegistry
|
||||
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.
|
||||
def threaded_wrapper(fn):
|
||||
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
|
||||
|
||||
# NOTE: Threads WILL die with parent's destruction.
|
||||
def daemon_threaded_wrapper(fn):
|
||||
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
|
||||
|
||||
|
||||
@ -32,12 +36,12 @@ def daemon_threaded_wrapper(fn):
|
||||
# NOTE: Just reminding myself we can add to builtins two different ways...
|
||||
# __builtins__.update({"event_system": Builtins()})
|
||||
builtins.app_name = "<change_me>"
|
||||
builtins.db = engine
|
||||
|
||||
builtins.keybindings = Keybindings()
|
||||
builtins.event_system = EventSystem()
|
||||
builtins.endpoint_registry = EndpointRegistry()
|
||||
builtins.settings_manager = SettingsManager()
|
||||
builtins.db = DB()
|
||||
|
||||
settings_manager.load_settings()
|
||||
|
||||
@ -58,4 +62,4 @@ def custom_except_hook(exc_type, exc_value, exc_traceback):
|
||||
|
||||
logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback))
|
||||
|
||||
sys.excepthook = custom_except_hook
|
||||
sys.excepthook = custom_except_hook
|
@ -15,6 +15,7 @@ class AppLaunchException(Exception):
|
||||
...
|
||||
|
||||
|
||||
|
||||
class Application(IPCServer):
|
||||
""" docstring for Application. """
|
||||
|
||||
@ -30,7 +31,7 @@ class Application(IPCServer):
|
||||
message = f"FILE|{arg}"
|
||||
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()
|
||||
Window(args, unknownargs)
|
||||
@ -56,4 +57,4 @@ class Application(IPCServer):
|
||||
)
|
||||
except ValueError:
|
||||
# Typically: ValueError: signal only works in main thread
|
||||
...
|
||||
...
|
@ -6,9 +6,8 @@ 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
|
||||
from .header_container import HeaderContainer
|
||||
from .body_container import BodyContainer
|
||||
|
||||
|
||||
|
||||
@ -38,12 +37,11 @@ class BaseContainer(Gtk.Box):
|
||||
event_system.subscribe("remove_transparency", self._remove_transparency)
|
||||
|
||||
def _load_widgets(self):
|
||||
self.add(LeftContainer())
|
||||
self.add(CenterContainer())
|
||||
self.add(RightContainer())
|
||||
self.add(HeaderContainer())
|
||||
self.add(BodyContainer())
|
||||
|
||||
def _update_transparency(self):
|
||||
self.ctx.add_class(f"mw_transparency_{settings.theming.transparency}")
|
||||
|
||||
def _remove_transparency(self):
|
||||
self.ctx.remove_class(f"mw_transparency_{settings.theming.transparency}")
|
||||
self.ctx.remove_class(f"mw_transparency_{settings.theming.transparency}")
|
44
src/core/containers/body_container.py
Normal file
44
src/core/containers/body_container.py
Normal 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())
|
@ -6,7 +6,7 @@ gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
from ..widgets.transparency_scale import TransparencyScale
|
||||
|
||||
|
||||
|
||||
class CenterContainer(Gtk.Box):
|
||||
@ -35,21 +35,12 @@ class CenterContainer(Gtk.Box):
|
||||
|
||||
def _load_widgets(self):
|
||||
glade_box = self._builder.get_object("glade_box")
|
||||
glade_box = self._builder.get_object("glade_box")
|
||||
button = Gtk.Button(label = "Interactive Debug")
|
||||
button2 = Gtk.Button(label = "Click Me!")
|
||||
button = Gtk.Button(label = "Click Me!")
|
||||
|
||||
button.connect("clicked", self._interactive_debug)
|
||||
button2.connect("clicked", self._hello_world)
|
||||
button.connect("clicked", self._hello_world)
|
||||
|
||||
self.add(TransparencyScale())
|
||||
self.add(button)
|
||||
self.add(button2)
|
||||
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):
|
||||
logger.debug("Hello, World!")
|
||||
logger.debug("Hello, World!")
|
46
src/core/containers/header_container.py
Normal file
46
src/core/containers/header_container.py
Normal 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")
|
@ -26,7 +26,7 @@ class TransparencyScale(Gtk.Scale):
|
||||
self.set_digits(0)
|
||||
self.set_value_pos(Gtk.PositionType.RIGHT)
|
||||
self.add_mark(50.0, Gtk.PositionType.TOP, "50%")
|
||||
|
||||
self.set_hexpand(True)
|
||||
|
||||
def _setup_signals(self):
|
||||
self.connect("value-changed", self._update_transparency)
|
||||
@ -45,4 +45,4 @@ class TransparencyScale(Gtk.Scale):
|
||||
event_system.emit("remove_transparency")
|
||||
tp = int(range.get_value())
|
||||
settings.theming.transparency = tp
|
||||
event_system.emit("update_transparency")
|
||||
event_system.emit("update_transparency")
|
38
src/utils/db.py
Normal file
38
src/utils/db.py
Normal 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)
|
@ -2,7 +2,7 @@
|
||||
from typing import Optional
|
||||
|
||||
# Lib imports
|
||||
from sqlmodel import Field, Session, SQLModel, create_engine
|
||||
from sqlmodel import SQLModel, Field
|
||||
|
||||
# Application imports
|
||||
|
||||
@ -13,13 +13,3 @@ class User(SQLModel, table = True):
|
||||
name: str
|
||||
password: str
|
||||
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
Block a user