Mercurial > libervia-desktop-kivy
annotate src/cagou/core/menu.py @ 97:5d2289127bb7
menu (upload): better menu using dedicated widget:
upload menu now use a decicated widget instead of context menu.
The menu take half the size of the main window, and show each upload option as an icon. Use can select upload or P2P sending, and a short text message explains how the file will be transmitted.
author | Goffi <goffi@goffi.org> |
---|---|
date | Thu, 29 Dec 2016 23:47:07 +0100 |
parents | 3dc526bb4a5a |
children | 4d8c122b86a6 |
rev | line source |
---|---|
51 | 1 #!/usr/bin/python |
2 # -*- coding: utf-8 -*- | |
3 | |
4 # Cagou: desktop/mobile frontend for Salut à Toi XMPP client | |
5 # Copyright (C) 2016 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.i18n import _ | |
22 from sat.core import log as logging | |
23 log = logging.getLogger(__name__) | |
24 from cagou.core.constants import Const as C | |
85
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
25 from kivy.uix.boxlayout import BoxLayout |
51 | 26 from kivy.uix.label import Label |
27 from kivy.uix.popup import Popup | |
28 from kivy import properties | |
85
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
29 from kivy.garden import contextmenu |
51 | 30 from sat_frontends.quick_frontend import quick_menus |
31 from cagou import G | |
32 import webbrowser | |
33 | |
34 ABOUT_TITLE = _(u"About {}".format(C.APP_NAME)) | |
35 ABOUT_CONTENT = _(u"""Cagou (Salut à Toi) v{} | |
36 | |
37 Cagou is a libre communication tool based on libre standard XMPP. | |
38 | |
39 Cagou is part of the "Salut à Toi" project | |
40 more informations at [color=5500ff][ref=website]salut-a-toi.org[/ref][/color] | |
41 """).format(C.APP_VERSION) | |
42 | |
43 | |
44 class AboutContent(Label): | |
45 | |
46 def on_ref_press(self, value): | |
47 if value == "website": | |
48 webbrowser.open("https://salut-a-toi.org") | |
49 | |
50 | |
51 class AboutPopup(Popup): | |
52 | |
53 def on_touch_down(self, touch): | |
54 if self.collide_point(*touch.pos): | |
55 self.dismiss() | |
56 return super(AboutPopup, self).on_touch_down(touch) | |
57 | |
58 | |
85
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
59 class MainMenu(contextmenu.AppMenu): |
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
60 pass |
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
61 |
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
62 |
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
63 class MenuItem(contextmenu.ContextMenuTextItem): |
51 | 64 item = properties.ObjectProperty() |
65 | |
66 def on_item(self, instance, item): | |
67 self.text = item.name | |
68 | |
69 def on_release(self): | |
85
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
70 super(MenuItem, self).on_release() |
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
71 self.parent.hide() |
51 | 72 selected = G.host.selected_widget |
73 profile = None | |
74 if selected is not None: | |
75 try: | |
76 profile = selected.profile | |
77 except AttributeError: | |
78 pass | |
79 | |
80 if profile is None: | |
81 try: | |
82 profile = list(selected.profiles)[0] | |
83 except (AttributeError, IndexError): | |
84 try: | |
85 profile = list(G.host.profiles)[0] | |
86 except IndexError: | |
87 log.warning(u"Can't find profile") | |
88 self.item.call(selected, profile) | |
89 | |
90 | |
85
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
91 class MenuSeparator(contextmenu.ContextMenuDivider): |
51 | 92 pass |
93 | |
94 | |
85
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
95 class RootMenuContainer(contextmenu.AppMenuTextItem): |
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
96 pass |
51 | 97 |
98 | |
85
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
99 class MenuContainer(contextmenu.ContextMenuTextItem): |
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
100 pass |
51 | 101 |
102 | |
85
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
103 class MenusWidget(BoxLayout): |
51 | 104 |
105 def update(self, type_, caller=None): | |
106 """Method to call when menus have changed | |
107 | |
108 @param type_(unicode): menu type like in sat.core.sat_main.importMenu | |
109 @param caller(Widget): instance linked to the menus | |
110 """ | |
111 self.menus_container = G.host.menus.getMainContainer(type_) | |
112 self.createMenus(caller) | |
113 | |
114 def _buildMenus(self, container, caller=None): | |
115 """Recursively build menus of the container | |
116 | |
117 @param container(quick_menus.MenuContainer): menu container | |
118 @param caller(Widget): instance linked to the menus | |
119 """ | |
120 if caller is None: | |
85
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
121 main_menu = MainMenu() |
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
122 self.add_widget(main_menu) |
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
123 caller = main_menu |
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
124 else: |
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
125 context_menu = contextmenu.ContextMenu() |
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
126 caller.add_widget(context_menu) |
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
127 # FIXME: next line is needed after parent is set to avoid a display bug in contextmenu |
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
128 # TODO: fix this upstream |
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
129 context_menu._on_visible(False) |
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
130 |
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
131 caller = context_menu |
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
132 |
51 | 133 for child in container.getActiveMenus(): |
134 if isinstance(child, quick_menus.MenuContainer): | |
85
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
135 if isinstance(caller, MainMenu): |
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
136 menu_container = RootMenuContainer() |
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
137 else: |
c2a7234d13d2
menu: use of garden's contextmenu for menus
Goffi <goffi@goffi.org>
parents:
53
diff
changeset
|
138 menu_container = MenuContainer() |
51 | 139 menu_container.text = child.name |
140 caller.add_widget(menu_container) | |
141 self._buildMenus(child, caller=menu_container) | |
142 elif isinstance(child, quick_menus.MenuSeparator): | |
143 wid = MenuSeparator() | |
144 caller.add_widget(wid) | |
145 elif isinstance(child, quick_menus.MenuItem): | |
146 wid = MenuItem(item=child) | |
147 caller.add_widget(wid) | |
148 else: | |
149 log.error(u"Unknown child type: {}".format(child)) | |
150 | |
151 def createMenus(self, caller): | |
152 self.clear_widgets() | |
153 self._buildMenus(self.menus_container, caller) | |
154 | |
155 def onAbout(self): | |
156 about = AboutPopup() | |
157 about.title = ABOUT_TITLE | |
158 about.content = AboutContent(text=ABOUT_CONTENT, markup=True) | |
159 about.open() | |
86 | 160 |
161 | |
97
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
162 class TransferItem(BoxLayout): |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
163 plug_info = properties.DictProperty() |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
164 |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
165 def on_touch_up(self, touch): |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
166 if not self.collide_point(*touch.pos): |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
167 return super(TransferItem, self).on_touch_up(touch) |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
168 else: |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
169 transfer_menu = self.parent |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
170 while not isinstance(transfer_menu, TransferMenu): |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
171 transfer_menu = transfer_menu.parent |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
172 transfer_menu.do_callback(self.plug_info) |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
173 return True |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
174 |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
175 |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
176 class TransferMenu(BoxLayout): |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
177 """transfer menu which handle display and callbacks""" |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
178 # callback will be called with path to file to transfer |
86 | 179 callback = properties.ObjectProperty() |
180 # cancel callback need to remove the widget for UI | |
181 # will be called with the widget to remove as argument | |
182 cancel_cb = properties.ObjectProperty() | |
97
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
183 # profiles if set will be sent to transfer widget, may be used to get specific files |
86 | 184 profiles = properties.ObjectProperty() |
97
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
185 transfer_txt = _(u"Beware! The file will be sent to your server and stay unencrypted there\nServer admin(s) can see the file, and they choose how, when and if it will be deleted") |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
186 send_txt = _(u"The file will be sent unencrypted directly to your contact (without transiting by the server), except in some cases") |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
187 items_layout = properties.ObjectProperty() |
86 | 188 |
189 def __init__(self, **kwargs): | |
97
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
190 super(TransferMenu, self).__init__(**kwargs) |
86 | 191 if self.cancel_cb is None: |
97
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
192 self.cancel_cb = self.onTransferCancelled |
86 | 193 if self.profiles is None: |
194 self.profiles = iter(G.host.profiles) | |
97
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
195 for plug_info in G.host.getPluggedWidgets(type_=C.PLUG_TYPE_TRANSFER): |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
196 item = TransferItem( |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
197 plug_info = plug_info |
86 | 198 ) |
97
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
199 self.items_layout.add_widget(item) |
86 | 200 |
201 def show(self, caller_wid=None): | |
97
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
202 self.visible = True |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
203 G.host.app.root.add_widget(self) |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
204 |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
205 def on_touch_down(self, touch): |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
206 # we remove the menu if we click outside |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
207 # else we want to handle the event, but not |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
208 # transmit it to parents |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
209 if not self.collide_point(*touch.pos): |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
210 self.parent.remove_widget(self) |
86 | 211 else: |
97
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
212 return super(TransferMenu, self).on_touch_down(touch) |
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
213 return True |
86 | 214 |
215 def _closeUI(self, wid): | |
216 G.host.closeUI() | |
217 | |
97
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
218 def onTransferCancelled(self, wid, cleaning_cb=None): |
86 | 219 self._closeUI(wid) |
88
3dc526bb4a5a
upload: plugin android gallery, first draft:
Goffi <goffi@goffi.org>
parents:
86
diff
changeset
|
220 if cleaning_cb is not None: |
3dc526bb4a5a
upload: plugin android gallery, first draft:
Goffi <goffi@goffi.org>
parents:
86
diff
changeset
|
221 cleaning_cb() |
86 | 222 |
223 def do_callback(self, plug_info): | |
97
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
224 self.parent.remove_widget(self) |
86 | 225 if self.callback is None: |
97
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
226 log.warning(u"TransferMenu callback is not set") |
86 | 227 else: |
228 wid = None | |
88
3dc526bb4a5a
upload: plugin android gallery, first draft:
Goffi <goffi@goffi.org>
parents:
86
diff
changeset
|
229 external = plug_info.get('external', False) |
97
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
230 def onTransferCb(file_path, cleaning_cb=None): |
88
3dc526bb4a5a
upload: plugin android gallery, first draft:
Goffi <goffi@goffi.org>
parents:
86
diff
changeset
|
231 if not external: |
3dc526bb4a5a
upload: plugin android gallery, first draft:
Goffi <goffi@goffi.org>
parents:
86
diff
changeset
|
232 self._closeUI(wid) |
3dc526bb4a5a
upload: plugin android gallery, first draft:
Goffi <goffi@goffi.org>
parents:
86
diff
changeset
|
233 self.callback(file_path, cleaning_cb) |
97
5d2289127bb7
menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents:
88
diff
changeset
|
234 wid = plug_info['factory'](plug_info, onTransferCb, self.cancel_cb, self.profiles) |
88
3dc526bb4a5a
upload: plugin android gallery, first draft:
Goffi <goffi@goffi.org>
parents:
86
diff
changeset
|
235 if not external: |
3dc526bb4a5a
upload: plugin android gallery, first draft:
Goffi <goffi@goffi.org>
parents:
86
diff
changeset
|
236 G.host.showExtraUI(wid) |