diff cagou/core/cagou_main.py @ 250:ff1efdeff53f

core: notifs can now have a custom icon and be clickable: - new host.doAction method, to open a specific widget/target (chat only for now) - when adding a notif, symbol can now be specified - an action can be linked to a notification - notifs design improvments - plugins contact list and chat use the new doAction/notif action - if None is given as old widget in SwitchWidget, the new getWidgetToSwitch method is used to select one to switch.
author Goffi <goffi@goffi.org>
date Sat, 26 Jan 2019 20:24:48 +0100
parents 5d69e4cab925
children 4601793b0dee
line wrap: on
line diff
--- a/cagou/core/cagou_main.py	Sat Jan 26 20:24:48 2019 +0100
+++ b/cagou/core/cagou_main.py	Sat Jan 26 20:24:48 2019 +0100
@@ -54,6 +54,7 @@
 from kivy.uix.screenmanager import (ScreenManager, Screen,
                                     FallOutTransition, RiseInTransition)
 from kivy.uix.dropdown import DropDown
+from kivy.uix.behaviors import ButtonBehavior
 from kivy.core.window import Window
 from kivy.animation import Animation
 from kivy.metrics import dp
@@ -104,13 +105,21 @@
     message = properties.StringProperty()
     level = properties.OptionProperty(C.XMLUI_DATA_LVL_DEFAULT,
                                       options=list(C.XMLUI_DATA_LVLS))
+    symbol = properties.StringProperty()
+    action = properties.ObjectProperty()
 
 
-class NoteDrop(BoxLayout):
+class NoteDrop(ButtonBehavior, BoxLayout):
     title = properties.StringProperty()
     message = properties.StringProperty()
     level = properties.OptionProperty(C.XMLUI_DATA_LVL_DEFAULT,
                                       options=list(C.XMLUI_DATA_LVLS))
+    symbol = properties.StringProperty()
+    action = properties.ObjectProperty()
+
+    def on_press(self):
+        if self.action is not None:
+            self.parent.parent.select(self.action)
 
 
 class NotesDrop(DropDown):
@@ -123,10 +132,24 @@
     def open(self, widget):
         self.clear_widgets()
         for n in self.notes:
-            self.add_widget(NoteDrop(title=n.title, message=n.message, level=n.level))
+            kwargs = {
+                u'title': n.title,
+                u'message': n.message,
+                u'level': n.level
+            }
+            if n.symbol is not None:
+                kwargs[u'symbol'] = n.symbol
+            if n.action is not None:
+                kwargs[u'action'] = n.action
+            self.add_widget(NoteDrop(title=n.title, message=n.message, level=n.level,
+                                     symbol=n.symbol, action=n.action))
         self.add_widget(self.clear_btn)
         super(NotesDrop, self).open(widget)
 
+    def on_select(self, action_kwargs):
+        app = App.get_running_app()
+        app.host.doAction(**action_kwargs)
+
 
 class RootHeadWidget(BoxLayout):
     """Notifications widget"""
@@ -149,8 +172,17 @@
         """
         self.notifs_icon.addNotif(callback, *args, **kwargs)
 
-    def addNote(self, title, message, level):
-        note = Note(title=title, message=message, level=level)
+    def addNote(self, title, message, level, symbol, action):
+        kwargs = {
+            u'title': title,
+            u'message': message,
+            u'level': level
+        }
+        if symbol is not None:
+            kwargs[u'symbol'] = symbol
+        if action is not None:
+            kwargs[u'action'] = action
+        note = Note(**kwargs)
         self.notes.append(note)
         if self.notes_event is None:
             self.notes_event = Clock.schedule_interval(self._displayNextNote, 5)
@@ -237,8 +269,8 @@
         """Add a notification for an action"""
         self.head_widget.addNotif(handler, action_data, id_, security_limit, profile)
 
-    def addNote(self, title, message, level):
-        self.head_widget.addNote(title, message, level)
+    def addNote(self, title, message, level, symbol, action):
+        self.head_widget.addNote(title, message, level, symbol, action)
 
     def addNotifUI(self, ui):
         self.head_widget.addNotifUI(ui)
@@ -662,9 +694,12 @@
     def switchWidget(self, old, new):
         """Replace old widget by new one
 
-        old(CagouWidget): CagouWidget instance or a child
+        old(CagouWidgetn None): CagouWidget instance or a child
+            None to select automatically widget to switch
         new(CagouWidget): new widget instance
         """
+        if old is None:
+            old = self.getWidgetToSwitch()
         to_change = None
         if isinstance(old, CagouWidget):
             to_change = old
@@ -730,6 +765,42 @@
             w.addTarget(t)
         return w
 
+    def getWidgetToSwitch(self):
+        """Choose best candidate when we need to switch widget and old is not specified
+
+        @return (CagouWidget): widget to switch
+        """
+        if self.selected_widget is not None:
+            return self.selected_widget
+        # no widget is selected we check if we have any default widget
+        default_cls = self.default_wid['main']
+        for w in self.visible_widgets:
+            if isinstance(w, default_cls):
+                return w
+
+        # no default widget found, we return the first widget
+        return next(iter(self.visible_widgets))
+
+    def doAction(self, action, target, profiles):
+        """Launch an action handler by a plugin
+
+        @param action(unicode): action to do, can be:
+            - chat: open a chat widget
+        @param target(unicode): target of the action
+        @param profiles(list[unicode]): profiles to use
+        """
+        try:
+            # FIXME: Q&D way to get chat plugin, should be replaced by a clean method
+            #        in host
+            plg_infos = [p for p in self.getPluggedWidgets()
+                         if action in p['import_name']][0]
+        except IndexError:
+            log.warning(u"No plugin widget found to do {action}".format(action=action))
+        else:
+            factory = plg_infos['factory']
+            self.switchWidget(None,
+                factory(plg_infos, target=target, profiles=profiles))
+
     ## menus ##
 
     def _menusGetCb(self, backend_menus):
@@ -766,9 +837,10 @@
                 message=_(u'error while processing: {msg}')):
         self.addNote(title, message.format(msg=failure_), level=C.XMLUI_DATA_LVL_WARNING)
 
-    def addNote(self, title, message, level=C.XMLUI_DATA_LVL_INFO):
+    def addNote(self, title, message, level=C.XMLUI_DATA_LVL_INFO, symbol=None,
+        action=None):
         """add a note (message which disappear) to root widget's header"""
-        self.app.root.addNote(title, message, level)
+        self.app.root.addNote(title, message, level, symbol, action)
 
     def addNotifUI(self, ui):
         """add a notification with a XMLUI attached