ungana

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

commit 7e07000abbaed9c1b1ff72fd5f4f2300ffc46b47
parent 77c97cda7c28dad92778e46a85dc36eccaee0547
Author: lash <dev@holbrook.no>
Date:   Sun, 31 Aug 2025 22:07:51 +0100

Separate runner from gui module

Diffstat:
Aungana/gui/__init__.py | 1+
Dungana/gui/base.py | 189-------------------------------------------------------------------------------
Aungana/gui/main.py | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aungana/gui/win.py | 129+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aungana/i18n.py | 6++++++
Aungana/runnable/gui.py | 11+++++++++++
6 files changed, 209 insertions(+), 189 deletions(-)

diff --git a/ungana/gui/__init__.py b/ungana/gui/__init__.py @@ -0,0 +1 @@ +from .main import UnganaGui diff --git a/ungana/gui/base.py b/ungana/gui/base.py @@ -1,189 +0,0 @@ -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) diff --git a/ungana/gui/main.py b/ungana/gui/main.py @@ -0,0 +1,62 @@ +import logging + +import gi +gi.require_version('Gtk', '4.0') +gi.require_version('Adw', '1') +from gi.repository import Gtk, Adw, Gio + +from ungana.config import load as load_config +from .win import MainWindow + +logg = logging.getLogger("gui.app") + +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 UnganaGui(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 + diff --git a/ungana/gui/win.py b/ungana/gui/win.py @@ -0,0 +1,129 @@ +import logging +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.i18n import _ +from ungana.ical import ICalManager + +logg = logging.getLogger("gui.win") + +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)) + + diff --git a/ungana/i18n.py b/ungana/i18n.py @@ -0,0 +1,6 @@ +import gettext + +gettext.bindtextdomain("messages", "locales") +gettext.textdomain("messages") + +_ = gettext.gettext diff --git a/ungana/runnable/gui.py b/ungana/runnable/gui.py @@ -0,0 +1,11 @@ +import sys +import logging + +from ungana.gui import UnganaGui + +logging.basicConfig(level=logging.DEBUG) + + +#gettext.install(gettext.translation("ungana", localedir="locale", languages=['es'])) +app = UnganaGui(application_id="org.defalsify.ungana", initial_calendar=sys.argv[1]) +app.run(sys.argv)