comparison cagou/core/share_widget.py @ 348:38fd457b2158

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
author Goffi <goffi@goffi.org>
date Fri, 17 Jan 2020 18:44:32 +0100
parents b0c9017a1db7
children 4d3a0c4f2430
comparison
equal deleted inserted replaced
347:bf9474e164f3 348:38fd457b2158
1 #!/usr/bin/python 1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 2
4 # Cagou: desktop/mobile frontend for Salut à Toi XMPP client 3 # Cagou: desktop/mobile frontend for Salut à Toi XMPP client
5 # Copyright (C) 2016-2019 Jérôme Poisson (goffi@goffi.org) 4 # Copyright (C) 2016-2019 Jérôme Poisson (goffi@goffi.org)
6 5
7 # This program is free software: you can redistribute it and/or modify 6 # This program is free software: you can redistribute it and/or modify
17 # You should have received a copy of the GNU Affero General Public License 16 # You should have received a copy of the GNU Affero General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. 17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 18
20 19
21 from pathlib import Path 20 from pathlib import Path
21 from functools import partial
22 from sat.core import log as logging 22 from sat.core import log as logging
23 from sat.core.i18n import _ 23 from sat.core.i18n import _
24 from sat.tools.common import data_format 24 from sat.tools.common import data_format
25 from sat_frontends.tools import jid 25 from sat_frontends.tools import jid
26 from kivy.uix.boxlayout import BoxLayout 26 from kivy.uix.boxlayout import BoxLayout
27 from kivy.uix.behaviors import ButtonBehavior
28 from kivy.properties import StringProperty, DictProperty, ObjectProperty 27 from kivy.properties import StringProperty, DictProperty, ObjectProperty
29 from kivy.core.window import Window 28 from kivy.core.window import Window
30 from kivy.metrics import dp 29 from kivy.metrics import dp
31 from .common import ContactItem
32 from .constants import Const as C 30 from .constants import Const as C
33 from cagou import G 31 from cagou import G
34 32
35 33
36 log = logging.getLogger(__name__) 34 log = logging.getLogger(__name__)
40 "name": _("share"), 38 "name": _("share"),
41 "main": "Share", 39 "main": "Share",
42 "description": _("share a file"), 40 "description": _("share a file"),
43 "icon_symbol": "share", 41 "icon_symbol": "share",
44 } 42 }
45
46 class ShareContactItem(ButtonBehavior, ContactItem):
47
48 def filterDataCb(self, data):
49 G.host.doAction('chat', jid.JID(self.jid), [self.profile])
50 chat_wid = G.host.selected_widget
51
52 if self.share_wid.type == 'text':
53 text = self.share_wid.data['text']
54 chat_wid.message_input.text += text
55 else:
56 path = self.share_wid.data['path']
57 chat_wid.transferFile(path, cleaning_cb=data.get('cleaning_cb'))
58 self.share_wid.close()
59
60 def filterDataEb(self, failure_):
61 G.host.addNote(
62 _("file filter error"),
63 _("Can't apply filter to file: {msg}").format(msg=failure_),
64 level=C.XMLUI_DATA_LVL_ERROR)
65
66 def on_press(self):
67 self.share_wid = G.host.getAncestorWidget(self, ShareWidget)
68 self.share_wid.getFilteredData(self.filterDataCb, self.filterDataEb)
69 43
70 44
71 class TextPreview(BoxLayout): 45 class TextPreview(BoxLayout):
72 """Widget previewing shared text""" 46 """Widget previewing shared text"""
73 text = StringProperty() 47 text = StringProperty()
124 98
125 class ShareWidget(BoxLayout): 99 class ShareWidget(BoxLayout):
126 media_type = StringProperty() 100 media_type = StringProperty()
127 data = DictProperty() 101 data = DictProperty()
128 preview_box = ObjectProperty() 102 preview_box = ObjectProperty()
129 layout = ObjectProperty()
130 103
131 def __init__(self, **kwargs): 104 def __init__(self, **kwargs):
132 super().__init__(**kwargs) 105 super().__init__(**kwargs)
133 G.host.addListener("contactsFilled", self.onContactsFilled)
134 Window.bind(on_keyboard=self.key_input) 106 Window.bind(on_keyboard=self.key_input)
135 107
136 def on_kv_post(self, wid): 108 def on_kv_post(self, wid):
137 self.type, self.subtype = self.media_type.split('/') 109 self.type, self.subtype = self.media_type.split('/')
138 if self.type == 'text': 110 if self.type == 'text':
139 self.preview_box.add_widget(TextPreview(text=self.data['text'])) 111 self.preview_box.add_widget(TextPreview(text=self.data['text']))
140 elif self.type == 'image': 112 elif self.type == 'image':
141 self.preview_box.add_widget(ImagePreview(path=self.data['path'])) 113 self.preview_box.add_widget(ImagePreview(path=self.data['path']))
142 else: 114 else:
143 self.preview_box.add_widget(GenericPreview(path=self.data['path'])) 115 self.preview_box.add_widget(GenericPreview(path=self.data['path']))
144 self.addRosterContacts()
145 116
146 def close(self): 117 def close(self):
147 G.host.closeUI() 118 G.host.closeUI()
148
149 def on_parent(self, wid, parent):
150 if parent is None:
151 log.debug("removing contactsFilled listener")
152 G.host.removeListener("contactsFilled", self.onContactsFilled)
153
154
155 def addRosterContacts(self):
156 log.debug("starting addRosterContacts")
157 self.layout.clear_widgets()
158 for profile in G.host.profiles:
159 contact_list = G.host.contact_lists[profile]
160 for entity_jid in sorted(contact_list.roster):
161 item = ShareContactItem(
162 jid=entity_jid,
163 data=contact_list.getItem(entity_jid),
164 profile=profile,
165 )
166 self.layout.add_widget(item)
167
168 def onContactsFilled(self, profile):
169 log.debug("onContactsFilled event received")
170 self.addRosterContacts()
171 119
172 def getFilteredData(self, callback, errback): 120 def getFilteredData(self, callback, errback):
173 """Apply filter if suitable, and call callback with with modified data""" 121 """Apply filter if suitable, and call callback with with modified data"""
174 try: 122 try:
175 getFilter = self.preview_box.children[0].getFilter 123 getFilter = self.preview_box.children[0].getFilter
177 callback(self.data) 125 callback(self.data)
178 else: 126 else:
179 filter_ = getFilter() 127 filter_ = getFilter()
180 filter_(self.data, callback=callback, errback=errback) 128 filter_(self.data, callback=callback, errback=errback)
181 129
130 def filterDataCb(self, data, contact_jid, profile):
131 G.host.doAction('chat', contact_jid, [profile])
132 chat_wid = G.host.selected_widget
133
134 if self.type == 'text':
135 text = self.data['text']
136 chat_wid.message_input.text += text
137 else:
138 path = self.data['path']
139 chat_wid.transferFile(path, cleaning_cb=data.get('cleaning_cb'))
140 self.close()
141
142 def filterDataEb(self, failure_):
143 G.host.addNote(
144 _("file filter error"),
145 _("Can't apply filter to file: {msg}").format(msg=failure_),
146 level=C.XMLUI_DATA_LVL_ERROR)
147
148 def on_select(self, contact_button):
149 contact_jid = jid.JID(contact_button.jid)
150 self.getFilteredData(
151 partial(
152 self.filterDataCb,
153 contact_jid=contact_jid,
154 profile=contact_button.profile),
155 self.filterDataEb
156 )
157
182 def key_input(self, window, key, scancode, codepoint, modifier): 158 def key_input(self, window, key, scancode, codepoint, modifier):
183 if key == 27: 159 if key == 27:
184 self.close() 160 self.close()
185 return True 161 return True