changeset 33:c21d1be2e54c

core: XMLUI notifications coming from backend are handled: when a notification from backend is coming, it's added to a notification icon (on the right for important notifications which need user action, while left icon is used for notes). If user click on the notification icon, the XMLUI replace the main widget with a rise animation. When action is finished, ui is closed with a fall out animation.
author Goffi <goffi@goffi.org>
date Sun, 21 Aug 2016 21:41:52 +0200
parents fdaf914e2729
children 02acbb297a61
files src/cagou/core/cagou_main.py src/cagou/core/xmlui.py src/cagou/kv/root_widget.kv
diffstat 3 files changed, 62 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/src/cagou/core/cagou_main.py	Sun Aug 21 17:49:14 2016 +0200
+++ b/src/cagou/core/cagou_main.py	Sun Aug 21 21:41:52 2016 +0200
@@ -39,7 +39,7 @@
 from kivy.clock import Clock
 from kivy.uix.label import Label
 from kivy.uix.boxlayout import BoxLayout
-from kivy.uix.screenmanager import ScreenManager, Screen
+from kivy.uix.screenmanager import ScreenManager, Screen, FallOutTransition, RiseInTransition
 from kivy.uix.dropdown import DropDown
 from cagou_widget import CagouWidget
 from .common import IconButton
@@ -50,16 +50,15 @@
 import cagou.kv
 
 
-class NotifIcon(IconButton):
-
-    def __init__(self, callback, callback_args):
-        self._callback = callback
-        self._callback_args = callback_args
-        super(NotifIcon, self).__init__()
+class NotifsIcon(IconButton):
+    notifs = properties.ListProperty()
 
     def on_release(self):
-        self.parent.remove_widget(self)
-        self._callback(*self._callback_args)
+        callback, args, kwargs = self.notifs.pop(0)
+        callback(*args, **kwargs)
+
+    def addNotif(self, callback, *args, **kwargs):
+        self.notifs.append((callback, args, kwargs))
 
 
 class Note(Label):
@@ -90,17 +89,17 @@
 class RootHeadWidget(BoxLayout):
     """Notifications widget"""
     manager = properties.ObjectProperty()
+    notifs_icon = properties.ObjectProperty()
     notes = properties.ListProperty()
 
     def __init__(self):
         super(RootHeadWidget, self).__init__()
         self.notes_last = None
         self.notes_event = None
-        self.notes_drop = NotesDrop(self.notes) # auto_with=False, width=100)
+        self.notes_drop = NotesDrop(self.notes)
 
-    def addNotif(self, callback, *args):
-        icon = NotifIcon(callback, args)
-        self.add_widget(icon)
+    def addNotif(self, callback, *args, **kwargs):
+        self.notifs_icon.addNotif(callback, *args, **kwargs)
 
     def addNote(self, title, message, level):
         note = Note(title=title, message=message, level=level)
@@ -111,6 +110,9 @@
             self.notes_event = Clock.schedule_interval(self._displayNextNote, 5)
             self._displayNextNote()
 
+    def addNotifUI(self, ui):
+        self.notifs_icon.addNotif(ui.show, force=True)
+
     def _displayNextNote(self, dummy=None):
         screen = Screen()
         try:
@@ -137,17 +139,29 @@
 
         # body
         self._manager = ScreenManager()
+        # main widgets
         main_screen = Screen(name='main')
         main_screen.add_widget(main_widget)
         self._manager.add_widget(main_screen)
+        # backend XMLUI (popups, forms, etc)
+        xmlui_screen = Screen(name='xmlui')
+        self._manager.add_widget(xmlui_screen)
         self.add_widget(self._manager)
-        self.change_widget(main_widget)
 
-    def change_widget(self, main_widget, screen="main"):
+    def changeWidget(self, widget, screen_name="main"):
         """change main widget"""
