annotate src/cagou/plugins/plugin_wid_chat.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 a51ea7874e43
children 2aa44a82d0e7
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1 #!/usr/bin/python
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
2 # -*- coding: utf-8 -*-
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
3
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
4 # Cagou: desktop/mobile frontend for Salut à Toi XMPP client
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
5 # Copyright (C) 2016 Jérôme Poisson (goffi@goffi.org)
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
6
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
7 # This program is free software: you can redistribute it and/or modify
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
8 # it under the terms of the GNU Affero General Public License as published by
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
9 # the Free Software Foundation, either version 3 of the License, or
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
10 # (at your option) any later version.
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
11
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
12 # This program is distributed in the hope that it will be useful,
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
15 # GNU Affero General Public License for more details.
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
16
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
17 # You should have received a copy of the GNU Affero General Public License
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
19
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
20
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
21 from sat.core import log as logging
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
22 log = logging.getLogger(__name__)
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
23 from sat.core.i18n import _
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
24 from cagou.core.constants import Const as C
45
b0595a33465d chat: design improvments:
Goffi <goffi@goffi.org>
parents: 44
diff changeset
25 from kivy.uix.gridlayout import GridLayout
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
26 from kivy.uix.stacklayout import StackLayout
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
27 from kivy.uix.scrollview import ScrollView
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
28 from kivy.uix.textinput import TextInput
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
29 from kivy.uix.label import Label
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
30 from kivy.uix.image import AsyncImage
45
b0595a33465d chat: design improvments:
Goffi <goffi@goffi.org>
parents: 44
diff changeset
31 from kivy.metrics import dp
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
32 from kivy.utils import escape_markup
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
33 from kivy import properties
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
34 from sat_frontends.quick_frontend import quick_widgets
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
35 from sat_frontends.quick_frontend import quick_chat
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
36 from sat_frontends.tools import jid, css_color
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
37 from cagou.core import cagou_widget
44
7819e9efa250 chat: avatar and nick are now displayed, need further aesthetic improvments
Goffi <goffi@goffi.org>
parents: 42
diff changeset
38 from cagou.core.image import Image
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
39 from cagou import G
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
40 from xml.etree import ElementTree as ET
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
41
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
42
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
43 PLUGIN_INFO = {
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
44 "name": _(u"chat"),
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
45 "main": "Chat",
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
46 "description": _(u"instant messaging with one person or a group"),
25
d09bd16dbbe2 code (cagou widget), selector: icons handling + use of new muchoslava icon set
Goffi <goffi@goffi.org>
parents: 24
diff changeset
47 "icon_small": u"{media}/icons/muchoslava/png/chat_rouge_32.png",
d09bd16dbbe2 code (cagou widget), selector: icons handling + use of new muchoslava icon set
Goffi <goffi@goffi.org>
parents: 24
diff changeset
48 "icon_medium": u"{media}/icons/muchoslava/png/chat_rouge_44.png"
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
49 }
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
50
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
51
44
7819e9efa250 chat: avatar and nick are now displayed, need further aesthetic improvments
Goffi <goffi@goffi.org>
parents: 42
diff changeset
52 class MessAvatar(Image):
7819e9efa250 chat: avatar and nick are now displayed, need further aesthetic improvments
Goffi <goffi@goffi.org>
parents: 42
diff changeset
53 pass
7819e9efa250 chat: avatar and nick are now displayed, need further aesthetic improvments
Goffi <goffi@goffi.org>
parents: 42
diff changeset
54
7819e9efa250 chat: avatar and nick are now displayed, need further aesthetic improvments
Goffi <goffi@goffi.org>
parents: 42
diff changeset
55
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
56 class Escape(unicode):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
57 """Class used to mark that a message need to be escaped"""
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
58
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
59 def __init__(self, text):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
60 super(Escape, self).__init__(text)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
61
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
62
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
63 class SimpleXHTMLWidgetEscapedText(Label):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
64 pass
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
65
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
66 class SimpleXHTMLWidgetText(Label):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
67 pass
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
68
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
69 class SimpleXHTMLWidgetImage(AsyncImage):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
70 pass
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
71
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
72 class SimpleXHTMLWidget(StackLayout):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
73 """widget handling simple XHTML parsing"""
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
74 xhtml = properties.StringProperty()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
75 color = properties.ListProperty([1, 1, 1, 1])
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
76 # XXX: bold is only used for escaped text
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
77 bold = properties.BooleanProperty(False)
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
78 content_width = properties.NumericProperty(0)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
79
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
80 # text/XHTML input
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
81
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
82 def on_xhtml(self, instance, xhtml):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
83 """parse xhtml and set content accordingly
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
84
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
85 if xhtml is an instance of Escape, a Label with not markup
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
86 will be used
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
87 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
88 self.clear_widgets()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
89 if isinstance(xhtml, Escape):
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
90 label = SimpleXHTMLWidgetEscapedText(text=xhtml, color=self.color)
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
91 self.bind(color=label.setter('color'))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
92 self.bind(bold=label.setter('bold'))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
93 self.add_widget(label)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
94 else:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
95 xhtml = ET.fromstring(xhtml.encode('utf-8'))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
96 self.current_wid = None
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
97 self.styles = []
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
98 self._callParseMethod(xhtml)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
99
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
100 def escape(self, text):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
101 """mark that a text need to be escaped (i.e. no markup)"""
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
102 return Escape(text)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
103
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
104 # sizing
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
105
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
106 def on_width(self, instance, width):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
107 if len(self.children) == 1:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
108 wid = self.children[0]
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
109 if isinstance(wid, Label):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
110 try:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
111 full_width = wid._full_width
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
112 except AttributeError:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
113 wid.size_hint = (None, None)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
114 wid.texture_update()
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
115 full_width = wid._full_width = wid.texture_size[0]
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
116 if full_width > width:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
117 wid.text_size = width, None
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
118 else:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
119 wid.text_size = None, None
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
120 self.content_width = wid.width + self.padding[0] + self.padding[2]
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
121 else:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
122 wid.size_hint(1, None)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
123 wid.height = 100
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
124 self.content_width = self.width
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
125 else:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
126 self._do_complexe_sizing(width)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
127
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
128 def _do_complexe_sizing(self, width):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
129 try:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
130 self.splitted
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
131 except AttributeError:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
132 # XXX: to make things easier, we split labels in words
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
133 log.debug(u"split start")
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
134 children = self.children[::-1]
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
135 self.clear_widgets()
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
136 for child in children:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
137 if isinstance(child, Label):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
138 log.debug(u"label before split: {}".format(child.text))
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
139 styles = []
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
140 tag = False
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
141 new_text = []
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
142 current_tag = []
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
143 current_value = []
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
144 current_wid = self._createText()
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
145 value = False
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
146 close = False
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
147 # we will parse the text and create a new widget
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
148 # on each new word (actually each space)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
149 # FIXME: handle '\n' and other white chars
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
150 for c in child.text:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
151 if tag:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
152 # we are parsing a markup tag
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
153 if c == u']':
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
154 current_tag_s = u''.join(current_tag)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
155 current_style = (current_tag_s, u''.join(current_value))
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
156 if close:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
157 for idx, s in enumerate(reversed(styles)):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
158 if s[0] == current_tag_s:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
159 del styles[len(styles) - idx - 1]
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
160 break
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
161 else:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
162 styles.append(current_style)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
163 current_tag = []
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
164 current_value = []
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
165 tag = False
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
166 value = False
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
167 close = False
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
168 elif c == u'/':
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
169 close = True
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
170 elif c == u'=':
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
171 value = True
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
172 elif value:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
173 current_value.append(c)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
174 else:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
175 current_tag.append(c)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
176 new_text.append(c)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
177 else:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
178 # we are parsing regular text
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
179 if c == u'[':
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
180 new_text.append(c)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
181 tag = True
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
182 elif c == u' ':
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
183 # new word, we do a new widget
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
184 new_text.append(u' ')
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
185 for t, v in reversed(styles):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
186 new_text.append(u'[/{}]'.format(t))
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
187 current_wid.text = u''.join(new_text)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
188 new_text = []
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
189 self.add_widget(current_wid)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
190 log.debug(u"new widget: {}".format(current_wid.text))
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
191 current_wid = self._createText()
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
192 for t, v in styles:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
193 new_text.append(u'[{tag}{value}]'.format(
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
194 tag = t,
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
195 value = u'={}'.format(v) if v else u''))
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
196 else:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
197 new_text.append(c)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
198 if current_wid.text:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
199 # we may have a remaining widget after the parsing
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
200 close_styles = []
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
201 for t, v in reversed(styles):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
202 close_styles.append(u'[/{}]'.format(t))
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
203 current_wid.text = u''.join(close_styles)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
204 self.add_widget(current_wid)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
205 log.debug(u"new widget: {}".format(current_wid.text))
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
206 else:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
207 # non Label widgets, we just add them
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
208 self.add_widget(child)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
209 self.splitted = True
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
210 log.debug(u"split OK")
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
211
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
212 # we now set the content width
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
213 # FIXME: for now we just use the full width
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
214 self.content_width = width
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
215
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
216 # XHTML parsing methods
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
217
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
218 def _callParseMethod(self, e):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
219 """call the suitable method to parse the element
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
220
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
221 self.xhtml_[tag] will be called if it exists, else
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
222 self.xhtml_generic will be used
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
223 @param e(ET.Element): element to parse
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
224 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
225 try:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
226 method = getattr(self, "xhtml_{}".format(e.tag))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
227 except AttributeError:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
228 log.warning(u"Unhandled XHTML tag: {}".format(e.tag))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
229 method = self.xhtml_generic
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
230 method(e)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
231
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
232 def _addStyle(self, tag, value=None, append_to_list=True):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
233 """add a markup style to label
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
234
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
235 @param tag(unicode): markup tag
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
236 @param value(unicode): markup value if suitable
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
237 @param append_to_list(bool): if True style we be added to self.styles
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
238 self.styles is needed to keep track of styles to remove
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
239 should most probably be set to True
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
240 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
241 label = self._getLabel()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
242 label.text += u'[{tag}{value}]'.format(
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
243 tag = tag,
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
244 value = u'={}'.format(value) if value else ''
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
245 )
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
246 if append_to_list:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
247 self.styles.append((tag, value))
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
248
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
249 def _removeStyle(self, tag, remove_from_list=True):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
250 """remove a markup style from the label
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
251
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
252 @param tag(unicode): markup tag to remove
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
253 @param remove_from_list(bool): if True, remove from self.styles too
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
254 should most probably be set to True
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
255 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
256 label = self._getLabel()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
257 label.text += u'[/{tag}]'.format(
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
258 tag = tag
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
259 )
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
260 if remove_from_list:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
261 for rev_idx, style in enumerate(reversed(self.styles)):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
262 if style[0] == tag:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
263 tag_idx = len(self.styles) - 1 - rev_idx
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
264 del self.styles[tag_idx]
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
265 break
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
266
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
267 def _getLabel(self):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
268 """get current Label if it exists, or create a new one"""
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
269 if not isinstance(self.current_wid, Label):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
270 self._addLabel()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
271 return self.current_wid
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
272
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
273 def _addLabel(self):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
274 """add a new Label
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
275
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
276 current styles will be closed and reopened if needed
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
277 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
278 self._closeLabel()
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
279 self.current_wid = self._createText()
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
280 for tag, value in self.styles:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
281 self._addStyle(tag, value, append_to_list=False)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
282 self.add_widget(self.current_wid)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
283
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
284 def _createText(self):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
285 label = SimpleXHTMLWidgetText(color=self.color, markup=True)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
286 self.bind(color=label.setter('color'))
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
287 label.bind(texture_size=label.setter('size'))
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
288 return label
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
289
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
290 def _closeLabel(self):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
291 """close current style tags in current label
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
292
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
293 needed when you change label to keep style between
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
294 different widgets
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
295 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
296 if isinstance(self.current_wid, Label):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
297 for tag, value in reversed(self.styles):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
298 self._removeStyle(tag, remove_from_list=False)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
299
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
300 def _parseCSS(self, e):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
301 """parse CSS found in "style" attribute of element
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
302
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
303 self._css_styles will be created and contained markup styles added by this method
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
304 @param e(ET.Element): element which may have a "style" attribute
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
305 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
306 styles_limit = len(self.styles)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
307 styles = e.attrib['style'].split(u';')
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
308 for style in styles:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
309 try:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
310 prop, value = style.split(u':')
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
311 except ValueError:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
312 log.warning(u"can't parse style: {}".format(style))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
313 continue
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
314 prop = prop.strip().replace(u'-', '_')
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
315 value = value.strip()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
316 try:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
317 method = getattr(self, "css_{}".format(prop))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
318 except AttributeError:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
319 log.warning(u"Unhandled CSS: {}".format(prop))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
320 else:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
321 method(e, value)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
322 self._css_styles = self.styles[styles_limit:]
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
323
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
324 def _closeCSS(self):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
325 """removed CSS styles
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
326
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
327 styles in self._css_styles will be removed
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
328 and the attribute will be deleted
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
329 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
330 for tag, dummy in reversed(self._css_styles):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
331 self._removeStyle(tag)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
332 del self._css_styles
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
333
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
334 def xhtml_generic(self, elem, style=True, markup=None):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
335 """generic method for adding HTML elements
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
336
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
337 this method handle content, style and children parsing
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
338 @param elem(ET.Element): element to add
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
339 @param style(bool): if True handle style attribute (CSS)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
340 @param markup(tuple[unicode, (unicode, None)], None): kivy markup to use
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
341 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
342 # we first add markup and CSS style
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
343 if markup is not None:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
344 if isinstance(markup, basestring):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
345 tag, value = markup, None
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
346 else:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
347 tag, value = markup
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
348 self._addStyle(tag, value)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
349 style_ = 'style' in elem.attrib and style
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
350 if style_:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
351 self._parseCSS(elem)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
352
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
353 # then content
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
354 if elem.text:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
355 self._getLabel().text += escape_markup(elem.text)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
356
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
357 # we parse the children
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
358 for child in elem:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
359 self._callParseMethod(child)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
360
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
361 # closing CSS style and markup
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
362 if style_:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
363 self._closeCSS()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
364 if markup is not None:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
365 self._removeStyle(tag)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
366
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
367 # and the tail, which is regular text
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
368 if elem.tail:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
369 self._getLabel().text += escape_markup(elem.tail)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
370
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
371 # method handling XHTML elements
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
372
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
373 def xhtml_br(self, elem):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
374 label = self._getLabel()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
375 label.text+='\n'
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
376 self.xhtml_generic(style=False)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
377
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
378 def xhtml_em(self, elem):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
379 self.xhtml_generic(elem, markup='i')
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
380
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
381 def xhtml_img(self, elem):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
382 try:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
383 src = elem.attrib['src']
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
384 except KeyError:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
385 log.warning(u"<img> element without src: {}".format(ET.tostring(elem)))
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
386 return
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
387 img = SimpleXHTMLWidgetImage(source=src)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
388 self.current_wid = img
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
389 self.add_widget(img)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
390
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
391 def xhtml_p(self, elem):
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
392 if isinstance(self.current_wid, Label):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
393 self.current_wid.text+="\n\n"
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
394 self.xhtml_generic(elem)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
395
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
396 def xhtml_span(self, elem):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
397 self.xhtml_generic(elem)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
398
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
399 def xhtml_strong(self, elem):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
400 self.xhtml_generic(elem, markup='b')
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
401
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
402 # methods handling CSS properties
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
403
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
404 def css_color(self, elem, value):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
405 self._addStyle(u"color", css_color.parse(value))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
406
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
407 def css_text_decoration(self, elem, value):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
408 if value == u'underline':
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
409 log.warning(u"{} not handled yet, it needs Kivy 1.9.2 to be released".format(value))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
410 # FIXME: activate when 1.9.2 is out
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
411 # self._addStyle('u')
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
412 elif value == u'line-through':
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
413 log.warning(u"{} not handled yet, it needs Kivy 1.9.2 to be released".format(value))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
414 # FIXME: activate when 1.9.2 is out
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
415 # self._addStyle('s')
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
416 else:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
417 log.warning(u"unhandled text decoration: {}".format(value))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
418
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
419
45
b0595a33465d chat: design improvments:
Goffi <goffi@goffi.org>
parents: 44
diff changeset
420 class MessageWidget(GridLayout):
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
421 mess_data = properties.ObjectProperty()
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
422 mess_xhtml = properties.ObjectProperty()
45
b0595a33465d chat: design improvments:
Goffi <goffi@goffi.org>
parents: 44
diff changeset
423 mess_padding = (dp(5), dp(5))
47
abb81efef3bb chat: update avatar following quick frontend improvments
Goffi <goffi@goffi.org>
parents: 46
diff changeset
424 avatar = properties.ObjectProperty()
abb81efef3bb chat: update avatar following quick frontend improvments
Goffi <goffi@goffi.org>
parents: 46
diff changeset
425
abb81efef3bb chat: update avatar following quick frontend improvments
Goffi <goffi@goffi.org>
parents: 46
diff changeset
426 def __init__(self, **kwargs):
abb81efef3bb chat: update avatar following quick frontend improvments
Goffi <goffi@goffi.org>
parents: 46
diff changeset
427 super(MessageWidget, self).__init__(**kwargs)
abb81efef3bb chat: update avatar following quick frontend improvments
Goffi <goffi@goffi.org>
parents: 46
diff changeset
428 self.mess_data.widgets.add(self)
44
7819e9efa250 chat: avatar and nick are now displayed, need further aesthetic improvments
Goffi <goffi@goffi.org>
parents: 42
diff changeset
429
7819e9efa250 chat: avatar and nick are now displayed, need further aesthetic improvments
Goffi <goffi@goffi.org>
parents: 42
diff changeset
430 @property
7819e9efa250 chat: avatar and nick are now displayed, need further aesthetic improvments
Goffi <goffi@goffi.org>
parents: 42
diff changeset
431 def chat(self):
7819e9efa250 chat: avatar and nick are now displayed, need further aesthetic improvments
Goffi <goffi@goffi.org>
parents: 42
diff changeset
432 """return parent Chat instance"""
7819e9efa250 chat: avatar and nick are now displayed, need further aesthetic improvments
Goffi <goffi@goffi.org>
parents: 42
diff changeset
433 return self.mess_data.parent
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
434
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
435 @property
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
436 def message(self):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
437 """Return currently displayed message"""
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
438 return self.mess_data.main_message
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
439
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
440 @property
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
441 def message_xhtml(self):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
442 """Return currently displayed message"""
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
443 return self.mess_data.main_message_xhtml
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
444
45
b0595a33465d chat: design improvments:
Goffi <goffi@goffi.org>
parents: 44
diff changeset
445 def widthAdjust(self):
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
446 """this widget grows up with its children"""
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
447 pass
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
448 # parent = self.mess_xhtml.parent
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
449 # padding_x = self.mess_padding[0]
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
450 # text_width, text_height = self.mess_xhtml.texture_size
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
451 # if text_width > parent.width:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
452 # self.mess_xhtml.text_size = (parent.width - padding_x, None)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
453 # self.text_max = text_width
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
454 # elif self.mess_xhtml.text_size[0] is not None and text_width < parent.width - padding_x:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
455 # if text_width < self.text_max:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
456 # self.mess_xhtml.text_size = (None, None)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
457 # else:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
458 # self.mess_xhtml.text_size = (parent.width - padding_x, None)
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
459
54
514c187afebc chat: changed udpate to use dict instead of single key/value
Goffi <goffi@goffi.org>
parents: 47
diff changeset
460 def update(self, update_dict):
514c187afebc chat: changed udpate to use dict instead of single key/value
Goffi <goffi@goffi.org>
parents: 47
diff changeset
461 if 'avatar' in update_dict:
514c187afebc chat: changed udpate to use dict instead of single key/value
Goffi <goffi@goffi.org>
parents: 47
diff changeset
462 self.avatar.source = update_dict['avatar']
47
abb81efef3bb chat: update avatar following quick frontend improvments
Goffi <goffi@goffi.org>
parents: 46
diff changeset
463
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
464
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
465 class MessageInputWidget(TextInput):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
466
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
467 def _key_down(self, key, repeat=False):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
468 displayed_str, internal_str, internal_action, scale = key
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
469 if internal_action == 'enter':
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
470 self.dispatch('on_text_validate')
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
471 else:
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
472 super(MessageInputWidget, self)._key_down(key, repeat)
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
473
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
474
45
b0595a33465d chat: design improvments:
Goffi <goffi@goffi.org>
parents: 44
diff changeset
475 class MessagesWidget(GridLayout):
b0595a33465d chat: design improvments:
Goffi <goffi@goffi.org>
parents: 44
diff changeset
476 pass
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
477
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
478
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
479 class Chat(quick_chat.QuickChat, cagou_widget.CagouWidget):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
480
46
d6a63942d5ad chat: fixed MUC joining following changes in backend
Goffi <goffi@goffi.org>
parents: 45
diff changeset
481 def __init__(self, host, target, type_=C.CHAT_ONE2ONE, nick=None, occupants=None, subject=None, profiles=None):
d6a63942d5ad chat: fixed MUC joining following changes in backend
Goffi <goffi@goffi.org>
parents: 45
diff changeset
482 quick_chat.QuickChat.__init__(self, host, target, type_, nick, occupants, subject, profiles=profiles)
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
483 cagou_widget.CagouWidget.__init__(self)
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
484 self.header_input.hint_text = u"You are talking with {}".format(target)
37
6cf08d0ee460 chat: forbid scrolling on X axis + don't delete widget until explicitly requested (with force attribute)
Goffi <goffi@goffi.org>
parents: 35
diff changeset
485 scroll_view = ScrollView(size_hint=(1,0.8), scroll_y=0, do_scroll_x=False)
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
486 self.messages_widget = MessagesWidget()
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
487 scroll_view.add_widget(self.messages_widget)
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
488 self.add_widget(scroll_view)
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
489 message_input = MessageInputWidget()
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
490 message_input.bind(on_text_validate=self.onSend)
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
491 self.add_widget(message_input)
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
492 self.postInit()
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
493
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
494 @classmethod
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
495 def factory(cls, plugin_info, target, profiles):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
496 profiles = list(profiles)
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
497 if len(profiles) > 1:
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
498 raise NotImplementedError(u"Multi-profiles is not available yet for chat")
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
499 if target is None:
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
500 target = G.host.profiles[profiles[0]].whoami
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
501 return G.host.widgets.getOrCreateWidget(cls, target, on_new_widget=None, on_existing_widget=C.WIDGET_RECREATE, profiles=profiles)
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
502
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
503 def messageDataConverter(self, idx, mess_id):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
504 return {"mess_data": self.messages[mess_id]}
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
505
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
506 def _onHistoryPrinted(self):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
507 """Refresh or scroll down the focus after the history is printed"""
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
508 # self.adapter.data = self.messages
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
509 for mess_data in self.messages.itervalues():
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
510 self.appendMessage(mess_data)
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
511 super(Chat, self)._onHistoryPrinted()
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
512
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
513 def createMessage(self, message):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
514 self.appendMessage(message)
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
515
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
516 def appendMessage(self, mess_data):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
517 self.messages_widget.add_widget(MessageWidget(mess_data=mess_data))
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
518
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
519 def onSend(self, input_widget):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
520 G.host.messageSend(
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
521 self.target,
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
522 {'': input_widget.text}, # TODO: handle language
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
523 mess_type = C.MESS_TYPE_GROUPCHAT if self.type == C.CHAT_GROUP else C.MESS_TYPE_CHAT, # TODO: put this in QuickChat
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
524 profile_key=self.profile
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
525 )
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
526 input_widget.text = ''
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
527
46
d6a63942d5ad chat: fixed MUC joining following changes in backend
Goffi <goffi@goffi.org>
parents: 45
diff changeset
528 def _mucJoinCb(self, joined_data):
d6a63942d5ad chat: fixed MUC joining following changes in backend
Goffi <goffi@goffi.org>
parents: 45
diff changeset
529 joined, room_jid_s, occupants, user_nick, subject, profile = joined_data
d6a63942d5ad chat: fixed MUC joining following changes in backend
Goffi <goffi@goffi.org>
parents: 45
diff changeset
530 self.host.mucRoomJoinedHandler(*joined_data[1:])
d6a63942d5ad chat: fixed MUC joining following changes in backend
Goffi <goffi@goffi.org>
parents: 45
diff changeset
531 jid_ = jid.JID(room_jid_s)
42
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
532 self.changeWidget(jid_)
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
533
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
534 def _mucJoinEb(self, failure):
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
535 log.warning(u"Can't join room: {}".format(failure))
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
536
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
537 def changeWidget(self, jid_):
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
538 """change current widget for a new one with given jid
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
539
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
540 @param jid_(jid.JID): jid of the widget to create
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
541 """
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
542 plugin_info = G.host.getPluginInfo(main=Chat)
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
543 factory = plugin_info['factory']
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
544 G.host.switchWidget(self, factory(plugin_info, jid_, profiles=[self.profile]))
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
545 self.header_input.text = ''
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
546
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
547 def onHeaderInput(self):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
548 text = self.header_input.text.strip()
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
549 try:
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
550 if text.count(u'@') != 1 or text.count(u' '):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
551 raise ValueError
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
552 jid_ = jid.JID(text)
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
553 except ValueError:
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
554 log.info(u"entered text is not a jid")
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
555 return
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
556
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
557 def discoCb(disco):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
558 # TODO: check if plugin XEP-0045 is activated
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
559 if "conference" in [i[0] for i in disco[1]]:
42
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
560 G.host.bridge.mucJoin(unicode(jid_), "", "", self.profile, callback=self._mucJoinCb, errback=self._mucJoinEb)
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
561 else:
42
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
562 self.changeWidget(jid_)
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
563
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
564 def discoEb(failure):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
565 log.warning(u"Disco failure, ignore this text: {}".format(failure))
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
566
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
567 G.host.bridge.discoInfos(jid_.domain, self.profile, callback=discoCb, errback=discoEb)
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
568
37
6cf08d0ee460 chat: forbid scrolling on X axis + don't delete widget until explicitly requested (with force attribute)
Goffi <goffi@goffi.org>
parents: 35
diff changeset
569 def onDelete(self, force=False):
6cf08d0ee460 chat: forbid scrolling on X axis + don't delete widget until explicitly requested (with force attribute)
Goffi <goffi@goffi.org>
parents: 35
diff changeset
570 if force==True:
47
abb81efef3bb chat: update avatar following quick frontend improvments
Goffi <goffi@goffi.org>
parents: 46
diff changeset
571 return super(Chat, self).onDelete()
37
6cf08d0ee460 chat: forbid scrolling on X axis + don't delete widget until explicitly requested (with force attribute)
Goffi <goffi@goffi.org>
parents: 35
diff changeset
572 if len(list(G.host.widgets.getWidgets(self.__class__, self.target, profiles=self.profiles))) > 1:
6cf08d0ee460 chat: forbid scrolling on X axis + don't delete widget until explicitly requested (with force attribute)
Goffi <goffi@goffi.org>
parents: 35
diff changeset
573 # we don't keep duplicate widgets
47
abb81efef3bb chat: update avatar following quick frontend improvments
Goffi <goffi@goffi.org>
parents: 46
diff changeset
574 return super(Chat, self).onDelete()
37
6cf08d0ee460 chat: forbid scrolling on X axis + don't delete widget until explicitly requested (with force attribute)
Goffi <goffi@goffi.org>
parents: 35
diff changeset
575 return False
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
576
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
577
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
578 PLUGIN_INFO["factory"] = Chat.factory
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
579 quick_widgets.register(quick_chat.QuickChat, Chat)