Mercurial > libervia-desktop-kivy
diff cagou/core/common.py @ 404:f7476818f9fb
core (common): JidSelector + behaviors various improvments:
- renamed *Behaviour => *Behavior to be consistent with Kivy + moved to new
"core.behaviors" modules
- use a dedicated property in ContactItem for notification counter (which is now named
"badge")
- in JidSelector, well-known strings now create use a dedicated layout, add separator
(except if new `add_separators` property is set to False), and are added to attribute of
the same name
- a new `item_class` property is now used to indicate the class to instanciate for items
(by default it's a ContactItem)
- FilterBahavior.do_filter now expect the parent layout instead of directly the children,
this is to allow a FilterBahavior to manage several children layout at once (used with
JidSelector)
- core.utils has been removed, as the behavior there has been moved to core.behaviors
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 12 Feb 2020 20:02:58 +0100 |
parents | 54f6a47cc60a |
children | 84ff5c917064 |
line wrap: on
line diff
--- a/cagou/core/common.py Wed Feb 12 20:02:58 2020 +0100 +++ b/cagou/core/common.py Wed Feb 12 20:02:58 2020 +0100 @@ -27,13 +27,15 @@ from kivy.uix.label import Label from kivy.uix.behaviors import ButtonBehavior from kivy.uix.behaviors import ToggleButtonBehavior +from kivy.uix.stacklayout import StackLayout from kivy.uix.boxlayout import BoxLayout from kivy.uix.scrollview import ScrollView from kivy.event import EventDispatcher from kivy.metrics import dp from kivy import properties from sat_frontends.quick_frontend import quick_chat -from cagou.core.constants import Const as C +from .constants import Const as C +from .common_widgets import CategorySeparator from cagou import G log = logging.getLogger(__name__) @@ -63,17 +65,26 @@ base_width = dp(150) avatar_layout = properties.ObjectProperty() avatar = properties.ObjectProperty() + badge = properties.ObjectProperty(allownone=True) + badge_text = properties.StringProperty('') profile = properties.StringProperty() data = properties.DictProperty() jid = properties.StringProperty('') - def on_kv_post(self, __): - if self.data and self.data.get('notifs'): - notif = NotifLabel( - pos_hint={"right": 0.8, "y": 0}, - text=str(len(self.data['notifs'])) - ) - self.avatar_layout.add_widget(notif) + def on_badge_text(self, wid, text): + if text: + if self.badge is not None: + self.badge.text = text + else: + self.badge = NotifLabel( + pos_hint={"right": 0.8, "y": 0}, + text=text, + ) + self.avatar_layout.add_widget(self.badge) + else: + if self.badge is not None: + self.avatar_layout.remove_widget(self.badge) + self.badge = None class ContactButton(ButtonBehavior, ContactItem): @@ -174,12 +185,25 @@ self.add_widget(icon_wid) +class JidSelectorCategoryLayout(StackLayout): + pass + + class JidSelector(ScrollView, EventDispatcher): layout = properties.ObjectProperty(None) + # if item_class is changed, the properties must be the same as for ContactButton + # and ordering must be supported + item_class = properties.ObjectProperty(ContactButton) + add_separators = properties.ObjectProperty(True) # list of item to show, can be: - # - a well-known string like: - # * "roster": to show all roster jids - # * "opened_chats": to show jids of all opened chat widgets + # - a well-known string which can be: + # * "roster": all roster jids + # * "opened_chats": all opened chat widgets + # * "bookmarks": MUC bookmarks + # A layout will be created each time and stored in the attribute of the same + # name. + # If add_separators is True, a CategorySeparator will be added on top of each + # layout. # - a kivy Widget, which will be added to the layout (notable useful with # common_widgets.CategorySeparator) # - a callable, which must return an iterable of kwargs for ContactButton @@ -190,6 +214,10 @@ def __init__(self, **kwargs): self.register_event_type('on_select') + # list of layouts containing items + self.items_layouts = [] + # jid to list of ContactButton instances map + self.items_map = {} super().__init__(**kwargs) def on_kv_post(self, wid): @@ -210,6 +238,13 @@ log.debug("onContactsFilled event received") self.update() + + def _createItem(self, **kwargs): + item = self.item_class(**kwargs) + jid = kwargs['jid'] + self.items_map.setdefault(jid, []).append(item) + return item + def update(self): log.debug("starting update") self.layout.clear_widgets() @@ -228,52 +263,69 @@ elif callable(item): items_kwargs = item() for item_kwargs in items_kwargs: - item = ContactButton(**item_kwargs) + item = self._createItem(**items_kwargs) item.bind(on_press=partial(self.dispatch, 'on_select')) self.layout.add_widget(item) else: log.error(f"unmanaged to_show item type: {item!r}") - def addOpenedChatsItems(self): - opened_chats = G.host.widgets.getWidgets( - quick_chat.QuickChat, - profiles = G.host.profiles) + def addCategoryLayout(self, label=None): + category_layout = JidSelectorCategoryLayout() + + if label and self.add_separators: + category_layout.add_widget(CategorySeparator(text=label)) + + self.layout.add_widget(category_layout) + self.items_layouts.append(category_layout) + return category_layout - for wid in opened_chats: - contact_list = G.host.contact_lists[wid.profile] - data=contact_list.getItem(wid.target) - notifs = list(G.host.getNotifs(wid.target, profile=wid.profile)) - if notifs: - # we shallow copy the dict to have the notification displayed only with - # opened chats (otherwise, the counter would appear on each other - # instance of ContactButton for this entity, i.e. in roster too). - data = data.copy() - data['notifs'] = notifs - try: - item = ContactButton( - jid=wid.target, - data=data, - profile=wid.profile, - ) - except Exception as e: - log.warning(f"Can't add contact {wid.target}: {e}") + def getItemFromWid(self, wid): + """create JidSelector item from QuickChat widget""" + contact_list = G.host.contact_lists[wid.profile] + data=contact_list.getItem(wid.target) + try: + item = self._createItem( + jid=wid.target, + data=data, + profile=wid.profile, + ) + except Exception as e: + log.warning(f"Can't add contact {wid.target}: {e}") + return + notifs = list(G.host.getNotifs(wid.target, profile=wid.profile)) + if notifs: + item.badge_text = str(len(notifs)) + item.bind(on_press=partial(self.dispatch, 'on_select')) + return item + + def addOpenedChatsItems(self): + self.opened_chats = category_layout = self.addCategoryLayout(_("Opened chats")) + widgets = sorted(G.host.widgets.getWidgets( + quick_chat.QuickChat, + profiles = G.host.profiles, + with_duplicates=False)) + + for wid in widgets: + item = self.getItemFromWid(wid) + if item is None: continue - item.bind(on_press=partial(self.dispatch, 'on_select')) - self.layout.add_widget(item) + category_layout.add_widget(item) def addRosterItems(self): + self.roster = category_layout = self.addCategoryLayout(_("Your contacts")) for profile in G.host.profiles: contact_list = G.host.contact_lists[profile] for entity_jid in sorted(contact_list.roster): - item = ContactButton( + item = self._createItem( jid=entity_jid, data=contact_list.getItem(entity_jid), profile=profile, ) item.bind(on_press=partial(self.dispatch, 'on_select')) - self.layout.add_widget(item) + category_layout.add_widget(item) def addBookmarksItems(self): + self.bookmarks = category_layout = self.addCategoryLayout(_("Your chat rooms")) for profile in G.host.profiles: profile_manager = G.host.profiles[profile] try: @@ -288,10 +340,10 @@ cache = contact_list.getItem(entity_jid) except KeyError: cache = {} - item = ContactButton( + item = self._createItem( jid=entity_jid, data=cache, profile=profile, ) item.bind(on_press=partial(self.dispatch, 'on_select')) - self.layout.add_widget(item) + category_layout.add_widget(item)