comparison cagou/core/share_widget.py @ 336:b0c9017a1db7

core: added forgotten share_widget module
author Goffi <goffi@goffi.org>
date Sat, 28 Dec 2019 16:09:54 +0100
parents
children 38fd457b2158
comparison
equal deleted inserted replaced
335:597cc207c8e7 336:b0c9017a1db7
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3
4 # Cagou: desktop/mobile frontend for Salut à Toi XMPP client
5 # Copyright (C) 2016-2019 Jérôme Poisson (goffi@goffi.org)
6
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Affero General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Affero General Public License for more details.
16
17 # 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/>.
19
20
21 from pathlib import Path
22 from sat.core import log as logging
23 from sat.core.i18n import _
24 from sat.tools.common import data_format
25 from sat_frontends.tools import jid
26 from kivy.uix.boxlayout import BoxLayout
27 from kivy.uix.behaviors import ButtonBehavior
28 from kivy.properties import StringProperty, DictProperty, ObjectProperty
29 from kivy.core.window import Window
30 from kivy.metrics import dp
31 from .common import ContactItem
32 from .constants import Const as C
33 from cagou import G
34
35
36 log = logging.getLogger(__name__)
37
38
39 PLUGIN_INFO = {
40 "name": _("share"),
41 "main": "Share",
42 "description": _("share a file"),
43 "icon_symbol": "share",
44 }
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
70
71 class TextPreview(BoxLayout):
72 """Widget previewing shared text"""
73 text = StringProperty()
74
75
76 class ImagePreview(BoxLayout):
77 """Widget previewing shared image"""
78 path = StringProperty()
79 reduce_layout = ObjectProperty()
80 reduce_checkbox = ObjectProperty()
81
82 def _checkImageCb(self, report_raw):
83 self.report = data_format.deserialise(report_raw)
84 if self.report['too_large']:
85 self.reduce_layout.opacity = 1
86 self.reduce_layout.height = self.reduce_layout.minimum_height + dp(10)
87 self.reduce_layout.padding = [0, dp(5)]
88
89 def _checkImageEb(self, failure_):
90 log.error(f"Can't check image: {failure_}")
91
92 def on_path(self, wid, path):
93 G.host.bridge.imageCheck(
94 path, callback=self._checkImageCb, errback=self._checkImageEb)
95
96 def resizeImage(self, data, callback, errback):
97
98 def imageResizeCb(new_path):
99 new_path = Path(new_path)
100 log.debug(f"image {data['path']} resized at {new_path}")
101 data['path'] = new_path
102 data['cleaning_cb'] = lambda: new_path.unlink()
103 callback(data)
104
105 path = data['path']
106 width, height = self.report['recommended_size']
107 G.host.bridge.imageResize(
108 path, width, height,
109 callback=imageResizeCb,
110 errback=errback
111 )
112
113 def getFilter(self):
114 if self.report['too_large'] and self.reduce_checkbox.active:
115 return self.resizeImage
116 else:
117 return lambda data, callback, errback: callback(data)
118
119
120 class GenericPreview(BoxLayout):
121 """Widget previewing shared image"""
122 path = StringProperty()
123
124
125 class ShareWidget(BoxLayout):
126 media_type = StringProperty()
127 data = DictProperty()
128 preview_box = ObjectProperty()
129 layout = ObjectProperty()
130
131 def __init__(self, **kwargs):
132 super().__init__(**kwargs)
133 G.host.addListener("contactsFilled", self.onContactsFilled)
134 Window.bind(on_keyboard=self.key_input)
135
136 def on_kv_post(self, wid):
137 self.type, self.subtype = self.media_type.split('/')
138 if self.type == 'text':
139 self.preview_box.add_widget(TextPreview(text=self.data['text']))
140 elif self.type == 'image':
141 self.preview_box.add_widget(ImagePreview(path=self.data['path']))
142 else:
143 self.preview_box.add_widget(GenericPreview(path=self.data['path']))
144 self.addRosterContacts()
145
146 def close(self):
147 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
172 def getFilteredData(self, callback, errback):
173 """Apply filter if suitable, and call callback with with modified data"""
174 try:
175 getFilter = self.preview_box.children[0].getFilter
176 except AttributeError:
177 callback(self.data)
178 else:
179 filter_ = getFilter()
180 filter_(self.data, callback=callback, errback=errback)
181
182 def key_input(self, window, key, scancode, codepoint, modifier):
183 if key == 27:
184 self.close()
185 return True