@@ 2,6 2,7 @@ from gi.repository import Gio
from gi.repository import GObject
from gi.repository import Gtk
from gi.repository import Adw
+from gi.repository import Notify
from . import local
from . import models
@@ 13,7 14,7 @@ from .widgets import PageHeaderBar
from .pages import PageInfo
from .pages import PageList
from .pages import PageDetails
-
+from .utils import clean_markup
@Gtk.Template(resource_path="/net/kirgroup/confy/mainwindow.ui")
class MainWindow(Adw.ApplicationWindow):
@@ 68,6 69,13 @@ class MainWindow(Adw.ApplicationWindow):
self.emit("conf-updated")
self.show_main()
+ self.notifications = {}
+ # Check if there are notifications to send
+ Gio.Application.get_default().connect(
+ 'tick', self.check_event_notification
+ )
+ self.check_event_notification()
+
def _init_pages(self):
for p in self.main_stack.get_pages():
child = p.get_child()
@@ 92,6 100,41 @@ class MainWindow(Adw.ApplicationWindow):
def _on_fetcher_error(self, fetcher, error):
self.show_error(error)
+ def check_event_notification(self, *args):
+ nextup = list(models.Event.nextup(5))
+ for e in nextup:
+ # fast and stupid clean html
+ #cleanr = re.compile('<.*?>|&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-f]{1,6});')
+ #title = re.sub(cleanr, '', e.title)
+ title = clean_markup(e.title)
+ self._send_desktop_notification(
+ _("Next up: {}").format(title),
+ _("at {} in {}").format(
+ e.start_in_tz().strftime("%H:%M"),
+ e.room
+ ),
+ f"nextup-{e.id}")
+ e.set_notified(True)
+
+ def _send_desktop_notification(self, title, body, nid=None):
+ n = Notify.Notification.new(title, body, APP_ID)
+ n.set_timeout(Notify.EXPIRES_NEVER)
+ n.add_action("view", "View", self.on_notification_action, nid)
+ n.show()
+ self.notifications[nid] = n
+
+ def on_notification_action(self, notification, action, data):
+ print(notification, action, data)
+ if action == "view" and data.startswith("nextup-"):
+ eventid = int(data.split("-")[1])
+ event = models.Event.by_id(eventid)
+ # if we are not on "events" subpage, force it as non navigatable,
+ # we want to be back to we were
+ print(self.subpage_leaflet.get_visible_child(), self.subpage_events)
+ can_we_go_back_to_events = self.subpage_leaflet.get_visible_child() == self.subpage_events
+ self.show_details(event, can_we_go_back_to_events)
+
+
def show_loader(self):
self.loader_stack.set_visible_child_name("loader")
@@ 114,13 157,6 @@ class MainWindow(Adw.ApplicationWindow):
@Gtk.Template.Callback()
def _on_page_changed(self, *_):
- # Quindi. Quando la pagina cambia su "starred"
- # imposto "subpage_events" come non "navigatable"
- # così quando l'utente sceglie un evento preferito, viene mandato a
- # "subpage_details", e quando naviga indietro torna a "leaflet"
- is_events_navigatable = self.main_stack.get_visible_child_name() != "starred"
- self.subpage_leaflet.get_page(self.subpage_events).set_navigatable(is_events_navigatable)
-
self.set_pageheader_title()
self.show_stack()
@@ 149,6 185,22 @@ class MainWindow(Adw.ApplicationWindow):
def show_search_all(self):
self.subpage_leaflet.get_page(self.subpage_events).set_navigatable(False)
self.subpage_leaflet.get_page(self.subpage_details).set_navigatable(False)
+
+ def show_details(self, event, is_events_navigatable=None):
+ # Se sono sulla pagina "starred"
+ # imposto "subpage_events" come non "navigatable"
+ # così quando l'utente sceglie un evento preferito, viene mandato a
+ # "subpage_details", e quando naviga indietro torna a "leaflet".
+ #
+ # A meno che non ci sia impostato 'is_events_navigatable' come paramentro,
+ # nel qual caso, vince lui.
+ if is_events_navigatable is None:
+ is_events_navigatable = self.main_stack.get_visible_child_name() != "starred"
+ self.subpage_leaflet.get_page(self.subpage_events).set_navigatable(is_events_navigatable)
+
+ self.subpage_details.set_obj(event)
+ self.show_subpage_details()
+
@Gtk.Template.Callback()
def _on_pagelist_row_activated(self, page):
self.subpage_events.set_model(page.get_model())
@@ 157,6 209,4 @@ class MainWindow(Adw.ApplicationWindow):
@Gtk.Template.Callback()
def _on_event_row_activated(self, page):
- self.subpage_details.set_obj(page.get_value())
- self.show_subpage_details()
-
+ self.show_details(page.get_value())
@@ 25,6 25,11 @@ from . import local
from .settings import Settings
from .fetcher import Fetcher
+
+class ObjectNotFound(Exception):
+ pass
+
+
## models
def _build_filter(day=None, room=None, track=None, event=None, **kwargs):
filterdata = []
@@ 398,6 403,13 @@ class Event(GObject.GObject):
yield cls()._init(row)
@classmethod
+ def by_id(cls, id):
+ row = local.getDb().execute("SELECT * FROM events WHERE id = ?", (id,)).fetchone()
+ if row is None:
+ raise ObjectNotFound("<{} #{}>".format(cls.__name__, id))
+ return cls()._init(row)
+
+ @classmethod
def filter(cls, day:Day = None, room:Room = None, track:Track = None, **kwargs):
filterdata, wherestm = _build_filter(day=day, room=room, track=track, **kwargs)