# HG changeset patch # User Goffi # Date 1548530688 -3600 # Node ID ff1efdeff53f355cdb91193028ac024c948e79d3 # Parent 5d69e4cab925a0cb1c22b1350ee2379f3f055a8f 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. diff -r 5d69e4cab925 -r ff1efdeff53f cagou/core/cagou_main.py --- 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 diff -r 5d69e4cab925 -r ff1efdeff53f cagou/kv/root_widget.kv --- a/cagou/kv/root_widget.kv Sat Jan 26 20:24:48 2019 +0100 +++ b/cagou/kv/root_widget.kv Sat Jan 26 20:24:48 2019 +0100 @@ -33,7 +33,7 @@ : orientation: 'horizontal' size_hint: 1, None - height: label.height + height: max(label.height, dp(45)) symbol: symbol canvas.before: BorderImage: @@ -45,14 +45,14 @@ width: dp(20) Symbol: id: symbol - size_hint: None, None + size_hint: None, 1 width: dp(30) - height: label.height padding_y: dp(10) valign: 'top' haligh: 'right' - symbol: root.level + symbol: root.symbol or root.level color: + C.COLOR_PRIM_LIGHT if root.symbol is None else \ {C.XMLUI_DATA_LVL_INFO: app.c_prim_light,\ C.XMLUI_DATA_LVL_WARNING: C.COLOR_WARNING,\ C.XMLUI_DATA_LVL_ERROR: C.COLOR_ERROR}[root.level] diff -r 5d69e4cab925 -r ff1efdeff53f cagou/plugins/plugin_wid_chat.py --- a/cagou/plugins/plugin_wid_chat.py Sat Jan 26 20:24:48 2019 +0100 +++ b/cagou/plugins/plugin_wid_chat.py Sat Jan 26 20:24:48 2019 +0100 @@ -527,14 +527,24 @@ if not is_visible: G.host.addNote( _(u"private message"), - notif_msg + notif_msg, + symbol = u"chat", + action = { + "action": u'chat', + "target": self.target, + "profiles": self.profiles} ) else: if mess_data.mention and not mess_data.history: notif_msg = self._get_notif_msg(mess_data) G.host.addNote( _(u"mention"), - notif_msg + notif_msg, + symbol = u"chat", + action = { + "action": u'chat', + "target": self.target, + "profiles": self.profiles} ) if not Window.focus: G.host.desktop_notif( diff -r 5d69e4cab925 -r ff1efdeff53f cagou/plugins/plugin_wid_contact_list.py --- a/cagou/plugins/plugin_wid_contact_list.py Sat Jan 26 20:24:48 2019 +0100 +++ b/cagou/plugins/plugin_wid_contact_list.py Sat Jan 26 20:24:48 2019 +0100 @@ -117,18 +117,7 @@ assert self.profile # XXX: for now clicking on an item launch the corresponding Chat widget # behaviour should change in the future - try: - # FIXME: Q&D way to get chat plugin, should be replaced by a clean method - # in host - plg_infos = [p for p in G.host.getPluggedWidgets() - if 'chat' in p['import_name']][0] - except IndexError: - log.warning(u"No plugin widget found to display chat") - else: - factory = plg_infos['factory'] - G.host.switchWidget(self, factory(plg_infos, - jid.JID(self.jid), - profiles=[self.profile])) + G.host.doAction(u'chat', jid.JID(self.jid), [self.profile]) def getMenuChoices(self): choices = []