Mercurial > libervia-desktop-kivy
view 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 |
line wrap: on
line source
#!/usr/bin/python # -*- coding: utf-8 -*- # Cagou: desktop/mobile frontend for Salut à Toi XMPP client # Copyright (C) 2016 Jérôme Poisson (goffi@goffi.org) # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. from sat.core.i18n import _ from sat.core import log as logging log = logging.getLogger(__name__) from cagou.core.constants import Const as C from kivy.uix.boxlayout import BoxLayout from kivy.uix.label import Label from kivy.uix.popup import Popup from kivy import properties from kivy.garden import contextmenu from sat_frontends.quick_frontend import quick_menus from cagou import G import webbrowser ABOUT_TITLE = _(u"About {}".format(C.APP_NAME)) ABOUT_CONTENT = _(u"""Cagou (Salut à Toi) v{} Cagou is a libre communication tool based on libre standard XMPP. Cagou is part of the "Salut à Toi" project more informations at [color=5500ff][ref=website]salut-a-toi.org[/ref][/color] """).format(C.APP_VERSION) class AboutContent(Label): def on_ref_press(self, value): if value == "website": webbrowser.open("https://salut-a-toi.org") class AboutPopup(Popup): def on_touch_down(self, touch): if self.collide_point(*touch.pos): self.dismiss() return super(AboutPopup, self).on_touch_down(touch) class MainMenu(contextmenu.AppMenu): pass class MenuItem(contextmenu.ContextMenuTextItem): item = properties.ObjectProperty() def on_item(self, instance, item): self.text = item.name def on_release(self): super(MenuItem, self).on_release() self.parent.hide() selected = G.host.selected_widget profile = None if selected is not None: try: profile = selected.profile except AttributeError: pass if profile is None: try: profile = list(selected.profiles)[0] except (AttributeError, IndexError): try: profile = list(G.host.profiles)[0] except IndexError: log.warning(u"Can't find profile") self.item.call(selected, profile) class MenuSeparator(contextmenu.ContextMenuDivider): pass class RootMenuContainer(contextmenu.AppMenuTextItem): pass class MenuContainer(contextmenu.ContextMenuTextItem): pass class MenusWidget(BoxLayout): def update(self, type_, caller=None): """Method to call when menus have changed @param type_(unicode): menu type like in sat.core.sat_main.importMenu @param caller(Widget): instance linked to the menus """ self.menus_container = G.host.menus.getMainContainer(type_) self.createMenus(caller) def _buildMenus(self, container, caller=None): """Recursively build menus of the container @param container(quick_menus.MenuContainer): menu container @param caller(Widget): instance linked to the menus """ if caller is None: main_menu = MainMenu() self.add_widget(main_menu) caller = main_menu else: context_menu = contextmenu.ContextMenu() caller.add_widget(context_menu) # FIXME: next line is needed after parent is set to avoid a display bug in contextmenu # TODO: fix this upstream context_menu._on_visible(False) caller = context_menu for child in container.getActiveMenus(): if isinstance(child, quick_menus.MenuContainer): if isinstance(caller, MainMenu): menu_container = RootMenuContainer() else: menu_container = MenuContainer() menu_container.text = child.name caller.add_widget(menu_container) self._buildMenus(child, caller=menu_container) elif isinstance(child, quick_menus.MenuSeparator): wid = MenuSeparator() caller.add_widget(wid) elif isinstance(child, quick_menus.MenuItem): wid = MenuItem(item=child) caller.add_widget(wid) else: log.error(u"Unknown child type: {}".format(child)) def createMenus(self, caller): self.clear_widgets() self._buildMenus(self.menus_container, caller) def onAbout(self): about = AboutPopup() about.title = ABOUT_TITLE about.content = AboutContent(text=ABOUT_CONTENT, markup=True) about.open() class TransferItem(BoxLayout): plug_info = properties.DictProperty() def on_touch_up(self, touch): if not self.collide_point(*touch.pos): return super(TransferItem, self).on_touch_up(touch) else: transfer_menu = self.parent while not isinstance(transfer_menu, TransferMenu): transfer_menu = transfer_menu.parent transfer_menu.do_callback(self.plug_info) return True class TransferMenu(BoxLayout): """transfer menu which handle display and callbacks""" # callback will be called with path to file to transfer callback = properties.ObjectProperty() # cancel callback need to remove the widget for UI # will be called with the widget to remove as argument cancel_cb = properties.ObjectProperty() # profiles if set will be sent to transfer widget, may be used to get specific files profiles = properties.ObjectProperty() 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") send_txt = _(u"The file will be sent unencrypted directly to your contact (without transiting by the server), except in some cases") items_layout = properties.ObjectProperty() def __init__(self, **kwargs): super(TransferMenu, self).__init__(**kwargs) if self.cancel_cb is None: self.cancel_cb = self.onTransferCancelled if self.profiles is None: self.profiles = iter(G.host.profiles) for plug_info in G.host.getPluggedWidgets(type_=C.PLUG_TYPE_TRANSFER): item = TransferItem( plug_info = plug_info ) self.items_layout.add_widget(item) def show(self, caller_wid=None): self.visible = True G.host.app.root.add_widget(self) def on_touch_down(self, touch): # we remove the menu if we click outside # else we want to handle the event, but not # transmit it to parents if not self.collide_point(*touch.pos): self.parent.remove_widget(self) else: return super(TransferMenu, self).on_touch_down(touch) return True def _closeUI(self, wid): G.host.closeUI() def onTransferCancelled(self, wid, cleaning_cb=None): self._closeUI(wid) if cleaning_cb is not None: cleaning_cb() def do_callback(self, plug_info): self.parent.remove_widget(self) if self.callback is None: log.warning(u"TransferMenu callback is not set") else: wid = None external = plug_info.get('external', False) def onTransferCb(file_path, cleaning_cb=None): if not external: self._closeUI(wid) self.callback(file_path, cleaning_cb) wid = plug_info['factory'](plug_info, onTransferCb, self.cancel_cb, self.profiles) if not external: G.host.showExtraUI(wid)