annotate src/cagou/plugins/plugin_wid_chat.py @ 105:ce6ef88f2cff

chat: avatar improvments: - avatar source is not set anymore in kv but on MessageWidget init, so None value can be handled correclty - Message widget add itself to mess_data before parsing kv, so call to properties in kv can update the widget correctly (specially important for embedded bridge)
author Goffi <goffi@goffi.org>
date Sun, 15 Jan 2017 18:02:53 +0100
parents c601e3d40342
children 9909ed7a7a20
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
78
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
25 from kivy.uix.boxlayout import BoxLayout
45
b0595a33465d chat: design improvments:
Goffi <goffi@goffi.org>
parents: 44
diff changeset
26 from kivy.uix.gridlayout import GridLayout
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
27 from kivy.uix.stacklayout import StackLayout
22
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
45
b0595a33465d chat: design improvments:
Goffi <goffi@goffi.org>
parents: 44
diff changeset
30 from kivy.metrics import dp
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
31 from kivy.utils import escape_markup
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
32 from kivy import properties
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
33 from sat_frontends.quick_frontend import quick_widgets
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
34 from sat_frontends.quick_frontend import quick_chat
100
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
35 from sat_frontends.tools import jid, css_color, strings as sat_strings
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
36 from cagou.core import cagou_widget
102
20251d926cc2 chat: fixed bad size_hint setting on XHTML
Goffi <goffi@goffi.org>
parents: 100
diff changeset
37 from cagou.core.image import Image, AsyncImage
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
38 from cagou import G
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
39 from xml.etree import ElementTree as ET
100
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
40 import webbrowser
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"),
90
9a6121722669 chat, contact_list, selector: use of new icons from muchoslava
Goffi <goffi@goffi.org>
parents: 88
diff changeset
47 "icon_small": u"{media}/icons/muchoslava/png/chat_new_32.png",
9a6121722669 chat, contact_list, selector: use of new icons from muchoslava
Goffi <goffi@goffi.org>
parents: 88
diff changeset
48 "icon_medium": u"{media}/icons/muchoslava/png/chat_new_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):
100
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
64
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
65 def _addUrlMarkup(self, text):
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
66 text_elts = []
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
67 idx = 0
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
68 links = 0
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
69 while True:
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
70 m = sat_strings.RE_URL.search(text[idx:])
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
71 if m is not None:
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
72 text_elts.append(escape_markup(m.string[0:m.start()]))
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
73 link_key = u'link_' + unicode(links)
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
74 url = m.group()
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
75 text_elts.append(u'[color=5500ff][ref={link}]{url}[/ref][/color]'.format(
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
76 link = link_key,
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
77 url = url
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
78 ))
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
79 if not links:
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
80 self.ref_urls = {link_key: url}
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
81 else:
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
82 self.ref_urls[link_key] = url
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
83 links += 1
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
84 idx += m.end()
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
85 else:
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
86 if links:
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
87 text_elts.append(escape_markup(text[idx:]))
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
88 self.markup = True
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
89 self.text = u''.join(text_elts)
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
90 break
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
91
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
92 def on_text(self, instance, text):
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
93 # do NOT call the method if self.markup is set
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
94 # this would result in infinite loop (because self.text
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
95 # is changed if an URL is found, and in this case markup too)
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
96 if text and not self.markup:
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
97 self._addUrlMarkup(text)
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
98
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
99 def on_ref_press(self, ref):
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
100 url = self.ref_urls[ref]
d7447c585603 chat: added url detection on text messages
Goffi <goffi@goffi.org>
parents: 98
diff changeset
101 webbrowser.open(url)
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
102
59
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
103
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
104 class SimpleXHTMLWidgetText(Label):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
105 pass
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
106
59
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
107
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
108 class SimpleXHTMLWidgetImage(AsyncImage):
59
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
109 # following properties are desired height/width
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
110 # i.e. the ones specified in height/width attributes of <img>
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
111 # (or wanted for whatever reason)
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
112 # set to 0 to ignore them
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
113 target_height = properties.NumericProperty()
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
114 target_width = properties.NumericProperty()
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
115
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
116 def _get_parent_container(self):
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
117 """get parent SimpleXHTMLWidget instance
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
118
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
119 @param warning(bool): if True display a log.error if nothing found
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
120 @return (SimpleXHTMLWidget, None): found SimpleXHTMLWidget instance
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
121 """
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
122 parent = self.parent
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
123 while parent and not isinstance(parent, SimpleXHTMLWidget):
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
124 parent = parent.parent
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
125 if parent is None:
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
126 log.error(u"no SimpleXHTMLWidget parent found")
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
127 return parent
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
128
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
129 def _on_source_load(self, value):
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
130 # this method is called when image is loaded
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
131 super(SimpleXHTMLWidgetImage, self)._on_source_load(value)
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
132 if self.parent is not None:
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
133 container = self._get_parent_container()
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
134 # image is loaded, we need to recalculate size
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
135 self.on_container_width(container, container.width)
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
136
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
137 def on_container_width(self, container, container_width):
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
138 """adapt size according to container width
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
139
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
140 called when parent container (SimpleXHTMLWidget) width change
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
141 """
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
142 target_size = (self.target_width or self.texture.width, self.target_height or self.texture.height)
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
143 padding = container.padding
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
144 padding_h = (padding[0] + padding[2]) if len(padding) == 4 else padding[0]
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
145 width = container_width - padding_h
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
146 if target_size[0] < width:
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
147 self.size = target_size
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
148 else:
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
149 height = width / self.image_ratio
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
150 self.size = (width, height)
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
151
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
152 def on_parent(self, instance, parent):
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
153 if parent is not None:
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
154 container = self._get_parent_container()
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
155 container.bind(width=self.on_container_width)
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
156
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
157
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
158 class SimpleXHTMLWidget(StackLayout):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
159 """widget handling simple XHTML parsing"""
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
160 xhtml = properties.StringProperty()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
161 color = properties.ListProperty([1, 1, 1, 1])
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
162 # XXX: bold is only used for escaped text
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
163 bold = properties.BooleanProperty(False)
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
164 content_width = properties.NumericProperty(0)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
165
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
166 # text/XHTML input
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
167
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
168 def on_xhtml(self, instance, xhtml):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
169 """parse xhtml and set content accordingly
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
170
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
171 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
172 will be used
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
173 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
174 self.clear_widgets()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
175 if isinstance(xhtml, Escape):
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
176 label = SimpleXHTMLWidgetEscapedText(text=xhtml, color=self.color)
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
177 self.bind(color=label.setter('color'))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
178 self.bind(bold=label.setter('bold'))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
179 self.add_widget(label)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
180 else:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
181 xhtml = ET.fromstring(xhtml.encode('utf-8'))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
182 self.current_wid = None
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
183 self.styles = []
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
184 self._callParseMethod(xhtml)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
185
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
186 def escape(self, text):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
187 """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
188 return Escape(text)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
189
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
190 # sizing
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
191
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
192 def on_width(self, instance, width):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
193 if len(self.children) == 1:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
194 wid = self.children[0]
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
195 if isinstance(wid, Label):
68
4a1e1012337e chat: fixed chat messages width
Goffi <goffi@goffi.org>
parents: 67
diff changeset
196 # we have simple text
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
197 try:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
198 full_width = wid._full_width
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
199 except AttributeError:
68
4a1e1012337e chat: fixed chat messages width
Goffi <goffi@goffi.org>
parents: 67
diff changeset
200 # on first time, we need the required size
4a1e1012337e chat: fixed chat messages width
Goffi <goffi@goffi.org>
parents: 67
diff changeset
201 # for the full text, without width limit
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
202 wid.size_hint = (None, None)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
203 wid.texture_update()
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
204 full_width = wid._full_width = wid.texture_size[0]
68
4a1e1012337e chat: fixed chat messages width
Goffi <goffi@goffi.org>
parents: 67
diff changeset
205
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
206 if full_width > width:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
207 wid.text_size = width, None
68
4a1e1012337e chat: fixed chat messages width
Goffi <goffi@goffi.org>
parents: 67
diff changeset
208 wid.width = width
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
209 else:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
210 wid.text_size = None, None
68
4a1e1012337e chat: fixed chat messages width
Goffi <goffi@goffi.org>
parents: 67
diff changeset
211 wid.texture_update()
4a1e1012337e chat: fixed chat messages width
Goffi <goffi@goffi.org>
parents: 67
diff changeset
212 wid.width = wid.texture_size[0]
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
213 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
214 else:
102
20251d926cc2 chat: fixed bad size_hint setting on XHTML
Goffi <goffi@goffi.org>
parents: 100
diff changeset
215 wid.size_hint = (1, None)
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
216 wid.height = 100
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
217 self.content_width = self.width
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
218 else:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
219 self._do_complexe_sizing(width)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
220
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
221 def _do_complexe_sizing(self, width):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
222 try:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
223 self.splitted
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
224 except AttributeError:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
225 # 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
226 log.debug(u"split start")
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
227 children = self.children[::-1]
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
228 self.clear_widgets()
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
229 for child in children:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
230 if isinstance(child, Label):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
231 log.debug(u"label before split: {}".format(child.text))
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
232 styles = []
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
233 tag = False
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
234 new_text = []
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
235 current_tag = []
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
236 current_value = []
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
237 current_wid = self._createText()
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
238 value = False
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
239 close = False
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
240 # 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
241 # on each new word (actually each space)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
242 # FIXME: handle '\n' and other white chars
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
243 for c in child.text:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
244 if tag:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
245 # we are parsing a markup tag
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
246 if c == u']':
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
247 current_tag_s = u''.join(current_tag)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
248 current_style = (current_tag_s, u''.join(current_value))
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
249 if close:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
250 for idx, s in enumerate(reversed(styles)):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
251 if s[0] == current_tag_s:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
252 del styles[len(styles) - idx - 1]
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
253 break
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
254 else:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
255 styles.append(current_style)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
256 current_tag = []
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
257 current_value = []
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
258 tag = False
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
259 value = False
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
260 close = False
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
261 elif c == u'/':
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
262 close = True
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
263 elif c == u'=':
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
264 value = True
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
265 elif value:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
266 current_value.append(c)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
267 else:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
268 current_tag.append(c)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
269 new_text.append(c)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
270 else:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
271 # we are parsing regular text
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
272 if c == u'[':
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
273 new_text.append(c)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
274 tag = True
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
275 elif c == u' ':
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
276 # new word, we do a new widget
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
277 new_text.append(u' ')
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
278 for t, v in reversed(styles):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
279 new_text.append(u'[/{}]'.format(t))
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
280 current_wid.text = u''.join(new_text)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
281 new_text = []
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
282 self.add_widget(current_wid)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
283 log.debug(u"new widget: {}".format(current_wid.text))
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
284 current_wid = self._createText()
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
285 for t, v in styles:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
286 new_text.append(u'[{tag}{value}]'.format(
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
287 tag = t,
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
288 value = u'={}'.format(v) if v else u''))
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
289 else:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
290 new_text.append(c)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
291 if current_wid.text:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
292 # we may have a remaining widget after the parsing
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
293 close_styles = []
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
294 for t, v in reversed(styles):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
295 close_styles.append(u'[/{}]'.format(t))
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
296 current_wid.text = u''.join(close_styles)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
297 self.add_widget(current_wid)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
298 log.debug(u"new widget: {}".format(current_wid.text))
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
299 else:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
300 # non Label widgets, we just add them
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
301 self.add_widget(child)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
302 self.splitted = True
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
303 log.debug(u"split OK")
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
304
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
305 # we now set the content width
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
306 # FIXME: for now we just use the full width
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
307 self.content_width = width
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
308
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
309 # XHTML parsing methods
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
310
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
311 def _callParseMethod(self, e):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
312 """call the suitable method to parse the element
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
313
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
314 self.xhtml_[tag] will be called if it exists, else
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
315 self.xhtml_generic will be used
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
316 @param e(ET.Element): element to parse
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
317 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
318 try:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
319 method = getattr(self, "xhtml_{}".format(e.tag))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
320 except AttributeError:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
321 log.warning(u"Unhandled XHTML tag: {}".format(e.tag))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
322 method = self.xhtml_generic
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
323 method(e)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
324
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
325 def _addStyle(self, tag, value=None, append_to_list=True):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
326 """add a markup style to label
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
327
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
328 @param tag(unicode): markup tag
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
329 @param value(unicode): markup value if suitable
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
330 @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
331 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
332 should most probably be set to True
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 label = self._getLabel()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
335 label.text += u'[{tag}{value}]'.format(
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
336 tag = tag,
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
337 value = u'={}'.format(value) if value else ''
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
338 )
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
339 if append_to_list:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
340 self.styles.append((tag, value))
57
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 def _removeStyle(self, tag, remove_from_list=True):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
343 """remove a markup style from the label
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
344
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
345 @param tag(unicode): markup tag to remove
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
346 @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
347 should most probably be set to True
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
348 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
349 label = self._getLabel()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
350 label.text += u'[/{tag}]'.format(
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
351 tag = tag
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 if remove_from_list:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
354 for rev_idx, style in enumerate(reversed(self.styles)):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
355 if style[0] == tag:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
356 tag_idx = len(self.styles) - 1 - rev_idx
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
357 del self.styles[tag_idx]
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
358 break
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
359
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
360 def _getLabel(self):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
361 """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
362 if not isinstance(self.current_wid, Label):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
363 self._addLabel()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
364 return self.current_wid
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
365
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
366 def _addLabel(self):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
367 """add a new Label
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
368
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
369 current styles will be closed and reopened if needed
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 self._closeLabel()
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
372 self.current_wid = self._createText()
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
373 for tag, value in self.styles:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
374 self._addStyle(tag, value, append_to_list=False)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
375 self.add_widget(self.current_wid)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
376
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
377 def _createText(self):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
378 label = SimpleXHTMLWidgetText(color=self.color, markup=True)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
379 self.bind(color=label.setter('color'))
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
380 label.bind(texture_size=label.setter('size'))
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
381 return label
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
382
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
383 def _closeLabel(self):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
384 """close current style tags in current label
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
385
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
386 needed when you change label to keep style between
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
387 different widgets
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
388 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
389 if isinstance(self.current_wid, Label):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
390 for tag, value in reversed(self.styles):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
391 self._removeStyle(tag, remove_from_list=False)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
392
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
393 def _parseCSS(self, e):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
394 """parse CSS found in "style" attribute of element
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 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
397 @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
398 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
399 styles_limit = len(self.styles)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
400 styles = e.attrib['style'].split(u';')
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
401 for style in styles:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
402 try:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
403 prop, value = style.split(u':')
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
404 except ValueError:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
405 log.warning(u"can't parse style: {}".format(style))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
406 continue
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
407 prop = prop.strip().replace(u'-', '_')
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
408 value = value.strip()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
409 try:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
410 method = getattr(self, "css_{}".format(prop))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
411 except AttributeError:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
412 log.warning(u"Unhandled CSS: {}".format(prop))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
413 else:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
414 method(e, value)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
415 self._css_styles = self.styles[styles_limit:]
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
416
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
417 def _closeCSS(self):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
418 """removed CSS styles
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
419
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
420 styles in self._css_styles will be removed
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
421 and the attribute will be deleted
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
422 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
423 for tag, dummy in reversed(self._css_styles):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
424 self._removeStyle(tag)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
425 del self._css_styles
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
426
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
427 def xhtml_generic(self, elem, style=True, markup=None):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
428 """generic method for adding HTML elements
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
429
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
430 this method handle content, style and children parsing
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
431 @param elem(ET.Element): element to add
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
432 @param style(bool): if True handle style attribute (CSS)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
433 @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
434 """
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
435 # we first add markup and CSS style
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
436 if markup is not None:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
437 if isinstance(markup, basestring):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
438 tag, value = markup, None
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
439 else:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
440 tag, value = markup
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
441 self._addStyle(tag, value)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
442 style_ = 'style' in elem.attrib and style
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
443 if style_:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
444 self._parseCSS(elem)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
445
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
446 # then content
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
447 if elem.text:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
448 self._getLabel().text += escape_markup(elem.text)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
449
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
450 # we parse the children
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
451 for child in elem:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
452 self._callParseMethod(child)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
453
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
454 # closing CSS style and markup
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
455 if style_:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
456 self._closeCSS()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
457 if markup is not None:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
458 self._removeStyle(tag)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
459
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
460 # and the tail, which is regular text
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
461 if elem.tail:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
462 self._getLabel().text += escape_markup(elem.tail)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
463
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
464 # method handling XHTML elements
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
465
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
466 def xhtml_br(self, elem):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
467 label = self._getLabel()
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
468 label.text+='\n'
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
469 self.xhtml_generic(style=False)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
470
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
471 def xhtml_em(self, elem):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
472 self.xhtml_generic(elem, markup='i')
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
473
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
474 def xhtml_img(self, elem):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
475 try:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
476 src = elem.attrib['src']
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
477 except KeyError:
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
478 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
479 return
59
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
480 try:
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
481 target_height = int(elem.get(u'height', 0))
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
482 except ValueError:
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
483 log.warning(u"Can't parse image height: {}".format(elem.get(u'height')))
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
484 target_height = 0
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
485 try:
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
486 target_width = int(elem.get(u'width', 0))
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
487 except ValueError:
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
488 log.warning(u"Can't parse image width: {}".format(elem.get(u'width')))
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
489 target_width = 0
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
490
2aa44a82d0e7 chat: XHTML image size handling:
Goffi <goffi@goffi.org>
parents: 58
diff changeset
491 img = SimpleXHTMLWidgetImage(source=src, target_height=target_height, target_width=target_width)
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
492 self.current_wid = img
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
493 self.add_widget(img)
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
494
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
495 def xhtml_p(self, elem):
58
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
496 if isinstance(self.current_wid, Label):
7aa2ffff9067 chat: <img/> tag handling first draft:
Goffi <goffi@goffi.org>
parents: 57
diff changeset
497 self.current_wid.text+="\n\n"
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
498 self.xhtml_generic(elem)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
499
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
500 def xhtml_span(self, elem):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
501 self.xhtml_generic(elem)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
502
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
503 def xhtml_strong(self, elem):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
504 self.xhtml_generic(elem, markup='b')
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
505
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
506 # methods handling CSS properties
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
507
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
508 def css_color(self, elem, value):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
509 self._addStyle(u"color", css_color.parse(value))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
510
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
511 def css_text_decoration(self, elem, value):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
512 if value == u'underline':
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
513 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
514 # FIXME: activate when 1.9.2 is out
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
515 # self._addStyle('u')
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
516 elif value == u'line-through':
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
517 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
518 # FIXME: activate when 1.9.2 is out
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
519 # self._addStyle('s')
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
520 else:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
521 log.warning(u"unhandled text decoration: {}".format(value))
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
522
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
523
45
b0595a33465d chat: design improvments:
Goffi <goffi@goffi.org>
parents: 44
diff changeset
524 class MessageWidget(GridLayout):
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
525 mess_data = properties.ObjectProperty()
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
526 mess_xhtml = properties.ObjectProperty()
45
b0595a33465d chat: design improvments:
Goffi <goffi@goffi.org>
parents: 44
diff changeset
527 mess_padding = (dp(5), dp(5))
47
abb81efef3bb chat: update avatar following quick frontend improvments
Goffi <goffi@goffi.org>
parents: 46
diff changeset
528 avatar = properties.ObjectProperty()
103
c601e3d40342 chat: display delivery receipt (with a green check mark)
Goffi <goffi@goffi.org>
parents: 102
diff changeset
529 delivery = properties.ObjectProperty()
47
abb81efef3bb chat: update avatar following quick frontend improvments
Goffi <goffi@goffi.org>
parents: 46
diff changeset
530
abb81efef3bb chat: update avatar following quick frontend improvments
Goffi <goffi@goffi.org>
parents: 46
diff changeset
531 def __init__(self, **kwargs):
105
ce6ef88f2cff chat: avatar improvments:
Goffi <goffi@goffi.org>
parents: 103
diff changeset
532 # self must be registered in widgets before kv is parsed
ce6ef88f2cff chat: avatar improvments:
Goffi <goffi@goffi.org>
parents: 103
diff changeset
533 kwargs['mess_data'].widgets.add(self)
47
abb81efef3bb chat: update avatar following quick frontend improvments
Goffi <goffi@goffi.org>
parents: 46
diff changeset
534 super(MessageWidget, self).__init__(**kwargs)
105
ce6ef88f2cff chat: avatar improvments:
Goffi <goffi@goffi.org>
parents: 103
diff changeset
535 avatar_path = self.mess_data.avatar
ce6ef88f2cff chat: avatar improvments:
Goffi <goffi@goffi.org>
parents: 103
diff changeset
536 if avatar_path is not None:
ce6ef88f2cff chat: avatar improvments:
Goffi <goffi@goffi.org>
parents: 103
diff changeset
537 self.avatar.source = avatar_path
44
7819e9efa250 chat: avatar and nick are now displayed, need further aesthetic improvments
Goffi <goffi@goffi.org>
parents: 42
diff changeset
538
7819e9efa250 chat: avatar and nick are now displayed, need further aesthetic improvments
Goffi <goffi@goffi.org>
parents: 42
diff changeset
539 @property
7819e9efa250 chat: avatar and nick are now displayed, need further aesthetic improvments
Goffi <goffi@goffi.org>
parents: 42
diff changeset
540 def chat(self):
7819e9efa250 chat: avatar and nick are now displayed, need further aesthetic improvments
Goffi <goffi@goffi.org>
parents: 42
diff changeset
541 """return parent Chat instance"""
7819e9efa250 chat: avatar and nick are now displayed, need further aesthetic improvments
Goffi <goffi@goffi.org>
parents: 42
diff changeset
542 return self.mess_data.parent
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
543
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
544 @property
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
545 def message(self):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
546 """Return currently displayed message"""
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
547 return self.mess_data.main_message
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
548
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
549 @property
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
550 def message_xhtml(self):
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
551 """Return currently displayed message"""
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
552 return self.mess_data.main_message_xhtml
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
553
45
b0595a33465d chat: design improvments:
Goffi <goffi@goffi.org>
parents: 44
diff changeset
554 def widthAdjust(self):
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
555 """this widget grows up with its children"""
57
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
556 pass
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
557 # parent = self.mess_xhtml.parent
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
558 # padding_x = self.mess_padding[0]
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
559 # text_width, text_height = self.mess_xhtml.texture_size
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
560 # if text_width > parent.width:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
561 # self.mess_xhtml.text_size = (parent.width - padding_x, None)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
562 # self.text_max = text_width
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
563 # 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
564 # if text_width < self.text_max:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
565 # self.mess_xhtml.text_size = (None, None)
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
566 # else:
a51ea7874e43 chat: XHTML parsing first draft:
Goffi <goffi@goffi.org>
parents: 54
diff changeset
567 # self.mess_xhtml.text_size = (parent.width - padding_x, None)
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
568
54
514c187afebc chat: changed udpate to use dict instead of single key/value
Goffi <goffi@goffi.org>
parents: 47
diff changeset
569 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
570 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
571 self.avatar.source = update_dict['avatar']
103
c601e3d40342 chat: display delivery receipt (with a green check mark)
Goffi <goffi@goffi.org>
parents: 102
diff changeset
572 if 'status' in update_dict:
c601e3d40342 chat: display delivery receipt (with a green check mark)
Goffi <goffi@goffi.org>
parents: 102
diff changeset
573 status = update_dict['status']
c601e3d40342 chat: display delivery receipt (with a green check mark)
Goffi <goffi@goffi.org>
parents: 102
diff changeset
574 self.delivery.text = u'\u2714' if status == 'delivered' else u''
47
abb81efef3bb chat: update avatar following quick frontend improvments
Goffi <goffi@goffi.org>
parents: 46
diff changeset
575
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
576
78
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
577 class MessageInputBox(BoxLayout):
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
578 pass
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
579
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
580
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
581 class MessageInputWidget(TextInput):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
582
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
583 def _key_down(self, key, repeat=False):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
584 displayed_str, internal_str, internal_action, scale = key
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
585 if internal_action == 'enter':
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
586 self.dispatch('on_text_validate')
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
587 else:
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
588 super(MessageInputWidget, self)._key_down(key, repeat)
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
589
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
590
45
b0595a33465d chat: design improvments:
Goffi <goffi@goffi.org>
parents: 44
diff changeset
591 class MessagesWidget(GridLayout):
b0595a33465d chat: design improvments:
Goffi <goffi@goffi.org>
parents: 44
diff changeset
592 pass
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
593
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
594
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
595 class Chat(quick_chat.QuickChat, cagou_widget.CagouWidget):
78
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
596 message_input = properties.ObjectProperty()
86
c711be670ecd core, chat: upload plugin system:
Goffi <goffi@goffi.org>
parents: 78
diff changeset
597 messages_widget = properties.ObjectProperty()
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
598
46
d6a63942d5ad chat: fixed MUC joining following changes in backend
Goffi <goffi@goffi.org>
parents: 45
diff changeset
599 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
600 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
601 cagou_widget.CagouWidget.__init__(self)
67
5f7f72c2635f chat: shortened chat header
Goffi <goffi@goffi.org>
parents: 59
diff changeset
602 self.header_input.hint_text = u"{}".format(target)
78
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
603 self.host.addListener('progressError', self.onProgressError, profiles)
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
604 self.host.addListener('progressFinished', self.onProgressFinished, profiles)
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
605 self._waiting_pids = {} # waiting progress ids
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
606 self.postInit()
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
607
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
608 @classmethod
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
609 def factory(cls, plugin_info, target, profiles):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
610 profiles = list(profiles)
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
611 if len(profiles) > 1:
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
612 raise NotImplementedError(u"Multi-profiles is not available yet for chat")
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
613 if target is None:
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
614 target = G.host.profiles[profiles[0]].whoami
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
615 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
616
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
617 def messageDataConverter(self, idx, mess_id):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
618 return {"mess_data": self.messages[mess_id]}
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
619
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
620 def _onHistoryPrinted(self):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
621 """Refresh or scroll down the focus after the history is printed"""
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
622 # self.adapter.data = self.messages
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
623 for mess_data in self.messages.itervalues():
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
624 self.appendMessage(mess_data)
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
625 super(Chat, self)._onHistoryPrinted()
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
626
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
627 def createMessage(self, message):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
628 self.appendMessage(message)
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
629
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
630 def appendMessage(self, mess_data):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
631 self.messages_widget.add_widget(MessageWidget(mess_data=mess_data))
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
632
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
633 def onSend(self, input_widget):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
634 G.host.messageSend(
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
635 self.target,
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
636 {'': input_widget.text}, # TODO: handle language
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
637 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
638 profile_key=self.profile
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
639 )
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
640 input_widget.text = ''
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
641
78
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
642 def onProgressFinished(self, progress_id, metadata, profile):
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
643 try:
88
3dc526bb4a5a upload: plugin android gallery, first draft:
Goffi <goffi@goffi.org>
parents: 86
diff changeset
644 callback, cleaning_cb = self._waiting_pids.pop(progress_id)
78
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
645 except KeyError:
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
646 return
88
3dc526bb4a5a upload: plugin android gallery, first draft:
Goffi <goffi@goffi.org>
parents: 86
diff changeset
647 if cleaning_cb is not None:
3dc526bb4a5a upload: plugin android gallery, first draft:
Goffi <goffi@goffi.org>
parents: 86
diff changeset
648 cleaning_cb()
78
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
649 callback(metadata, profile)
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
650
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
651 def onProgressError(self, progress_id, err_msg, profile):
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
652 try:
88
3dc526bb4a5a upload: plugin android gallery, first draft:
Goffi <goffi@goffi.org>
parents: 86
diff changeset
653 dummy, cleaning_cb = self._waiting_pids[progress_id]
78
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
654 except KeyError:
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
655 return
88
3dc526bb4a5a upload: plugin android gallery, first draft:
Goffi <goffi@goffi.org>
parents: 86
diff changeset
656 else:
3dc526bb4a5a upload: plugin android gallery, first draft:
Goffi <goffi@goffi.org>
parents: 86
diff changeset
657 del self._waiting_pids[progress_id]
3dc526bb4a5a upload: plugin android gallery, first draft:
Goffi <goffi@goffi.org>
parents: 86
diff changeset
658 if cleaning_cb is not None:
3dc526bb4a5a upload: plugin android gallery, first draft:
Goffi <goffi@goffi.org>
parents: 86
diff changeset
659 cleaning_cb()
78
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
660 # TODO: display message to user
97
5d2289127bb7 menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents: 90
diff changeset
661 log.warning(u"Can't transfer file: {}".format(err_msg))
78
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
662
97
5d2289127bb7 menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents: 90
diff changeset
663 def fileTransferDone(self, metadata, profile):
5d2289127bb7 menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents: 90
diff changeset
664 log.debug("file transfered: {}".format(metadata))
78
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
665 G.host.messageSend(
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
666 self.target,
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
667 {'': metadata['url']},
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
668 mess_type = C.MESS_TYPE_GROUPCHAT if self.type == C.CHAT_GROUP else C.MESS_TYPE_CHAT,
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
669 profile_key=profile
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
670 )
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
671
97
5d2289127bb7 menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents: 90
diff changeset
672 def fileTransferCb(self, progress_data, cleaning_cb):
78
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
673 try:
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
674 progress_id = progress_data['progress']
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
675 except KeyError:
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
676 xmlui = progress_data['xmlui']
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
677 G.host.showUI(xmlui)
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
678 else:
97
5d2289127bb7 menu (upload): better menu using dedicated widget:
Goffi <goffi@goffi.org>
parents: 90
diff changeset
679 self._waiting_pids[progress_id] = (self.fileTransferDone, cleaning_cb)
78
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
680
98
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
681 def onTransferOK(self, file_path, cleaning_cb, transfer_type):
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
682 if transfer_type == C.TRANSFER_UPLOAD:
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
683 G.host.bridge.fileUpload(
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
684 file_path,
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
685 "",
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
686 "",
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
687 {"ignore_tls_errors": C.BOOL_TRUE}, # FIXME: should not be the default
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
688 self.profile,
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
689 callback = lambda progress_data: self.fileTransferCb(progress_data, cleaning_cb)
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
690 )
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
691 elif transfer_type == C.TRANSFER_SEND:
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
692 if self.type == C.CHAT_GROUP:
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
693 log.warning(u"P2P transfer is not possible for group chat")
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
694 # TODO: show an error dialog to user, or better hide the send button for MUC
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
695 else:
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
696 jid_ = self.target
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
697 if not jid_.resource:
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
698 jid_ = G.host.contact_lists[self.profile].getFullJid(jid_)
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
699 G.host.bridge.fileSend(jid_, file_path, "", "", profile=self.profile)
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
700 # TODO: notification of sending/failing
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
701 else:
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
702 raise log.error(u"transfer of type {} are not handled".format(transfer_type))
4d8c122b86a6 menu (upload): send transfer (i.e. P2P transfer) is now working
Goffi <goffi@goffi.org>
parents: 97
diff changeset
703
78
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
704
46
d6a63942d5ad chat: fixed MUC joining following changes in backend
Goffi <goffi@goffi.org>
parents: 45
diff changeset
705 def _mucJoinCb(self, joined_data):
d6a63942d5ad chat: fixed MUC joining following changes in backend
Goffi <goffi@goffi.org>
parents: 45
diff changeset
706 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
707 self.host.mucRoomJoinedHandler(*joined_data[1:])
d6a63942d5ad chat: fixed MUC joining following changes in backend
Goffi <goffi@goffi.org>
parents: 45
diff changeset
708 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
709 self.changeWidget(jid_)
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
710
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
711 def _mucJoinEb(self, failure):
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
712 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
713
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
714 def changeWidget(self, jid_):
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
715 """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
716
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
717 @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
718 """
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
719 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
720 factory = plugin_info['factory']
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
721 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
722 self.header_input.text = ''
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
723
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
724 def onHeaderInput(self):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
725 text = self.header_input.text.strip()
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
726 try:
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
727 if text.count(u'@') != 1 or text.count(u' '):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
728 raise ValueError
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
729 jid_ = jid.JID(text)
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
730 except ValueError:
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
731 log.info(u"entered text is not a jid")
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
732 return
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
733
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
734 def discoCb(disco):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
735 # TODO: check if plugin XEP-0045 is activated
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
736 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
737 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
738 else:
42
286865bc013a chat: joining MUC using header input is now working:
Goffi <goffi@goffi.org>
parents: 41
diff changeset
739 self.changeWidget(jid_)
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
740
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
741 def discoEb(failure):
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
742 log.warning(u"Disco failure, ignore this text: {}".format(failure))
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
743
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
744 G.host.bridge.discoInfos(jid_.domain, self.profile, callback=discoCb, errback=discoEb)
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
745
78
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
746 def _onDelete(self):
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
747 self.host.removeListener('progressFinished', self.onProgressFinished)
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
748 self.host.removeListener('progressError', self.onProgressError)
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
749 return super(Chat, self).onDelete()
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
750
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
751 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
752 if force==True:
78
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
753 return 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
754 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
755 # we don't keep duplicate widgets
78
46d962910801 chat: file upload first draft:
Goffi <goffi@goffi.org>
parents: 68
diff changeset
756 return 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
757 return False
22
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
758
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
759
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
760 PLUGIN_INFO["factory"] = Chat.factory
74117b733bac plugin chat: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
761 quick_widgets.register(quick_chat.QuickChat, Chat)