# HG changeset patch # User Goffi # Date 1579283072 -3600 # Node ID 38fd457b2158b2a080ceaee15e395b111bc63808 # Parent bf9474e164f32e9d7c172f5e7d37d9579e41b682 core (common, share_widget): new JidSelector widget: - A widget to select jid among a list is commonly needed, so it has been implemented in core.common, based on the code from ShareWidget - ShareWidget has been adapted accordingly - new ContactButton class in core.common diff -r bf9474e164f3 -r 38fd457b2158 cagou/core/common.py --- a/cagou/core/common.py Sat Jan 04 16:24:57 2020 +0100 +++ b/cagou/core/common.py Fri Jan 17 18:44:32 2020 +0100 @@ -1,5 +1,4 @@ -#!/usr//bin/env python2 -# -*- coding: utf-8 -*- +#!/usr/bin/env python3 # Cagou: desktop/mobile frontend for Salut à Toi XMPP client # Copyright (C) 2016-2019 Jérôme Poisson (goffi@goffi.org) @@ -19,18 +18,21 @@ """common simple widgets""" +import json +from functools import partial from sat.core.i18n import _ +from sat.core import log as logging from kivy.uix.image import Image from kivy.uix.label import Label from kivy.uix.behaviors import ButtonBehavior from kivy.uix.behaviors import ToggleButtonBehavior from kivy.uix.boxlayout import BoxLayout +from kivy.uix.scrollview import ScrollView +from kivy.event import EventDispatcher from kivy.metrics import dp -from cagou.core.constants import Const as C from kivy import properties +from cagou.core.constants import Const as C from cagou import G -import json -from sat.core import log as logging log = logging.getLogger(__name__) @@ -46,12 +48,20 @@ class ContactItem(BoxLayout): + """An item from ContactList + + The item will drawn as an icon (JID avatar) with its jid below + """ base_width = dp(150) profile = properties.StringProperty() data = properties.DictProperty() jid = properties.StringProperty('') +class ContactButton(ButtonBehavior, ContactItem): + pass + + class JidItem(BoxLayout): bg_color = properties.ListProperty([0.2, 0.2, 0.2, 1]) color = properties.ListProperty([1, 1, 1, 1]) @@ -144,3 +154,42 @@ else: icon_wid = ActionSymbol(symbol=symbol) self.add_widget(icon_wid) + + +class JidSelector(ScrollView, EventDispatcher): + layout = properties.ObjectProperty(None) + + def __init__(self, **kwargs): + self.register_event_type('on_select') + super().__init__(**kwargs) + + def on_kv_post(self, wid): + self.addRosterContacts() + + def on_select(self, wid): + pass + + def on_parent(self, wid, parent): + if parent is None: + log.debug("removing contactsFilled listener") + G.host.removeListener("contactsFilled", self.onContactsFilled) + else: + G.host.addListener("contactsFilled", self.onContactsFilled) + + def onContactsFilled(self, profile): + log.debug("onContactsFilled event received") + self.addRosterContacts() + + def addRosterContacts(self): + log.debug("starting addRosterContacts") + self.layout.clear_widgets() + for profile in G.host.profiles: + contact_list = G.host.contact_lists[profile] + for entity_jid in sorted(contact_list.roster): + item = ContactButton( + 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) diff -r bf9474e164f3 -r 38fd457b2158 cagou/core/share_widget.py --- a/cagou/core/share_widget.py Sat Jan 04 16:24:57 2020 +0100 +++ b/cagou/core/share_widget.py Fri Jan 17 18:44:32 2020 +0100 @@ -1,5 +1,4 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- +#!/usr/bin/env python3 # Cagou: desktop/mobile frontend for Salut à Toi XMPP client # Copyright (C) 2016-2019 Jérôme Poisson (goffi@goffi.org) @@ -19,16 +18,15 @@ from pathlib import Path +from functools import partial from sat.core import log as logging from sat.core.i18n import _ from sat.tools.common import data_format from sat_frontends.tools import jid from kivy.uix.boxlayout import BoxLayout -from kivy.uix.behaviors import ButtonBehavior from kivy.properties import StringProperty, DictProperty, ObjectProperty from kivy.core.window import Window from kivy.metrics import dp -from .common import ContactItem from .constants import Const as C from cagou import G @@ -43,30 +41,6 @@ "icon_symbol": "share", } -class ShareContactItem(ButtonBehavior, ContactItem): - - def filterDataCb(self, data): - G.host.doAction('chat', jid.JID(self.jid), [self.profile]) - chat_wid = G.host.selected_widget - - if self.share_wid.type == 'text': - text = self.share_wid.data['text'] - chat_wid.message_input.text += text - else: - path = self.share_wid.data['path'] - chat_wid.transferFile(path, cleaning_cb=data.get('cleaning_cb')) - self.share_wid.close() - - def filterDataEb(self, failure_): - G.host.addNote( - _("file filter error"), - _("Can't apply filter to file: {msg}").format(msg=failure_), - level=C.XMLUI_DATA_LVL_ERROR) - - def on_press(self): - self.share_wid = G.host.getAncestorWidget(self, ShareWidget) - self.share_wid.getFilteredData(self.filterDataCb, self.filterDataEb) - class TextPreview(BoxLayout): """Widget previewing shared text""" @@ -126,11 +100,9 @@ media_type = StringProperty() data = DictProperty() preview_box = ObjectProperty() - layout = ObjectProperty() def __init__(self, **kwargs): super().__init__(**kwargs) - G.host.addListener("contactsFilled", self.onContactsFilled) Window.bind(on_keyboard=self.key_input) def on_kv_post(self, wid): @@ -141,34 +113,10 @@ self.preview_box.add_widget(ImagePreview(path=self.data['path'])) else: self.preview_box.add_widget(GenericPreview(path=self.data['path'])) - self.addRosterContacts() def close(self): G.host.closeUI() - def on_parent(self, wid, parent): - if parent is None: - log.debug("removing contactsFilled listener") - G.host.removeListener("contactsFilled", self.onContactsFilled) - - - def addRosterContacts(self): - log.debug("starting addRosterContacts") - self.layout.clear_widgets() - for profile in G.host.profiles: - contact_list = G.host.contact_lists[profile] - for entity_jid in sorted(contact_list.roster): - item = ShareContactItem( - jid=entity_jid, - data=contact_list.getItem(entity_jid), - profile=profile, - ) - self.layout.add_widget(item) - - def onContactsFilled(self, profile): - log.debug("onContactsFilled event received") - self.addRosterContacts() - def getFilteredData(self, callback, errback): """Apply filter if suitable, and call callback with with modified data""" try: @@ -179,6 +127,34 @@ filter_ = getFilter() filter_(self.data, callback=callback, errback=errback) + def filterDataCb(self, data, contact_jid, profile): + G.host.doAction('chat', contact_jid, [profile]) + chat_wid = G.host.selected_widget + + if self.type == 'text': + text = self.data['text'] + chat_wid.message_input.text += text + else: + path = self.data['path'] + chat_wid.transferFile(path, cleaning_cb=data.get('cleaning_cb')) + self.close() + + def filterDataEb(self, failure_): + G.host.addNote( + _("file filter error"), + _("Can't apply filter to file: {msg}").format(msg=failure_), + level=C.XMLUI_DATA_LVL_ERROR) + + def on_select(self, contact_button): + contact_jid = jid.JID(contact_button.jid) + self.getFilteredData( + partial( + self.filterDataCb, + contact_jid=contact_jid, + profile=contact_button.profile), + self.filterDataEb + ) + def key_input(self, window, key, scancode, codepoint, modifier): if key == 27: self.close() diff -r bf9474e164f3 -r 38fd457b2158 cagou/kv/common.kv --- a/cagou/kv/common.kv Sat Jan 04 16:24:57 2020 +0100 +++ b/cagou/kv/common.kv Fri Jan 17 18:44:32 2020 +0100 @@ -109,3 +109,12 @@ : bg_color: 0, 0, 0, 0 color: app.c_sec_light + + +: + layout: layout + StackLayout: + id: layout + size_hint: 1, None + height: self.minimum_height + spacing: 0 diff -r bf9474e164f3 -r 38fd457b2158 cagou/kv/share_widget.kv --- a/cagou/kv/share_widget.kv Sat Jan 04 16:24:57 2020 +0100 +++ b/cagou/kv/share_widget.kv Fri Jan 17 18:44:32 2020 +0100 @@ -20,7 +20,6 @@ : preview_box: preview_box - layout: layout orientation: 'vertical' Label: size_hint: 1, None @@ -44,12 +43,8 @@ height: self.font_size + dp(5) bold: True font_size: '25sp' - ScrollView: - StackLayout: - id: layout - size_hint: 1, None - height: self.minimum_height - spacing: 0 + JidSelector: + on_select: root.on_select(args[1]) Button: size_hint: 1, None height: C.BTN_HEIGHT