ungana

Unnamed repository; edit this file 'description' to name the repository.
Info | Log | Files | Refs | README

commit 77c97cda7c28dad92778e46a85dc36eccaee0547
parent 1a67eb53a015f59e1d5af04c31af5a44ce39871a
Author: lash <dev@holbrook.no>
Date:   Sun, 31 Aug 2025 21:58:21 +0100

Introduce config, move gui to package

Diffstat:
Dgui/base.py | 166-------------------------------------------------------------------------------
Mpyproject.toml | 8+++++++-
Aungana/config.py | 9+++++++++
Aungana/data/config.ini | 3+++
Aungana/gui/base.py | 189+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 208 insertions(+), 167 deletions(-)

diff --git a/gui/base.py b/gui/base.py @@ -1,166 +0,0 @@ -import sys -import logging -import gettext -import markdown - -import gi -gi.require_version('Gtk', '4.0') -gi.require_version('Adw', '1') -from gi.repository import Gtk, Adw, Gio - -from ungana.ical import ICalManager - -logging.basicConfig(level=logging.DEBUG) -logg = logging.getLogger() - -_ = gettext.gettext - -menu_src = """ -<?xml version="1.0" encoding="UTF-8"?> -<interface> -<menu id="menubar"> - <submenu> - <attribute name="label" translatable="yes">Edit</attribute> - <section> - <item> - <attribute name="action">win.settings</attribute> - <attribute name="target">Settings</attribute> - <attribute name="label" translatable="yes">Settings</attribute> - </item> - </section> - </submenu> -</menu> -</interface> -""" - -class MainWindow(Gtk.ApplicationWindow): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - self.props.show_menubar = True - self.cal = None - self.box_main = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) - self.set_child(self.box_main) - - title = Gtk.Label(label="UUID") - self.box_main.append(title) - entry = Gtk.Entry() - entry.set_editable(False) - entry.set_sensitive(False) - self.entry_uuid = entry - self.box_main.append(entry) - - title = Gtk.Label(label="Domain") - self.box_main.append(title) - entry = Gtk.Entry() - self.entry_domain = entry - self.box_main.append(entry) - - title = Gtk.Label(label="Summary") - self.box_main.append(title) - entry = Gtk.Entry() - self.entry_summary = entry - self.box_main.append(entry) - - title = Gtk.Label(label="Description") - self.box_main.append(title) - entry = Gtk.Entry() - self.box_main.append(entry) - - title = Gtk.Label(label="Start") - self.box_main.append(title) - entry = Gtk.Entry(placeholder_text="YYYY-MM-DD HH:MM") - self.box_main.append(entry) - - title = Gtk.Label(label="Duration") - self.box_main.append(title) - entry = Gtk.Entry(placeholder_text="") - self.box_main.append(entry) - - title = Gtk.Label(label="Banner") - self.box_main.append(title) - - - fltr = Gtk.FileFilter() - fltr.set_name("Images") - fltr.add_mime_type("image/*") - fltrs = Gio.ListStore.new(Gtk.FileFilter) - fltrs.append(fltr) - self.filedialog = Gtk.FileDialog.new() - self.filedialog.set_filters(fltrs) - self.filedialog.set_default_filter(fltr) - - img = Gtk.Image() - self.img = img - self.box_main.append(img) - self.img.set_size_request(0, 200) - - entry = Gtk.Button(label="Open") - entry.connect('clicked', self.show_open_dialog) - self.box_main.append(entry) - - self.status = Gtk.Statusbar() - self.box_main.append(self.status) - - - def show_open_dialog(self, button): - self.filedialog.open(self, None, self.open_dialog_callback) - - - def open_dialog_callback(self, dialog, result): - try: - f = dialog.open_finish(result) - if f is not None: - self.img.set_from_file(f.get_path()) - except GLib.Error as e: - logg.error("error open: {}".format(e)) - - def load(self, fp): - self.cal = ICalManager() - self.cal.load_ical_file(fp) - ev = self.cal.get_first_event(self.cal.calendar) - - v = ev.get('summary') - self.entry_summary.set_text(v) - - v = ev.get('uid') - (uid, domain) = v.split('@') - self.entry_uuid.set_text(uid) - self.entry_domain.set_text(domain) - - status_id = self.status.get_context_id("ical") - self.status.push(status_id, "{} {:s}: {}@{}".format(_("Loaded event from ical file"), fp, uid, domain)) - - -class Ungana(Adw.Application): - def __init__(self, initial_calendar=None, *args, **kwargs): - super().__init__(flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE, **kwargs) - self.file = initial_calendar - self.win = None - self.connect('activate', self.on_activate) - - def do_startup(self): - Adw.Application.do_startup(self) - builder = Gtk.Builder.new_from_string(menu_src, -1) - self.set_menubar(builder.get_object("menubar")) - - - def on_activate(self, app): - logg.debug("activate") - self.win = MainWindow(application=app) - self.win.load(self.file) - self.win.present() - - - def do_command_line(self, cli): - o = cli.get_options_dict() - logg.debug(o) - self.activate() - return 0 - - -#gettext.install(gettext.translation("ungana", localedir="locale", languages=['es'])) -gettext.bindtextdomain("messages", "locales") -gettext.textdomain("messages") -app = Ungana(application_id="org.defalsify.ungana", initial_calendar=sys.argv[1]) -app.run(sys.argv) diff --git a/pyproject.toml b/pyproject.toml @@ -8,7 +8,8 @@ version = "0.1.0" description = "Client application that creates customized .ics files for ticket booking and event reservations" requires-python = ">=3.8" dependencies = [ - "icalendar>=5.0.0", + "icalendar>=5.0.0", + "confini~=0.6.5", ] [project.optional-dependencies] @@ -23,3 +24,8 @@ ungana = "ungana.runnable.ungana_cal_cli:main" [tool.setuptools.packages.find] where = ["."] include = ["ungana*"] + +[tool.setuptools.package-data] +ungana = [ + "ungana/data/*" +] diff --git a/ungana/config.py b/ungana/config.py @@ -0,0 +1,9 @@ +import os +import confini + +__datadir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data") + +def load(): + cfg = confini.Config(__datadir) + cfg.process() + return cfg diff --git a/ungana/data/config.ini b/ungana/data/config.ini @@ -0,0 +1,3 @@ +[base] +domain = nondominium.org +zone = America/El_Salvador diff --git a/ungana/gui/base.py b/ungana/gui/base.py @@ -0,0 +1,189 @@ +import sys +import logging +import gettext +import zoneinfo + +import markdown +import gi +gi.require_version('Gtk', '4.0') +gi.require_version('Adw', '1') +from gi.repository import Gtk, Adw, Gio + +from ungana.ical import ICalManager +from ungana.config import load as load_config + +logging.basicConfig(level=logging.DEBUG) +logg = logging.getLogger() + +_ = gettext.gettext + +menu_src = """ +<?xml version="1.0" encoding="UTF-8"?> +<interface> +<menu id="menubar"> + <submenu> + <attribute name="label" translatable="yes">Edit</attribute> + <section> + <item> + <attribute name="action">win.settings</attribute> + <attribute name="target">Settings</attribute> + <attribute name="label" translatable="yes">Settings</attribute> + </item> + </section> + </submenu> +</menu> +</interface> +""" + +class MainWindow(Gtk.ApplicationWindow): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.props.show_menubar = True + self.cal = None + self.box_main = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) + self.set_child(self.box_main) + + title = Gtk.Label(label="UUID") + self.box_main.append(title) + entry = Gtk.Entry() + entry.set_editable(False) + entry.set_sensitive(False) + self.entry_uuid = entry + self.box_main.append(entry) + + title = Gtk.Label(label="Domain") + self.box_main.append(title) + entry = Gtk.Entry() + self.entry_domain = entry + self.box_main.append(entry) + + title = Gtk.Label(label="Summary") + self.box_main.append(title) + entry = Gtk.Entry() + self.entry_summary = entry + self.box_main.append(entry) + + title = Gtk.Label(label="Description") + self.box_main.append(title) + entry = Gtk.Entry() + self.box_main.append(entry) + + title = Gtk.Label(label="Time zone") + self.box_main.append(title) + entry = Gtk.DropDown() + entry.set_enable_search(True) + zones = Gtk.StringList() + entry.props.model = zones + zonedata = zoneinfo.available_timezones() + i = 0 + for v in sorted(zonedata): + zones.append(v) + if v == self.get_application().cfg.get('BASE_ZONE'): + entry.props.selected = i + logg.debug("timezone default: {}".format(v)) + i += 1 + self.box_main.append(entry) + + title = Gtk.Label(label="Start") + self.box_main.append(title) + entry = Gtk.Entry(placeholder_text="YYYY-MM-DD HH:MM") + self.box_main.append(entry) + + title = Gtk.Label(label="Duration") + self.box_main.append(title) + entry = Gtk.Entry(placeholder_text="") + self.box_main.append(entry) + + title = Gtk.Label(label="Banner") + self.box_main.append(title) + + + fltr = Gtk.FileFilter() + fltr.set_name("Images") + fltr.add_mime_type("image/*") + fltrs = Gio.ListStore.new(Gtk.FileFilter) + fltrs.append(fltr) + self.filedialog = Gtk.FileDialog.new() + self.filedialog.set_filters(fltrs) + self.filedialog.set_default_filter(fltr) + + img = Gtk.Image() + self.img = img + self.box_main.append(img) + self.img.set_size_request(0, 200) + + entry = Gtk.Button(label="Open") + entry.connect('clicked', self.show_open_dialog) + self.box_main.append(entry) + + self.status = Gtk.Statusbar() + self.box_main.append(self.status) + + + def show_open_dialog(self, button): + self.filedialog.open(self, None, self.open_dialog_callback) + + + def open_dialog_callback(self, dialog, result): + try: + f = dialog.open_finish(result) + if f is not None: + self.img.set_from_file(f.get_path()) + except GLib.Error as e: + logg.error("error open: {}".format(e)) + + def load(self, fp): + self.cal = ICalManager() + self.cal.load_ical_file(fp) + ev = self.cal.get_first_event(self.cal.calendar) + + v = ev.get('summary') + self.entry_summary.set_text(v) + + v = ev.get('uid') + (uid, domain) = v.split('@') + self.entry_uuid.set_text(uid) + self.entry_domain.set_text(domain) + + status_id = self.status.get_context_id("ical") + self.status.push(status_id, "{} {:s}: {}@{}".format(_("Loaded event from ical file"), fp, uid, domain)) + + +class Ungana(Adw.Application): + def __init__(self, initial_calendar=None, *args, **kwargs): + super().__init__(flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE, **kwargs) + self.file = initial_calendar + self.win = None + self.cfg = None + self.connect('activate', self.on_activate) + + + def do_startup(self): + Adw.Application.do_startup(self) + builder = Gtk.Builder.new_from_string(menu_src, -1) + self.set_menubar(builder.get_object("menubar")) + + + def on_activate(self, app): + logg.debug("activate") + self.win = MainWindow(application=app) + self.win.load(self.file) + self.win.present() + + + def do_command_line(self, cli): + o = cli.get_options_dict() + logg.debug(o) + self.cfg = load_config() + for k in self.cfg.all(): + logg.debug("config {} => {}".format(k, self.cfg.get(k))) + self.activate() + return 0 + + +#gettext.install(gettext.translation("ungana", localedir="locale", languages=['es'])) +gettext.bindtextdomain("messages", "locales") +gettext.textdomain("messages") +app = Ungana(application_id="org.defalsify.ungana", initial_calendar=sys.argv[1]) +app.run(sys.argv)