-        main_screen = self._manager.get_screen(screen)
-        main_screen.clear_widgets()
-        main_screen.add_widget(main_widget)
+        screen = self._manager.get_screen(screen_name)
+        screen.clear_widgets()
+        screen.add_widget(widget)
+
+    def show(self, screen="main"):
+        if self._manager.current == screen:
+            return
+        if screen == "main":
+            self._manager.transition = FallOutTransition()
+        else:
+            self._manager.transition = RiseInTransition()
+        self._manager.current = screen
 
     def newAction(self, handler, action_data, id_, security_limit, profile):
         """Add a notification for an action"""
@@ -156,6 +170,9 @@
     def addNote(self, title, message, level):
         self._head_widget.addNote(title, message, level)
 
+    def addNotifUI(self, ui):
+        self._head_widget.addNotifUI(ui)
+
 
 class CagouApp(App):
     """Kivy App for Cagou"""
@@ -314,7 +331,7 @@
     ## misc ##
 
     def plugging_profiles(self):
-        self.app.root.change_widget(WidgetsHandler())
+        self.app.root.changeWidget(WidgetsHandler())
 
     def setPresenceStatus(self, show='', status=None, profile=C.PROF_KEY_NONE):
         log.info(u"Profile presence status set to {show}/{status}".format(show=show, status=status))
@@ -323,13 +340,16 @@
         """add a note (message which disappear) to root widget's header"""
         self.app.root.addNote(title, message, level)
 
-    ## signals handling ##
+    def addNotifUI(self, ui):
+        """add a notification with a XMLUI attached
+
+        @param ui(xmlui.XMLUIPanel): XMLUI instance to show when notification is selected
+        """
+        self.app.root.addNotifUI(ui)
 
-    def actionNewHandler(self, action_data, id_, security_limit, profile):
-        handler = super(Cagou, self).actionNewHandler
-        # FIXME: temporarily deactivated
-        # if 'xmlui' in action_data:
-        #     self.app.root.newAction(handler, action_data, id_, security_limit, profile)
-        # else:
-        #     handler(action_data, id_, security_limit, profile)
-        handler(action_data, id_, security_limit, profile)
+    def showUI(self, ui):
+        self.app.root.changeWidget(ui, "xmlui")
+        self.app.root.show("xmlui")
+
+    def closeUI(self):
+        self.app.root.show()
--- a/src/cagou/core/xmlui.py	Sun Aug 21 17:49:14 2016 +0200
+++ b/src/cagou/core/xmlui.py	Sun Aug 21 21:41:52 2016 +0200
@@ -114,7 +114,7 @@
         if self.close_cb is not None:
             self.close_cb(self)
         else:
-            log.error(u"No close method defined")
+            G.host.closeUI()
 
     def constructUI(self, parsed_dom):
         xmlui.XMLUIPanel.constructUI(self, parsed_dom)
@@ -131,6 +131,12 @@
                 self.add_widget(cancel_btn)
         self.add_widget(Widget()) # to have elements on the top
 
+    def show(self, *args, **kwargs):
+        if not self.user_action and not kwargs.get("force", False):
+            G.host.addNotifUI(self)
+        else:
+            G.host.showUI(self)
+
 
 class XMLUIDialog(xmlui.XMLUIDialog):
     dialog_factory = WidgetFactory()
--- a/src/cagou/kv/root_widget.kv	Sun Aug 21 17:49:14 2016 +0200
+++ b/src/cagou/kv/root_widget.kv	Sun Aug 21 21:41:52 2016 +0200
@@ -49,6 +49,7 @@
 
 <RootHeadWidget>:
     manager: manager
+    notifs_icon: notifs_icon
     size_hint: 1, None
     height: 35
     IconButton:
@@ -58,3 +59,9 @@
         on_release: root.notes_drop.open(self) if root.notes else None
     ScreenManager:
         id: manager
+    NotifsIcon:
+        id: notifs_icon
+        source: app.expand("{media}/icons/muchoslava/png/cagou_profil_bleu_32.png") if self.notifs else app.expand("{media}/misc/black.png")
+        size_hint: None, 1
+        width: self.texture_size[0]
+