Mercurial > libervia-desktop-kivy
comparison libervia/desktop_kivy/core/file_chooser.py @ 514:d78728d7fd6a
plugin wid calls, core: implements WebRTC DataChannel file transfer:
- Add a new "file" icon in call UI to send a file via WebRTC.
- Handle new preflight mechanism, and WebRTC file transfer.
- Native file chooser handling has been moved to new `core.file_chooser` module, and now
supports "save" and "dir" modes (based on `plyer`).
rel 442
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 06 Apr 2024 13:37:27 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
513:0fdf3e59aaad | 514:d78728d7fd6a |
---|---|
1 #!/usr/bin/env python3 | |
2 | |
3 # Libervia Desktop-Kivy | |
4 # Copyright (C) 2016-2024 Jérôme Poisson (goffi@goffi.org) | |
5 | |
6 # This program is free software: you can redistribute it and/or modify | |
7 # it under the terms of the GNU Affero General Public License as published by | |
8 # the Free Software Foundation, either version 3 of the License, or | |
9 # (at your option) any later version. | |
10 | |
11 # This program is distributed in the hope that it will be useful, | |
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 # GNU Affero General Public License for more details. | |
15 | |
16 # You should have received a copy of the GNU Affero General Public License | |
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | |
19 import asyncio | |
20 import threading | |
21 | |
22 from libervia.backend.core import exceptions | |
23 from libervia.backend.core.i18n import _ | |
24 | |
25 from kivy import properties | |
26 from kivy.clock import Clock | |
27 from kivy.event import EventDispatcher | |
28 from plyer import filechooser, storagepath | |
29 | |
30 | |
31 class FileChooser(EventDispatcher): | |
32 callback = properties.ObjectProperty() | |
33 cancel_cb = properties.ObjectProperty() | |
34 native_filechooser = True | |
35 default_path = properties.StringProperty(storagepath.get_home_dir()) | |
36 mode = properties.OptionProperty("open", options=["open", "save", "dir"]) | |
37 title = properties.StringProperty(_("Please select a file to upload")) | |
38 | |
39 def open(self): | |
40 """Open the file selection dialog in a separate thread""" | |
41 thread = threading.Thread(target=self._native_file_chooser) | |
42 thread.start() | |
43 | |
44 @classmethod | |
45 async def a_open(cls, **kwargs) -> str | None: | |
46 """Open the file selection dialog asynchronously | |
47 | |
48 @return: The path of the selected file | |
49 None if the dialog has been cancelled. | |
50 """ | |
51 future = asyncio.Future() | |
52 | |
53 def on_success(file_path): | |
54 if not future.done(): | |
55 future.set_result(file_path) | |
56 | |
57 def on_cancel(__): | |
58 if not future.done(): | |
59 future.set_result(None) | |
60 | |
61 file_chooser = cls( | |
62 **kwargs, | |
63 callback=on_success, | |
64 cancel_cb=on_cancel | |
65 ) | |
66 | |
67 file_chooser.open() | |
68 | |
69 return await future | |
70 | |
71 def _native_file_chooser(self, *args, **kwargs): | |
72 match self.mode: | |
73 case "open": | |
74 method = filechooser.open_file | |
75 case "save": | |
76 method = filechooser.save_file | |
77 case "dir": | |
78 method = filechooser.choose_dir | |
79 case _: | |
80 raise exceptions.InternalError("Should never be reached.") | |
81 files = method( | |
82 title=self.title, path=self.default_path, multiple=False, preview=True | |
83 ) | |
84 # we want to leave the thread when calling on_files, so we use Clock | |
85 Clock.schedule_once(lambda *args: self.on_files(files=files), 0) | |
86 | |
87 def on_files(self, files): | |
88 if files: | |
89 self.callback(files[0]) | |
90 else: | |
91 self.cancel_cb(self) |