Mercurial > libervia-desktop-kivy
annotate cagou/plugins/plugin_wid_file_sharing.py @ 228:e702228b655a
changed package/service namespaces to org.salutatoi.*
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 29 Jun 2018 16:14:09 +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))) |