annotate src/cagou/core/menu.py @ 58:7aa2ffff9067

chat: <img/> tag handling first draft: We need to have several widgets to handle <img/> (label(s) + image(s)), which make sizing and positioning complicated. To make things simpler, we use a simple trick when several widgets are present: we split the labels in as many labels as there are words, so we can take profit of the StackLayout. The split is done after the XHTML is parsed, so after all the widgets are present, and is done only once. This means that label need to be reparsed to be splitted. This is not perfect, but should be a reasonable solutions until we implement a real XHTML engine (probably CEF widget and Webview). image sizing and alignment is not handled correcly now, should be fixed soon.
author Goffi <goffi@goffi.org>
date Wed, 28 Sep 2016 22:02:36 +0200
parents 65775152aac1
children c2a7234d13d2
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
51
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1 #!/usr/bin/python
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
2 # -*- coding: utf-8 -*-
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
3
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
4 # Cagou: desktop/mobile frontend for Salut à Toi XMPP client
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
5 # Copyright (C) 2016 Jérôme Poisson (goffi@goffi.org)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
6
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
7 # This program is free software: you can redistribute it and/or modify
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
8 # it under the terms of the GNU Affero General Public License as published by
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
9 # the Free Software Foundation, either version 3 of the License, or
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
10 # (at your option) any later version.
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
11
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
12 # This program is distributed in the hope that it will be useful,
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
15 # GNU Affero General Public License for more details.
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
16
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
17 # You should have received a copy of the GNU Affero General Public License
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
19
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
20
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
21 from sat.core.i18n import _
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
22 from sat.core import log as logging
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
23 log = logging.getLogger(__name__)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
24 from cagou.core.constants import Const as C
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
25 from kivy.uix.scrollview import ScrollView
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
26 from kivy.uix.gridlayout import GridLayout
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
27 from kivy.uix.widget import Widget
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
28 from kivy.uix.label import Label
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
29 from kivy.uix.button import Button
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
30 from kivy.uix.popup import Popup
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
31 from kivy.uix.dropdown import DropDown
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
32 from kivy import properties
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
33 from sat_frontends.quick_frontend import quick_menus
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
34 from cagou import G
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
35 import webbrowser
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
36
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
37 ABOUT_TITLE = _(u"About {}".format(C.APP_NAME))
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
38 ABOUT_CONTENT = _(u"""Cagou (Salut à Toi) v{}
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
39
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
40 Cagou is a libre communication tool based on libre standard XMPP.
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
41
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
42 Cagou is part of the "Salut à Toi" project
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
43 more informations at [color=5500ff][ref=website]salut-a-toi.org[/ref][/color]
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
44 """).format(C.APP_VERSION)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
45
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
46
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
47 class AboutContent(Label):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
48
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
49 def on_ref_press(self, value):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
50 if value == "website":
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
51 webbrowser.open("https://salut-a-toi.org")
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
52
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
53
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
54 class AboutPopup(Popup):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
55
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
56 def on_touch_down(self, touch):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
57 if self.collide_point(*touch.pos):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
58 self.dismiss()
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
59 return super(AboutPopup, self).on_touch_down(touch)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
60
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
61
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
62 class MenuItem(Button):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
63 item = properties.ObjectProperty()
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
64
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
65 def on_item(self, instance, item):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
66 self.text = item.name
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
67
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
68 def on_release(self):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
69 try:
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
70 self.parent.parent.dismiss()
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
71 except AttributeError:
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
72 pass
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
73 selected = G.host.selected_widget
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
74 profile = None
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
75 if selected is not None:
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
76 try:
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
77 profile = selected.profile
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
78 except AttributeError:
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
79 pass
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
80
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
81 if profile is None:
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
82 try:
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
83 profile = list(selected.profiles)[0]
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
84 except (AttributeError, IndexError):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
85 try:
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
86 profile = list(G.host.profiles)[0]
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
87 except IndexError:
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
88 log.warning(u"Can't find profile")
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
89 self.item.call(selected, profile)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
90
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
91
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
92 class MenuSeparator(Widget):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
93 pass
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
94
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
95
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
96 class MenuContainer(Button):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
97
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
98 def __init__(self, **kwargs):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
99 super(MenuContainer, self).__init__(**kwargs)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
100 self.dropdown = DropDown(auto_width=False, size_hint_x=None, width=400)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
101
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
102 def on_release(self):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
103 self.dropdown.open(self)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
104
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
105 def add_widget(self, widget):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
106 widget.size_hint_y = None
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
107 self.dropdown.add_widget(widget)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
108
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
109
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
110 class MenusWidget(ScrollView):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
111
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
112 def __init__(self, **kwargs):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
113 super(MenusWidget, self).__init__(**kwargs)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
114 self._grid = GridLayout(rows=1, size_hint=(None, 1))
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
115 self._grid.width = self._grid.minimum_width
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
116 super(MenusWidget, self).add_widget(self._grid)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
117
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
118 def add_widget(self, widget):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
119 self._grid.add_widget(widget)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
120
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
121 def clear_widgets(self, children=None):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
122 self._grid.clear_widgets(children)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
123
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
124 def update(self, type_, caller=None):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
125 """Method to call when menus have changed
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
126
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
127 @param type_(unicode): menu type like in sat.core.sat_main.importMenu
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
128 @param caller(Widget): instance linked to the menus
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
129 """
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
130 self.menus_container = G.host.menus.getMainContainer(type_)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
131 self.createMenus(caller)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
132
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
133 def _buildMenus(self, container, caller=None):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
134 """Recursively build menus of the container
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
135
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
136 @param container(quick_menus.MenuContainer): menu container
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
137 @param caller(Widget): instance linked to the menus
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
138 """
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
139 if caller is None:
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
140 caller = self
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
141 for child in container.getActiveMenus():
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
142 if isinstance(child, quick_menus.MenuContainer):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
143 menu_container = MenuContainer()
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
144 menu_container.text = child.name
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
145 caller.add_widget(menu_container)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
146 self._buildMenus(child, caller=menu_container)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
147 elif isinstance(child, quick_menus.MenuSeparator):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
148 wid = MenuSeparator()
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
149 caller.add_widget(wid)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
150 elif isinstance(child, quick_menus.MenuItem):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
151 wid = MenuItem(item=child)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
152 caller.add_widget(wid)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
153 else:
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
154 log.error(u"Unknown child type: {}".format(child))
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
155
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
156 def createMenus(self, caller):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
157 self.clear_widgets()
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
158 self._buildMenus(self.menus_container, caller)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
159
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
160 def onAbout(self):
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
161 about = AboutPopup()
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
162 about.title = ABOUT_TITLE
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
163 about.content = AboutContent(text=ABOUT_CONTENT, markup=True)
3f8599d9a766 core: menus first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
164 about.open()