Mercurial > libervia-desktop
annotate cagou/plugins/plugin_wid_file_sharing.py @ 233:ba8f3a4a5ac7
plugin chat: e2e encryption improvments:
OTR buttons has been replaced with a more generic one, which use new encryption mechanisms
to retrieve all current encryption algorithms (+ a button for plain text).
"refresh" and "authentify" buttons for OTR are temporarily removed.
Encryption state is checked on chat widget startup, and current encryption method is
selected (it will appear with a different background in encryption menu).
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 11 Aug 2018 18:34:16 +0200 |
parents | a676cb07c1cb |
children | 059c5b39032d |
rev | line source |
---|---|
192 | 1 #!/usr/bin/python |
2 # -*- coding: utf-8 -*- | |
3 | |
4 # Cagou: desktop/mobile frontend for Salut à Toi XMPP client | |
5 # Copyright (C) 2016-2018 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 sat.core import log as logging | |
22 from sat.core import exceptions | |
23 log = logging.getLogger(__name__) | |
24 from sat.core.i18n import _ | |
25 from sat.tools.common import files_utils | |
26 from sat_frontends.quick_frontend import quick_widgets | |
27 from sat_frontends.tools import jid | |
28 from cagou.core.constants import Const as C | |
29 from cagou.core import cagou_widget | |
222 | 30 from cagou.core.menu import (EntitiesSelectorMenu, TouchMenuBehaviour, |
31 TouchMenuItemBehaviour) | |
196
519b3a29743c
utils, plugin file sharing: new utils module, with a FilterBehavior:
Goffi <goffi@goffi.org>
parents:
194
diff
changeset
|
32 from cagou.core.utils import FilterBehavior |
192 | 33 from cagou import G |
34 from kivy import properties | |
35 from kivy.uix.label import Label | |
36 from kivy.uix.button import Button | |
37 from kivy.uix.boxlayout import BoxLayout | |
38 from kivy.metrics import dp | |
205
9cefc9f8efc9
plugin file sharing: use external storage directory instead of home (which is "/data") on Android when expanding "~"
Goffi <goffi@goffi.org>
parents:
202
diff
changeset
|
39 from kivy import utils as kivy_utils |
192 | 40 from functools import partial |
41 import os.path | |
42 import json | |
43 | |
44 | |
45 PLUGIN_INFO = { | |
46 "name": _(u"file sharing"), | |
47 "main": "FileSharing", | |
48 "description": _(u"share/transfer files between devices"), | |
49 "icon_symbol": u"exchange", | |
50 } | |
51 MODE_VIEW = u"view" | |
52 MODE_LOCAL = u"local" | |
194
a68c9baa6694
plugin file sharing: use header hint to show current path, and open new path:
Goffi <goffi@goffi.org>
parents:
192
diff
changeset
|
53 SELECT_INSTRUCTIONS = _(u"Please select entities to share with") |
192 | 54 |
205
9cefc9f8efc9
plugin file sharing: use external storage directory instead of home (which is "/data") on Android when expanding "~"
Goffi <goffi@goffi.org>
parents:
202
diff
changeset
|
55 if kivy_utils.platform == "android": |
9cefc9f8efc9
plugin file sharing: use external storage directory instead of home (which is "/data") on Android when expanding "~"
Goffi <goffi@goffi.org>
parents:
202
diff
changeset
|
56 from jnius import autoclass |
9cefc9f8efc9
plugin file sharing: use external storage directory instead of home (which is "/data") on Android when expanding "~"
Goffi <goffi@goffi.org>
parents:
202
diff
changeset
|
57 Environment = autoclass("android.os.Environment") |
9cefc9f8efc9
plugin file sharing: use external storage directory instead of home (which is "/data") on Android when expanding "~"
Goffi <goffi@goffi.org>
parents:
202
diff
changeset
|
58 base_dir = Environment.getExternalStorageDirectory().getAbsolutePath() |
9cefc9f8efc9
plugin file sharing: use external storage directory instead of home (which is "/data") on Android when expanding "~"
Goffi <goffi@goffi.org>
parents:
202
diff
changeset
|
59 def expanduser(path): |
9cefc9f8efc9
plugin file sharing: use external storage directory instead of home (which is "/data") on Android when expanding "~"
Goffi <goffi@goffi.org>
parents:
202
diff
changeset
|
60 if path == u'~' or path.startswith(u'~/'): |
9cefc9f8efc9
plugin file sharing: use external storage directory instead of home (which is "/data") on Android when expanding "~"
Goffi <goffi@goffi.org>
parents:
202
diff
changeset
|
61 return path.replace(u'~', base_dir, 1) |
9cefc9f8efc9
plugin file sharing: use external storage directory instead of home (which is "/data") on Android when expanding "~"
Goffi <goffi@goffi.org>
parents:
202
diff
changeset
|
62 return path |
9cefc9f8efc9
plugin file sharing: use external storage directory instead of home (which is "/data") on Android when expanding "~"
Goffi <goffi@goffi.org>
parents:
202
diff
changeset
|
63 else: |
9cefc9f8efc9
plugin file sharing: use external storage directory instead of home (which is "/data") on Android when expanding "~"
Goffi <goffi@goffi.org>
parents:
202
diff
changeset
|
64 expanduser = os.path.expanduser |
192 | 65 |
66 | |
67 class ModeBtn(Button): | |
68 | |
69 def __init__(self, parent, **kwargs): | |
70 super(ModeBtn, self).__init__(**kwargs) | |
71 parent.bind(mode=self.on_mode) | |
72 self.on_mode(parent, parent.mode) | |
73 | |
74 def on_mode(self, parent, new_mode): | |
75 if new_mode == MODE_VIEW: | |
76 self.text = _(u"view shared files") | |
77 elif new_mode == MODE_LOCAL: | |
78 self.text = _(u"share local files") | |
79 else: | |
80 exceptions.InternalError(u"Unknown mode: {mode}".format(mode=new_mode)) | |
81 | |
82 | |
83 class Identities(object): | |
84 | |
85 def __init__(self, entity_ids): | |
86 identities = {} | |
87 for cat, type_, name in entity_ids: | |
88 identities.setdefault(cat, {}).setdefault(type_, []).append(name) | |
206
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
89 client = identities.get('client', {}) |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
90 if 'pc' in client: |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
91 self.type = 'desktop' |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
92 elif 'phone' in client: |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
93 self.type = 'phone' |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
94 elif 'web' in client: |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
95 self.type = 'web' |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
96 elif 'console' in client: |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
97 self.type = 'console' |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
98 else: |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
99 self.type = 'desktop' |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
100 |
192 | 101 self.identities = identities |
102 | |
103 @property | |
104 def name(self): | |
105 return self.identities.values()[0].values()[0][0] | |
106 | |
107 | |
222 | 108 class ItemWidget(TouchMenuItemBehaviour, BoxLayout): |
109 name = properties.StringProperty() | |
192 | 110 base_width = properties.NumericProperty(dp(100)) |
111 | |
112 | |
113 class PathWidget(ItemWidget): | |
114 | |
222 | 115 def __init__(self, filepath, main_wid, **kw): |
192 | 116 name = os.path.basename(filepath) |
117 self.filepath = os.path.normpath(filepath) | |
118 if self.filepath == u'.': | |
119 self.filepath = u'' | |
222 | 120 super(PathWidget, self).__init__(name=name, main_wid=main_wid, **kw) |
192 | 121 |
122 @property | |
123 def is_dir(self): | |
124 raise NotImplementedError | |
125 | |
126 def do_item_action(self, touch): | |
127 if self.is_dir: | |
222 | 128 self.main_wid.current_dir = self.filepath |
192 | 129 |
130 def open_menu(self, touch, dt): | |
131 log.debug(_(u"opening menu for {path}").format(path=self.filepath)) | |
132 super(PathWidget, self).open_menu(touch, dt) | |
133 | |
134 | |
135 class LocalPathWidget(PathWidget): | |
136 | |
137 @property | |
138 def is_dir(self): | |
139 return os.path.isdir(self.filepath) | |
140 | |
141 def getMenuChoices(self): | |
142 choices = [] | |
143 if self.shared: | |
144 choices.append(dict(text=_(u'unshare'), | |
145 index=len(choices)+1, | |
222 | 146 callback=self.main_wid.unshare)) |
192 | 147 else: |
148 choices.append(dict(text=_(u'share'), | |
149 index=len(choices)+1, | |
222 | 150 callback=self.main_wid.share)) |
192 | 151 return choices |
152 | |
153 | |
154 class RemotePathWidget(PathWidget): | |
155 | |
222 | 156 def __init__(self, main_wid, filepath, type_, **kw): |
192 | 157 self.type_ = type_ |
222 | 158 super(RemotePathWidget, self).__init__(filepath, main_wid=main_wid, **kw) |
192 | 159 |
160 @property | |
161 def is_dir(self): | |
162 return self.type_ == C.FILE_TYPE_DIRECTORY | |
163 | |
164 def do_item_action(self, touch): | |
165 if self.is_dir: | |
166 if self.filepath == u'..': | |
222 | 167 self.main_wid.remote_entity = u'' |
192 | 168 else: |
169 super(RemotePathWidget, self).do_item_action(touch) | |
170 else: | |
222 | 171 self.main_wid.request_item(self) |
192 | 172 return True |
173 | |
174 | |
175 class DeviceWidget(ItemWidget): | |
176 | |
222 | 177 def __init__(self, main_wid, entity_jid, identities, **kw): |
192 | 178 self.entity_jid = entity_jid |
179 self.identities = identities | |
211
b25d03403898
plugin file sharing: fixed name for service devices
Goffi <goffi@goffi.org>
parents:
206
diff
changeset
|
180 own_jid = next(G.host.profiles.itervalues()).whoami |
b25d03403898
plugin file sharing: fixed name for service devices
Goffi <goffi@goffi.org>
parents:
206
diff
changeset
|
181 self.own_device = entity_jid.bare == own_jid |
b25d03403898
plugin file sharing: fixed name for service devices
Goffi <goffi@goffi.org>
parents:
206
diff
changeset
|
182 if self.own_device: |
b25d03403898
plugin file sharing: fixed name for service devices
Goffi <goffi@goffi.org>
parents:
206
diff
changeset
|
183 name = self.identities.name |
b25d03403898
plugin file sharing: fixed name for service devices
Goffi <goffi@goffi.org>
parents:
206
diff
changeset
|
184 elif self.entity_jid.node: |
b25d03403898
plugin file sharing: fixed name for service devices
Goffi <goffi@goffi.org>
parents:
206
diff
changeset
|
185 name = self.entity_jid.node |
212
38b43ed18bb5
file sharing: use "your server" name when sharing component domain ends with our domain
Goffi <goffi@goffi.org>
parents:
211
diff
changeset
|
186 elif self.entity_jid.domain.endswith(own_jid.domain): |
211
b25d03403898
plugin file sharing: fixed name for service devices
Goffi <goffi@goffi.org>
parents:
206
diff
changeset
|
187 name = _(u"your server") |
b25d03403898
plugin file sharing: fixed name for service devices
Goffi <goffi@goffi.org>
parents:
206
diff
changeset
|
188 else: |
b25d03403898
plugin file sharing: fixed name for service devices
Goffi <goffi@goffi.org>
parents:
206
diff
changeset
|
189 name = _(u"sharing component") |
b25d03403898
plugin file sharing: fixed name for service devices
Goffi <goffi@goffi.org>
parents:
206
diff
changeset
|
190 |
222 | 191 super(DeviceWidget, self).__init__(name=name, main_wid=main_wid, **kw) |
192 | 192 |
206
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
193 def getSymbol(self): |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
194 if self.identities.type == 'desktop': |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
195 return 'desktop' |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
196 elif self.identities.type == 'phone': |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
197 return 'mobile' |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
198 elif self.identities.type == 'web': |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
199 return 'globe' |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
200 elif self.identities.type == 'console': |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
201 return 'terminal' |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
202 else: |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
203 return 'desktop' |
890b48e41998
plugin file sharing: use appropriate symbol when discovering devices
Goffi <goffi@goffi.org>
parents:
205
diff
changeset
|
204 |
192 | 205 def do_item_action(self, touch): |
222 | 206 self.main_wid.remote_entity = self.entity_jid |
207 self.main_wid.remote_dir = u'' | |
192 | 208 |
209 | |
210 class CategorySeparator(Label): | |
211 pass | |
212 | |
213 | |
222 | 214 class FileSharing(quick_widgets.QuickWidget, cagou_widget.CagouWidget, FilterBehavior, |
215 TouchMenuBehaviour): | |
192 | 216 SINGLE=False |
217 layout = properties.ObjectProperty() | |
218 mode = properties.OptionProperty(MODE_LOCAL, options=[MODE_VIEW, MODE_LOCAL]) | |
205
9cefc9f8efc9
plugin file sharing: use external storage directory instead of home (which is "/data") on Android when expanding "~"
Goffi <goffi@goffi.org>
parents:
202
diff
changeset
|
219 local_dir = properties.StringProperty(expanduser(u'~')) |
192 | 220 remote_dir = properties.StringProperty(u'') |
221 remote_entity = properties.StringProperty(u'') | |
222 shared_paths = properties.ListProperty() | |
223 signals_registered = False | |
224 | |
225 def __init__(self, host, target, profiles): | |
226 quick_widgets.QuickWidget.__init__(self, host, target, profiles) | |
227 cagou_widget.CagouWidget.__init__(self) | |
196
519b3a29743c
utils, plugin file sharing: new utils module, with a FilterBehavior:
Goffi <goffi@goffi.org>
parents:
194
diff
changeset
|
228 FilterBehavior.__init__(self) |
222 | 229 TouchMenuBehaviour.__init__(self) |
192 | 230 self.mode_btn = ModeBtn(self) |
231 self.mode_btn.bind(on_release=self.change_mode) | |
232 self.headerInputAddExtra(self.mode_btn) | |
233 self.bind(local_dir=self.update_view, | |
234 remote_dir=self.update_view, | |
235 remote_entity=self.update_view) | |
236 self.update_view() | |
237 if not FileSharing.signals_registered: | |
238 # FIXME: we use this hack (registering the signal for the whole class) now | |
239 # as there is currently no unregisterSignal available in bridges | |
217
286f14127f61
plugin file sharing: started to limit line to 90 chars as a test
Goffi <goffi@goffi.org>
parents:
214
diff
changeset
|
240 G.host.registerSignal("FISSharedPathNew", |
286f14127f61
plugin file sharing: started to limit line to 90 chars as a test
Goffi <goffi@goffi.org>
parents:
214
diff
changeset
|
241 handler=FileSharing.shared_path_new, |
286f14127f61
plugin file sharing: started to limit line to 90 chars as a test
Goffi <goffi@goffi.org>
parents:
214
diff
changeset
|
242 iface="plugin") |
286f14127f61
plugin file sharing: started to limit line to 90 chars as a test
Goffi <goffi@goffi.org>
parents:
214
diff
changeset
|
243 G.host.registerSignal("FISSharedPathRemoved", |
286f14127f61
plugin file sharing: started to limit line to 90 chars as a test
Goffi <goffi@goffi.org>
parents:
214
diff
changeset
|
244 handler=FileSharing.shared_path_removed, |
286f14127f61
plugin file sharing: started to limit line to 90 chars as a test
Goffi <goffi@goffi.org>
parents:
214
diff
changeset
|
245 iface="plugin") |
192 | 246 FileSharing.signals_registered = True |
247 G.host.bridge.FISLocalSharesGet(self.profile, | |
248 callback=self.fill_paths, | |
249 errback=G.host.errback) | |
250 | |
251 @property | |
252 def current_dir(self): | |
253 return self.local_dir if self.mode == MODE_LOCAL else self.remote_dir | |
254 | |
255 @current_dir.setter | |
256 def current_dir(self, new_dir): | |
257 if self.mode == MODE_LOCAL: | |
258 self.local_dir = new_dir | |
259 else: | |
260 self.remote_dir = new_dir | |
261 | |
262 def fill_paths(self, shared_paths): | |
263 self.shared_paths.extend(shared_paths) | |
264 | |
265 def change_mode(self, mode_btn): | |
266 self.clear_menu() | |
267 opt = self.__class__.mode.options | |
268 new_idx = (opt.index(self.mode)+1) % len(opt) | |
269 self.mode = opt[new_idx] | |
270 | |
271 def on_mode(self, instance, new_mode): | |
272 self.update_view(None, self.local_dir) | |
273 | |
194
a68c9baa6694
plugin file sharing: use header hint to show current path, and open new path:
Goffi <goffi@goffi.org>
parents:
192
diff
changeset
|
274 def onHeaderInput(self): |
a68c9baa6694
plugin file sharing: use header hint to show current path, and open new path:
Goffi <goffi@goffi.org>
parents:
192
diff
changeset
|
275 if u'/' in self.header_input.text or self.header_input.text == u'~': |
205
9cefc9f8efc9
plugin file sharing: use external storage directory instead of home (which is "/data") on Android when expanding "~"
Goffi <goffi@goffi.org>
parents:
202
diff
changeset
|
276 self.current_dir = expanduser(self.header_input.text) |
194
a68c9baa6694
plugin file sharing: use header hint to show current path, and open new path:
Goffi <goffi@goffi.org>
parents:
192
diff
changeset
|
277 |
196
519b3a29743c
utils, plugin file sharing: new utils module, with a FilterBehavior:
Goffi <goffi@goffi.org>
parents:
194
diff
changeset
|
278 def onHeaderInputComplete(self, wid, text, **kwargs): |
192 | 279 """we filter items when text is entered in input box""" |
194
a68c9baa6694
plugin file sharing: use header hint to show current path, and open new path:
Goffi <goffi@goffi.org>
parents:
192
diff
changeset
|
280 if u'/' in text: |
a68c9baa6694
plugin file sharing: use header hint to show current path, and open new path:
Goffi <goffi@goffi.org>
parents:
192
diff
changeset
|
281 return |
196
519b3a29743c
utils, plugin file sharing: new utils module, with a FilterBehavior:
Goffi <goffi@goffi.org>
parents:
194
diff
changeset
|
282 self.do_filter(self.layout.children, |
519b3a29743c
utils, plugin file sharing: new utils module, with a FilterBehavior:
Goffi <goffi@goffi.org>
parents:
194
diff
changeset
|
283 text, |
519b3a29743c
utils, plugin file sharing: new utils module, with a FilterBehavior:
Goffi <goffi@goffi.org>
parents:
194
diff
changeset
|
284 lambda c: c.name, |
519b3a29743c
utils, plugin file sharing: new utils module, with a FilterBehavior:
Goffi <goffi@goffi.org>
parents:
194
diff
changeset
|
285 width_cb=lambda c: c.base_width, |
519b3a29743c
utils, plugin file sharing: new utils module, with a FilterBehavior:
Goffi <goffi@goffi.org>
parents:
194
diff
changeset
|
286 height_cb=lambda c: c.minimum_height, |
519b3a29743c
utils, plugin file sharing: new utils module, with a FilterBehavior:
Goffi <goffi@goffi.org>
parents:
194
diff
changeset
|
287 continue_tests=[lambda c: not isinstance(c, ItemWidget), |
519b3a29743c
utils, plugin file sharing: new utils module, with a FilterBehavior:
Goffi <goffi@goffi.org>
parents:
194
diff
changeset
|
288 lambda c: c.name == u'..']) |
519b3a29743c
utils, plugin file sharing: new utils module, with a FilterBehavior:
Goffi <goffi@goffi.org>
parents:
194
diff
changeset
|
289 |
192 | 290 |
291 ## remote sharing callback ## | |
292 | |
293 def _discoFindByFeaturesCb(self, data): | |
294 entities_services, entities_own, entities_roster = data | |
295 for entities_map, title in ((entities_services, | |
296 _(u'services')), | |
297 (entities_own, | |
298 _(u'your devices')), | |
299 (entities_roster, | |
300 _(u'your contacts devices'))): | |
301 if entities_map: | |
302 self.layout.add_widget(CategorySeparator(text=title)) | |
303 for entity_str, entity_ids in entities_map.iteritems(): | |
304 entity_jid = jid.JID(entity_str) | |
305 item = DeviceWidget(self, | |
306 entity_jid, | |
307 Identities(entity_ids)) | |
308 self.layout.add_widget(item) | |
214
6a98d70a3a66
file sharing: display a message when not sharing device has been found
Goffi <goffi@goffi.org>
parents:
213
diff
changeset
|
309 if not entities_services and not entities_own and not entities_roster: |
6a98d70a3a66
file sharing: display a message when not sharing device has been found
Goffi <goffi@goffi.org>
parents:
213
diff
changeset
|
310 self.layout.add_widget(Label( |
6a98d70a3a66
file sharing: display a message when not sharing device has been found
Goffi <goffi@goffi.org>
parents:
213
diff
changeset
|
311 size_hint=(1, 1), |
6a98d70a3a66
file sharing: display a message when not sharing device has been found
Goffi <goffi@goffi.org>
parents:
213
diff
changeset
|
312 halign='center', |
6a98d70a3a66
file sharing: display a message when not sharing device has been found
Goffi <goffi@goffi.org>
parents:
213
diff
changeset
|
313 text_size=self.size, |
6a98d70a3a66
file sharing: display a message when not sharing device has been found
Goffi <goffi@goffi.org>
parents:
213
diff
changeset
|
314 text=_(u"No sharing device found"))) |
192 | 315 |
316 def discover_devices(self): | |
317 """Looks for devices handling file "File Information Sharing" and display them""" | |
318 try: | |
319 namespace = self.host.ns_map['fis'] | |
320 except KeyError: | |
217
286f14127f61
plugin file sharing: started to limit line to 90 chars as a test
Goffi <goffi@goffi.org>
parents:
214
diff
changeset
|
321 msg = _(u"can't find file information sharing namespace, " |
286f14127f61
plugin file sharing: started to limit line to 90 chars as a test
Goffi <goffi@goffi.org>
parents:
214
diff
changeset
|
322 u"is the plugin running?") |
192 | 323 log.warning(msg) |
324 G.host.addNote(_(u"missing plugin"), msg, C.XMLUI_DATA_LVL_ERROR) | |
325 return | |
326 self.host.bridge.discoFindByFeatures( | |
199
b80d275e437f
plugin file sharing: use new local_device argument of discoFindByFeatures
Goffi <goffi@goffi.org>
parents:
198
diff
changeset
|
327 [namespace], [], False, True, True, True, False, self.profile, |
192 | 328 callback=self._discoFindByFeaturesCb, |
329 errback=partial(G.host.errback, | |
330 title=_(u"shared folder error"), | |
331 message=_(u"can't check sharing devices: {msg}"))) | |
332 | |
333 def FISListCb(self, files_data): | |
334 for file_data in files_data: | |
335 filepath = os.path.join(self.current_dir, file_data[u'name']) | |
336 item = RemotePathWidget( | |
337 filepath=filepath, | |
222 | 338 main_wid=self, |
192 | 339 type_=file_data[u'type']) |
340 self.layout.add_widget(item) | |
341 | |
342 def FISListEb(self, failure_): | |
343 self.remote_dir = u'' | |
344 G.host.addNote( | |
345 _(u"shared folder error"), | |
346 _(u"can't list files for {remote_entity}: {msg}").format( | |
347 remote_entity=self.remote_entity, | |
348 msg=failure_), | |
349 level=C.XMLUI_DATA_LVL_WARNING) | |
350 | |
351 ## view generation ## | |
352 | |
353 def update_view(self, *args): | |
354 """update items according to current mode, entity and dir""" | |
355 log.debug(u'updating {}, {}'.format(self.current_dir, args)) | |
356 self.layout.clear_widgets() | |
357 self.header_input.text = u'' | |
194
a68c9baa6694
plugin file sharing: use header hint to show current path, and open new path:
Goffi <goffi@goffi.org>
parents:
192
diff
changeset
|
358 self.header_input.hint_text = self.current_dir |
a68c9baa6694
plugin file sharing: use header hint to show current path, and open new path:
Goffi <goffi@goffi.org>
parents:
192
diff
changeset
|
359 |
192 | 360 if self.mode == MODE_LOCAL: |
361 filepath = os.path.join(self.local_dir, u'..') | |
222 | 362 self.layout.add_widget(LocalPathWidget(filepath=filepath, main_wid=self)) |
213
423d462ea739
file sharing: catch OS errors while trying to list files on a local dir
Goffi <goffi@goffi.org>
parents:
212
diff
changeset
|
363 try: |
423d462ea739
file sharing: catch OS errors while trying to list files on a local dir
Goffi <goffi@goffi.org>
parents:
212
diff
changeset
|
364 files = sorted(os.listdir(self.local_dir)) |
423d462ea739
file sharing: catch OS errors while trying to list files on a local dir
Goffi <goffi@goffi.org>
parents:
212
diff
changeset
|
365 except OSError as e: |
423d462ea739
file sharing: catch OS errors while trying to list files on a local dir
Goffi <goffi@goffi.org>
parents:
212
diff
changeset
|
366 msg = _(u"can't list files in \"{local_dir}\": {msg}").format( |
423d462ea739
file sharing: catch OS errors while trying to list files on a local dir
Goffi <goffi@goffi.org>
parents:
212
diff
changeset
|
367 local_dir=self.local_dir, |
423d462ea739
file sharing: catch OS errors while trying to list files on a local dir
Goffi <goffi@goffi.org>
parents:
212
diff
changeset
|
368 msg=e) |
423d462ea739
file sharing: catch OS errors while trying to list files on a local dir
Goffi <goffi@goffi.org>
parents:
212
diff
changeset
|
369 G.host.addNote( |
423d462ea739
file sharing: catch OS errors while trying to list files on a local dir
Goffi <goffi@goffi.org>
parents:
212
diff
changeset
|
370 _(u"shared folder error"), |
423d462ea739
file sharing: catch OS errors while trying to list files on a local dir
Goffi <goffi@goffi.org>
parents:
212
diff
changeset
|
371 msg, |
423d462ea739
file sharing: catch OS errors while trying to list files on a local dir
Goffi <goffi@goffi.org>
parents:
212
diff
changeset
|
372 level=C.XMLUI_DATA_LVL_WARNING) |
423d462ea739
file sharing: catch OS errors while trying to list files on a local dir
Goffi <goffi@goffi.org>
parents:
212
diff
changeset
|
373 self.local_dir = expanduser(u'~') |
423d462ea739
file sharing: catch OS errors while trying to list files on a local dir
Goffi <goffi@goffi.org>
parents:
212
diff
changeset
|
374 return |
192 | 375 for f in files: |
376 filepath = os.path.join(self.local_dir, f) | |
222 | 377 self.layout.add_widget(LocalPathWidget(filepath=filepath, |
378 main_wid=self)) | |
192 | 379 elif self.mode == MODE_VIEW: |
380 if not self.remote_entity: | |
381 self.discover_devices() | |
382 else: | |
383 # we always a way to go back | |
384 # so user can return to previous list even in case of error | |
385 parent_path = os.path.join(self.remote_dir, u'..') | |
386 item = RemotePathWidget( | |
387 filepath = parent_path, | |
222 | 388 main_wid=self, |
192 | 389 type_ = C.FILE_TYPE_DIRECTORY) |
390 self.layout.add_widget(item) | |
391 self.host.bridge.FISList( | |
202
e20796eea873
plugin file sharing: transtype jid.Jid instance to unicode when using bridge, to avoid troubles with pb
Goffi <goffi@goffi.org>
parents:
199
diff
changeset
|
392 unicode(self.remote_entity), |
192 | 393 self.remote_dir, |
394 {}, | |
395 self.profile, | |
396 callback=self.FISListCb, | |
397 errback=self.FISListEb) | |
398 | |
399 ## Share methods ## | |
400 | |
198
60b63c3e63a1
plugin file sharing: use new EntitiesSelectorMenu to select entities which can access shared files
Goffi <goffi@goffi.org>
parents:
196
diff
changeset
|
401 def do_share(self, entities_jids, item): |
60b63c3e63a1
plugin file sharing: use new EntitiesSelectorMenu to select entities which can access shared files
Goffi <goffi@goffi.org>
parents:
196
diff
changeset
|
402 if entities_jids: |
60b63c3e63a1
plugin file sharing: use new EntitiesSelectorMenu to select entities which can access shared files
Goffi <goffi@goffi.org>
parents:
196
diff
changeset
|
403 access = {u'read': {u'type': 'whitelist', |
60b63c3e63a1
plugin file sharing: use new EntitiesSelectorMenu to select entities which can access shared files
Goffi <goffi@goffi.org>
parents:
196
diff
changeset
|
404 u'jids': entities_jids}} |
60b63c3e63a1
plugin file sharing: use new EntitiesSelectorMenu to select entities which can access shared files
Goffi <goffi@goffi.org>
parents:
196
diff
changeset
|
405 else: |
60b63c3e63a1
plugin file sharing: use new EntitiesSelectorMenu to select entities which can access shared files
Goffi <goffi@goffi.org>
parents:
196
diff
changeset
|
406 access = {} |
60b63c3e63a1
plugin file sharing: use new EntitiesSelectorMenu to select entities which can access shared files
Goffi <goffi@goffi.org>
parents:
196
diff
changeset
|
407 |
192 | 408 G.host.bridge.FISSharePath( |
409 item.name, | |
410 item.filepath, | |
198
60b63c3e63a1
plugin file sharing: use new EntitiesSelectorMenu to select entities which can access shared files
Goffi <goffi@goffi.org>
parents:
196
diff
changeset
|
411 json.dumps(access, ensure_ascii=False), |
192 | 412 self.profile, |
413 callback=lambda name: G.host.addNote( | |
414 _(u"sharing folder"), | |
415 _(u"{name} is now shared").format(name=name)), | |
416 errback=partial(G.host.errback, | |
417 title=_(u"sharing folder"), | |
418 message=_(u"can't share folder: {msg}"))) | |
419 | |
198
60b63c3e63a1
plugin file sharing: use new EntitiesSelectorMenu to select entities which can access shared files
Goffi <goffi@goffi.org>
parents:
196
diff
changeset
|
420 def share(self, menu): |
60b63c3e63a1
plugin file sharing: use new EntitiesSelectorMenu to select entities which can access shared files
Goffi <goffi@goffi.org>
parents:
196
diff
changeset
|
421 item = self.menu_item |
60b63c3e63a1
plugin file sharing: use new EntitiesSelectorMenu to select entities which can access shared files
Goffi <goffi@goffi.org>
parents:
196
diff
changeset
|
422 self.clear_menu() |
60b63c3e63a1
plugin file sharing: use new EntitiesSelectorMenu to select entities which can access shared files
Goffi <goffi@goffi.org>
parents:
196
diff
changeset
|
423 EntitiesSelectorMenu(instructions=SELECT_INSTRUCTIONS, |
60b63c3e63a1
plugin file sharing: use new EntitiesSelectorMenu to select entities which can access shared files
Goffi <goffi@goffi.org>
parents:
196
diff
changeset
|
424 callback=partial(self.do_share, item=item)).show() |
60b63c3e63a1
plugin file sharing: use new EntitiesSelectorMenu to select entities which can access shared files
Goffi <goffi@goffi.org>
parents:
196
diff
changeset
|
425 |
192 | 426 def unshare(self, menu): |
427 item = self.menu_item | |
428 self.clear_menu() | |
429 G.host.bridge.FISUnsharePath( | |
430 item.filepath, | |
431 self.profile, | |
432 callback=lambda: G.host.addNote( | |
433 _(u"sharing folder"), | |
434 _(u"{name} is not shared anymore").format(name=item.name)), | |
435 errback=partial(G.host.errback, | |
436 title=_(u"sharing folder"), | |
437 message=_(u"can't unshare folder: {msg}"))) | |
438 | |
439 def fileJingleRequestCb(self, progress_id, item, dest_path): | |
440 G.host.addNote( | |
441 _(u"file request"), | |
442 _(u"{name} download started at {dest_path}").format( | |
443 name = item.name, | |
444 dest_path = dest_path)) | |
445 | |
446 def request_item(self, item): | |
447 """Retrieve an item from remote entity | |
448 | |
449 @param item(RemotePathWidget): item to retrieve | |
450 """ | |
451 path, name = os.path.split(item.filepath) | |
452 assert name | |
453 assert self.remote_entity | |
454 extra = {'path': path} | |
455 dest_path = files_utils.get_unique_name(os.path.join(G.host.downloads_dir, name)) | |
202
e20796eea873
plugin file sharing: transtype jid.Jid instance to unicode when using bridge, to avoid troubles with pb
Goffi <goffi@goffi.org>
parents:
199
diff
changeset
|
456 G.host.bridge.fileJingleRequest(unicode(self.remote_entity), |
192 | 457 dest_path, |
458 name, | |
459 u'', | |
460 u'', | |
461 extra, | |
462 self.profile, | |
463 callback=partial(self.fileJingleRequestCb, | |
464 item=item, | |
465 dest_path=dest_path), | |
466 errback=partial(G.host.errback, | |
467 title = _(u"file request error"), | |
468 message = _(u"can't request file: {msg}"))) | |
469 | |
470 @classmethod | |
471 def shared_path_new(cls, shared_path, name, profile): | |
472 for wid in G.host.getVisibleList(cls): | |
473 if shared_path not in wid.shared_paths: | |
474 wid.shared_paths.append(shared_path) | |
475 | |
476 @classmethod | |
477 def shared_path_removed(cls, shared_path, profile): | |
478 for wid in G.host.getVisibleList(cls): | |
479 if shared_path in wid.shared_paths: | |
480 wid.shared_paths.remove(shared_path) | |
481 else: | |
482 log.warning(_(u"shared path {path} not found in {widget}".format( | |
483 path = shared_path, widget = wid))) |