HtmlTextView: Fix pylint errors and minor refactoring
This commit is contained in:
parent
97310a059a
commit
eedd0c2a72
|
@ -56,34 +56,32 @@ from gajim.gui_menu_builder import get_conv_context_menu
|
||||||
|
|
||||||
log = logging.getLogger('gajim.htmlview')
|
log = logging.getLogger('gajim.htmlview')
|
||||||
|
|
||||||
__all__ = ['HtmlTextView']
|
|
||||||
|
|
||||||
whitespace_rx = re.compile('\\s+')
|
whitespace_rx = re.compile('\\s+')
|
||||||
allwhitespace_rx = re.compile('^\\s*$')
|
allwhitespace_rx = re.compile('^\\s*$')
|
||||||
|
|
||||||
# embryo of CSS classes
|
# embryo of CSS classes
|
||||||
classes = {
|
classes = {
|
||||||
#'system-message':';display: none',
|
#'system-message':';display: none',
|
||||||
'problematic': ';color: red',
|
'problematic': ';color: red',
|
||||||
}
|
}
|
||||||
|
|
||||||
# styles for elements
|
# styles for elements
|
||||||
_element_styles = {
|
_element_styles = {
|
||||||
'u' : ';text-decoration: underline',
|
'u' : ';text-decoration: underline',
|
||||||
'em' : ';font-style: oblique',
|
'em' : ';font-style: oblique',
|
||||||
'cite' : '; background-color:rgb(170,190,250);'
|
'cite' : '; background-color:rgb(170,190,250);'
|
||||||
'font-style: oblique',
|
'font-style: oblique',
|
||||||
'li' : '; margin-left: 1em; margin-right: 10%',
|
'li' : '; margin-left: 1em; margin-right: 10%',
|
||||||
'strong' : ';font-weight: bold',
|
'strong' : ';font-weight: bold',
|
||||||
'pre' : '; background-color:rgb(190,190,190);'
|
'pre' : '; background-color:rgb(190,190,190);'
|
||||||
'font-family: monospace; white-space: pre;'
|
'font-family: monospace; white-space: pre;'
|
||||||
'margin-left: 1em; margin-right: 10%',
|
'margin-left: 1em; margin-right: 10%',
|
||||||
'kbd' : ';background-color:rgb(210,210,210);'
|
'kbd' : ';background-color:rgb(210,210,210);'
|
||||||
'font-family: monospace',
|
'font-family: monospace',
|
||||||
'blockquote' : '; background-color:rgb(170,190,250);'
|
'blockquote' : '; background-color:rgb(170,190,250);'
|
||||||
'margin-left: 2em; margin-right: 10%',
|
'margin-left: 2em; margin-right: 10%',
|
||||||
'dt' : ';font-weight: bold; font-style: oblique',
|
'dt' : ';font-weight: bold; font-style: oblique',
|
||||||
'dd' : ';margin-left: 2em; font-style: oblique'
|
'dd' : ';margin-left: 2em; font-style: oblique'
|
||||||
}
|
}
|
||||||
# no difference for the moment
|
# no difference for the moment
|
||||||
_element_styles['dfn'] = _element_styles['em']
|
_element_styles['dfn'] = _element_styles['em']
|
||||||
|
@ -93,6 +91,12 @@ _element_styles['tt'] = _element_styles['kbd']
|
||||||
_element_styles['i'] = _element_styles['em']
|
_element_styles['i'] = _element_styles['em']
|
||||||
_element_styles['b'] = _element_styles['strong']
|
_element_styles['b'] = _element_styles['strong']
|
||||||
|
|
||||||
|
_supported_style_attrs = [
|
||||||
|
'background-color', 'color', 'font-family', 'font-size', 'font-style',
|
||||||
|
'font-weight', 'margin-left', 'margin-right', 'text-align',
|
||||||
|
'text-decoration', 'white-space', 'display', 'width', 'height'
|
||||||
|
]
|
||||||
|
|
||||||
# ==========
|
# ==========
|
||||||
# XEP-0071
|
# XEP-0071
|
||||||
# ==========
|
# ==========
|
||||||
|
@ -182,8 +186,9 @@ for _name in BLOCK_HEAD:
|
||||||
_num = int(_name[1])
|
_num = int(_name[1])
|
||||||
_header_size = (_num - 1) // 2
|
_header_size = (_num - 1) // 2
|
||||||
_weight = (_num - 1) % 2
|
_weight = (_num - 1) % 2
|
||||||
_element_styles[_name] = '; font-size: %s; %s' % (('large', 'medium', 'small')[_header_size],
|
_element_styles[_name] = '; font-size: %s; %s' % (
|
||||||
('font-weight: bold', 'font-style: oblique')[_weight],)
|
('large', 'medium', 'small')[_header_size],
|
||||||
|
('font-weight: bold', 'font-style: oblique')[_weight])
|
||||||
|
|
||||||
def _parse_css_color(color):
|
def _parse_css_color(color):
|
||||||
if color.startswith('rgb(') and color.endswith(')'):
|
if color.startswith('rgb(') and color.endswith(')'):
|
||||||
|
@ -216,26 +221,35 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
self.list_counters = [] # stack (top at head) of list
|
self.list_counters = [] # stack (top at head) of list
|
||||||
# counters, or None for unordered list
|
# counters, or None for unordered list
|
||||||
|
|
||||||
|
# build a dictionary mapping styles to methods
|
||||||
|
self.__style_methods = {}
|
||||||
|
for style in _supported_style_attrs:
|
||||||
|
method_names = '_parse_style_%s' % style.replace('-', '_')
|
||||||
|
self.__style_methods[style] = method_names
|
||||||
|
|
||||||
def _get_points_from_pixels(self, pixels):
|
def _get_points_from_pixels(self, pixels):
|
||||||
resolution = self.textview.get_screen().get_resolution()
|
resolution = self.textview.get_screen().get_resolution()
|
||||||
# points = pixels * 72 / resolution
|
# points = pixels * 72 / resolution
|
||||||
return pixels * 72 / resolution
|
return pixels * 72 / resolution
|
||||||
|
|
||||||
def _parse_style_color(self, tag, value):
|
@staticmethod
|
||||||
|
def _parse_style_color(tag, value):
|
||||||
color = _parse_css_color(value)
|
color = _parse_css_color(value)
|
||||||
tag.set_property('foreground-gdk', color)
|
tag.set_property('foreground-gdk', color)
|
||||||
|
|
||||||
def _parse_style_background_color(self, tag, value):
|
@staticmethod
|
||||||
|
def _parse_style_background_color(tag, value):
|
||||||
color = _parse_css_color(value)
|
color = _parse_css_color(value)
|
||||||
tag.set_property('background-gdk', color)
|
tag.set_property('background-gdk', color)
|
||||||
tag.set_property('paragraph-background-gdk', color)
|
tag.set_property('paragraph-background-gdk', color)
|
||||||
|
|
||||||
def __parse_length_frac_size_allocate(self, textview, allocation, frac,
|
@staticmethod
|
||||||
callback, args):
|
def __parse_length_frac_size_allocate(_textview, allocation, frac,
|
||||||
|
callback, args):
|
||||||
callback(allocation.width*frac, *args)
|
callback(allocation.width*frac, *args)
|
||||||
|
|
||||||
def _parse_length(self, value, font_relative, block_relative, minl, maxl,
|
def _parse_length(self, value, font_relative, block_relative, minl, maxl,
|
||||||
callback, *args):
|
callback, *args):
|
||||||
"""
|
"""
|
||||||
Parse/calc length, converting to pixels, calls callback(length, *args)
|
Parse/calc length, converting to pixels, calls callback(length, *args)
|
||||||
when the length is first computed or changes
|
when the length is first computed or changes
|
||||||
|
@ -259,11 +273,11 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
# This is difficult/impossible to implement, so we use
|
# This is difficult/impossible to implement, so we use
|
||||||
# textview width instead; a reasonable approximation..
|
# textview width instead; a reasonable approximation..
|
||||||
alloc = self.textview.get_allocation()
|
alloc = self.textview.get_allocation()
|
||||||
self.__parse_length_frac_size_allocate(self.textview, alloc,
|
self.__parse_length_frac_size_allocate(
|
||||||
frac, callback, args)
|
self.textview, alloc, frac, callback, args)
|
||||||
self.textview.connect('size-allocate',
|
self.textview.connect('size-allocate',
|
||||||
self.__parse_length_frac_size_allocate,
|
self.__parse_length_frac_size_allocate,
|
||||||
frac, callback, args)
|
frac, callback, args)
|
||||||
else:
|
else:
|
||||||
callback(frac, *args)
|
callback(frac, *args)
|
||||||
return
|
return
|
||||||
|
@ -324,7 +338,8 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
elif type_ == 'px':
|
elif type_ == 'px':
|
||||||
tag.set_property('size-points', self._get_points_from_pixels(size))
|
tag.set_property('size-points', self._get_points_from_pixels(size))
|
||||||
|
|
||||||
def _parse_style_display(self, tag, value):
|
@staticmethod
|
||||||
|
def _parse_style_display(tag, value):
|
||||||
if value == 'none':
|
if value == 'none':
|
||||||
tag.set_property('invisible', 'true')
|
tag.set_property('invisible', 'true')
|
||||||
# FIXME: display: block, inline
|
# FIXME: display: block, inline
|
||||||
|
@ -355,13 +370,14 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
self._parse_length(
|
self._parse_length(
|
||||||
value, True, False, 5, 110, self.__parse_font_size_cb, tag)
|
value, True, False, 5, 110, self.__parse_font_size_cb, tag)
|
||||||
|
|
||||||
def _parse_style_font_style(self, tag, value):
|
@staticmethod
|
||||||
|
def _parse_style_font_style(tag, value):
|
||||||
try:
|
try:
|
||||||
style = {
|
style = {
|
||||||
'normal': Pango.Style.NORMAL,
|
'normal': Pango.Style.NORMAL,
|
||||||
'italic': Pango.Style.ITALIC,
|
'italic': Pango.Style.ITALIC,
|
||||||
'oblique': Pango.Style.OBLIQUE,
|
'oblique': Pango.Style.OBLIQUE,
|
||||||
}[value]
|
}[value]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
log.warning('unknown font-style %s', value)
|
log.warning('unknown font-style %s', value)
|
||||||
else:
|
else:
|
||||||
|
@ -376,51 +392,55 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
def _parse_style_margin_left(self, tag, value):
|
def _parse_style_margin_left(self, tag, value):
|
||||||
# block relative
|
# block relative
|
||||||
self._parse_length(value, False, True, 1, 1000,
|
self._parse_length(value, False, True, 1, 1000,
|
||||||
self.__frac_length_tag_cb, tag, 'left-margin')
|
self.__frac_length_tag_cb, tag, 'left-margin')
|
||||||
|
|
||||||
def _parse_style_margin_right(self, tag, value):
|
def _parse_style_margin_right(self, tag, value):
|
||||||
# block relative
|
# block relative
|
||||||
self._parse_length(value, False, True, 1, 1000,
|
self._parse_length(value, False, True, 1, 1000,
|
||||||
self.__frac_length_tag_cb, tag, 'right-margin')
|
self.__frac_length_tag_cb, tag, 'right-margin')
|
||||||
|
|
||||||
def _parse_style_font_weight(self, tag, value):
|
@staticmethod
|
||||||
|
def _parse_style_font_weight(tag, value):
|
||||||
# TODO: missing 'bolder' and 'lighter'
|
# TODO: missing 'bolder' and 'lighter'
|
||||||
try:
|
try:
|
||||||
weight = {
|
weight = {
|
||||||
'100': Pango.Weight.ULTRALIGHT,
|
'100': Pango.Weight.ULTRALIGHT,
|
||||||
'200': Pango.Weight.ULTRALIGHT,
|
'200': Pango.Weight.ULTRALIGHT,
|
||||||
'300': Pango.Weight.LIGHT,
|
'300': Pango.Weight.LIGHT,
|
||||||
'400': Pango.Weight.NORMAL,
|
'400': Pango.Weight.NORMAL,
|
||||||
'500': Pango.Weight.NORMAL,
|
'500': Pango.Weight.NORMAL,
|
||||||
'600': Pango.Weight.BOLD,
|
'600': Pango.Weight.BOLD,
|
||||||
'700': Pango.Weight.BOLD,
|
'700': Pango.Weight.BOLD,
|
||||||
'800': Pango.Weight.ULTRABOLD,
|
'800': Pango.Weight.ULTRABOLD,
|
||||||
'900': Pango.Weight.HEAVY,
|
'900': Pango.Weight.HEAVY,
|
||||||
'normal': Pango.Weight.NORMAL,
|
'normal': Pango.Weight.NORMAL,
|
||||||
'bold': Pango.Weight.BOLD,
|
'bold': Pango.Weight.BOLD,
|
||||||
}[value]
|
}[value]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
log.warning('unknown font-style %s', value)
|
log.warning('unknown font-style %s', value)
|
||||||
else:
|
else:
|
||||||
tag.set_property('weight', weight)
|
tag.set_property('weight', weight)
|
||||||
|
|
||||||
def _parse_style_font_family(self, tag, value):
|
@staticmethod
|
||||||
|
def _parse_style_font_family(tag, value):
|
||||||
tag.set_property('family', value)
|
tag.set_property('family', value)
|
||||||
|
|
||||||
def _parse_style_text_align(self, tag, value):
|
@staticmethod
|
||||||
|
def _parse_style_text_align(tag, value):
|
||||||
try:
|
try:
|
||||||
align = {
|
align = {
|
||||||
'left': Gtk.Justification.LEFT,
|
'left': Gtk.Justification.LEFT,
|
||||||
'right': Gtk.Justification.RIGHT,
|
'right': Gtk.Justification.RIGHT,
|
||||||
'center': Gtk.Justification.CENTER,
|
'center': Gtk.Justification.CENTER,
|
||||||
'justify': Gtk.Justification.FILL,
|
'justify': Gtk.Justification.FILL,
|
||||||
}[value]
|
}[value]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
log.warning('Invalid text-align: %s requested', value)
|
log.warning('Invalid text-align: %s requested', value)
|
||||||
else:
|
else:
|
||||||
tag.set_property('justification', align)
|
tag.set_property('justification', align)
|
||||||
|
|
||||||
def _parse_style_text_decoration(self, tag, value):
|
@staticmethod
|
||||||
|
def _parse_style_text_decoration(tag, value):
|
||||||
values = value.split(' ')
|
values = value.split(' ')
|
||||||
if 'none' in values:
|
if 'none' in values:
|
||||||
tag.set_property('underline', Pango.Underline.NONE)
|
tag.set_property('underline', Pango.Underline.NONE)
|
||||||
|
@ -438,7 +458,8 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
if 'overline' in values:
|
if 'overline' in values:
|
||||||
log.warning('text-decoration:overline not implemented')
|
log.warning('text-decoration:overline not implemented')
|
||||||
|
|
||||||
def _parse_style_white_space(self, tag, value):
|
@staticmethod
|
||||||
|
def _parse_style_white_space(tag, value):
|
||||||
if value == 'pre':
|
if value == 'pre':
|
||||||
tag.set_property('wrap_mode', Gtk.WrapMode.NONE)
|
tag.set_property('wrap_mode', Gtk.WrapMode.NONE)
|
||||||
elif value == 'normal':
|
elif value == 'normal':
|
||||||
|
@ -446,7 +467,8 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
elif value == 'nowrap':
|
elif value == 'nowrap':
|
||||||
tag.set_property('wrap_mode', Gtk.WrapMode.NONE)
|
tag.set_property('wrap_mode', Gtk.WrapMode.NONE)
|
||||||
|
|
||||||
def __length_tag_cb(self, value, tag, propname):
|
@staticmethod
|
||||||
|
def __length_tag_cb(value, tag, propname):
|
||||||
try:
|
try:
|
||||||
tag.set_property(propname, value)
|
tag.set_property(propname, value)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
@ -455,29 +477,13 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
def _parse_style_width(self, tag, value):
|
def _parse_style_width(self, tag, value):
|
||||||
if value == 'auto':
|
if value == 'auto':
|
||||||
return
|
return
|
||||||
self._parse_length(value, False, False, 1, 1000, self.__length_tag_cb,
|
self._parse_length(value, False, False, 1, 1000,
|
||||||
tag, "width")
|
self.__length_tag_cb, tag, "width")
|
||||||
def _parse_style_height(self, tag, value):
|
def _parse_style_height(self, tag, value):
|
||||||
if value == 'auto':
|
if value == 'auto':
|
||||||
return
|
return
|
||||||
self._parse_length(value, False, False, 1, 1000, self.__length_tag_cb,
|
self._parse_length(value, False, False, 1, 1000,
|
||||||
tag, "height")
|
self.__length_tag_cb, tag, "height")
|
||||||
|
|
||||||
|
|
||||||
# build a dictionary mapping styles to methods, for greater speed
|
|
||||||
__style_methods = dict()
|
|
||||||
for style in ('background-color', 'color', 'font-family', 'font-size',
|
|
||||||
'font-style', 'font-weight', 'margin-left', 'margin-right',
|
|
||||||
'text-align', 'text-decoration', 'white-space', 'display',
|
|
||||||
'width', 'height'):
|
|
||||||
try:
|
|
||||||
method = locals()['_parse_style_%s' % style.replace('-', '_')]
|
|
||||||
except KeyError:
|
|
||||||
log.warning('Style attribute "%s" not yet implemented', style)
|
|
||||||
else:
|
|
||||||
__style_methods[style] = method
|
|
||||||
del style # pylint: disable=undefined-loop-variable
|
|
||||||
# --
|
|
||||||
|
|
||||||
def _get_style_tags(self):
|
def _get_style_tags(self):
|
||||||
return [tag for tag in self.styles if tag is not None]
|
return [tag for tag in self.styles if tag is not None]
|
||||||
|
@ -523,8 +529,10 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
else:
|
else:
|
||||||
if self.conv_textview:
|
if self.conv_textview:
|
||||||
img_mark = self.textbuf.create_mark(None, self.iter, True)
|
img_mark = self.textbuf.create_mark(None, self.iter, True)
|
||||||
app.thread_interface(helpers.download_image, [
|
app.thread_interface(
|
||||||
self.conv_textview.account, attrs], self._update_img,
|
helpers.download_image,
|
||||||
|
[self.conv_textview.account, attrs],
|
||||||
|
self._update_img,
|
||||||
[attrs, img_mark, self._get_style_tags()])
|
[attrs, img_mark, self._get_style_tags()])
|
||||||
alt = attrs.get('alt', '')
|
alt = attrs.get('alt', '')
|
||||||
if alt:
|
if alt:
|
||||||
|
@ -542,19 +550,20 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
def width_cb(length):
|
def width_cb(length):
|
||||||
dims[0] = length
|
dims[0] = length
|
||||||
# process width and height attributes
|
# process width and height attributes
|
||||||
w = attrs.get('width')
|
width = attrs.get('width')
|
||||||
h = attrs.get('height')
|
height = attrs.get('height')
|
||||||
# override with width and height styles
|
# override with width and height styles
|
||||||
for attr, val in style_iter(attrs.get('style', '')):
|
for attr, val in style_iter(attrs.get('style', '')):
|
||||||
if attr == 'width':
|
if attr == 'width':
|
||||||
w = val
|
width = val
|
||||||
elif attr == 'height':
|
elif attr == 'height':
|
||||||
h = val
|
height = val
|
||||||
if w:
|
if width:
|
||||||
self._parse_length(w, False, False, 1, 1000, width_cb)
|
self._parse_length(width, False, False, 1, 1000, width_cb)
|
||||||
if h:
|
if height:
|
||||||
self._parse_length(h, False, False, 1, 1000, height_cb)
|
self._parse_length(height, False, False, 1, 1000, height_cb)
|
||||||
def set_size(pixbuf, w, h, dims):
|
|
||||||
|
def set_size(_pixbuf, w, h, dims):
|
||||||
"""
|
"""
|
||||||
FIXME: Floats should be relative to the whole textview, and
|
FIXME: Floats should be relative to the whole textview, and
|
||||||
resize with it. This needs new pifbufs for every resize,
|
resize with it. This needs new pifbufs for every resize,
|
||||||
|
@ -569,7 +578,8 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
if not dims[1]:
|
if not dims[1]:
|
||||||
dims[1] = h
|
dims[1] = h
|
||||||
loader.set_size(*dims)
|
loader.set_size(*dims)
|
||||||
if w or h:
|
|
||||||
|
if width or height:
|
||||||
loader.connect('size-prepared', set_size, dims)
|
loader.connect('size-prepared', set_size, dims)
|
||||||
loader.write(mem)
|
loader.write(mem)
|
||||||
loader.close()
|
loader.close()
|
||||||
|
@ -621,12 +631,10 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
attr = attr.lower()
|
attr = attr.lower()
|
||||||
val = val
|
val = val
|
||||||
try:
|
try:
|
||||||
method = self.__style_methods[attr]
|
getattr(self, self.__style_methods[attr])(tag, val)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
log.warning('Style attribute "%s" requested '
|
log.warning('Style attribute "%s" requested '
|
||||||
'but not yet implemented', attr)
|
'but not yet implemented', attr)
|
||||||
else:
|
|
||||||
method(self, tag, val)
|
|
||||||
self.styles.append(tag)
|
self.styles.append(tag)
|
||||||
|
|
||||||
def _end_span(self):
|
def _end_span(self):
|
||||||
|
@ -660,7 +668,7 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
else:
|
else:
|
||||||
self._insert_text(text.strip('\n'))
|
self._insert_text(text.strip('\n'))
|
||||||
|
|
||||||
def _anchor_event(self, tag, textview, event, iter_, href, type_):
|
def _anchor_event(self, _tag, _textview, event, _iter, href, type_):
|
||||||
if event.type == Gdk.EventType.BUTTON_PRESS:
|
if event.type == Gdk.EventType.BUTTON_PRESS:
|
||||||
self.textview.emit('url-clicked', href, type_)
|
self.textview.emit('url-clicked', href, type_)
|
||||||
return True
|
return True
|
||||||
|
@ -668,8 +676,8 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
|
|
||||||
def handle_specials(self, text):
|
def handle_specials(self, text):
|
||||||
if self.conv_textview:
|
if self.conv_textview:
|
||||||
self.iter = self.conv_textview.detect_and_print_special_text(text,
|
self.iter = self.conv_textview.detect_and_print_special_text(
|
||||||
self._get_style_tags(), iter_=self.iter)
|
text, self._get_style_tags(), iter_=self.iter)
|
||||||
else:
|
else:
|
||||||
self._insert_text(text)
|
self._insert_text(text)
|
||||||
|
|
||||||
|
@ -682,7 +690,6 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
self.text += content
|
self.text += content
|
||||||
self.starting = False
|
self.starting = False
|
||||||
|
|
||||||
|
|
||||||
def startElement(self, name, attrs):
|
def startElement(self, name, attrs):
|
||||||
self._flush_text()
|
self._flush_text()
|
||||||
klass = [i for i in attrs.get('class', ' ').split(' ') if i]
|
klass = [i for i in attrs.get('class', ' ').split(' ') if i]
|
||||||
|
@ -767,10 +774,10 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
log.warning('Unhandled element "%s"', name)
|
log.warning('Unhandled element "%s"', name)
|
||||||
|
|
||||||
def endElement(self, name):
|
def endElement(self, name):
|
||||||
endPreserving = False
|
end_preserving = False
|
||||||
newLine = False
|
newline = False
|
||||||
if name == 'br':
|
if name == 'br':
|
||||||
newLine = True
|
newline = True
|
||||||
elif name == 'hr':
|
elif name == 'hr':
|
||||||
#FIXME: plenty of unused attributes (width, height,...) :)
|
#FIXME: plenty of unused attributes (width, height,...) :)
|
||||||
self._jump_line()
|
self._jump_line()
|
||||||
|
@ -779,7 +786,7 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
elif name in LIST_ELEMS:
|
elif name in LIST_ELEMS:
|
||||||
self.list_counters.pop()
|
self.list_counters.pop()
|
||||||
elif name == 'li':
|
elif name == 'li':
|
||||||
newLine = True
|
newline = True
|
||||||
elif name == 'img':
|
elif name == 'img':
|
||||||
pass
|
pass
|
||||||
elif name in ('body', 'html'):
|
elif name in ('body', 'html'):
|
||||||
|
@ -792,21 +799,20 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
pass
|
pass
|
||||||
elif name in BLOCK:
|
elif name in BLOCK:
|
||||||
if name == 'pre':
|
if name == 'pre':
|
||||||
endPreserving = True
|
end_preserving = True
|
||||||
elif name in BLOCK_STRUCT:
|
elif name in BLOCK_STRUCT:
|
||||||
newLine = True
|
newline = True
|
||||||
else:
|
else:
|
||||||
log.warning("Unhandled element '%s'", name)
|
log.warning("Unhandled element '%s'", name)
|
||||||
self._flush_text()
|
self._flush_text()
|
||||||
if endPreserving:
|
if end_preserving:
|
||||||
self.preserve = False
|
self.preserve = False
|
||||||
if newLine:
|
if newline:
|
||||||
self._jump_line()
|
self._jump_line()
|
||||||
self._end_span()
|
self._end_span()
|
||||||
|
|
||||||
|
|
||||||
class HtmlTextView(Gtk.TextView):
|
class HtmlTextView(Gtk.TextView):
|
||||||
|
|
||||||
def __init__(self, account=None):
|
def __init__(self, account=None):
|
||||||
Gtk.TextView.__init__(self)
|
Gtk.TextView.__init__(self)
|
||||||
self.set_wrap_mode(Gtk.WrapMode.CHAR)
|
self.set_wrap_mode(Gtk.WrapMode.CHAR)
|
||||||
|
@ -847,7 +853,7 @@ class HtmlTextView(Gtk.TextView):
|
||||||
self.tagSthAtSth.set_property('underline', Pango.Underline.SINGLE)
|
self.tagSthAtSth.set_property('underline', Pango.Underline.SINGLE)
|
||||||
self.tagSthAtSth.connect('event', self.hyperlink_handler, 'sth_at_sth')
|
self.tagSthAtSth.connect('event', self.hyperlink_handler, 'sth_at_sth')
|
||||||
|
|
||||||
def __query_tooltip(self, widget, x_pos, y_pos, keyboard_mode, tooltip):
|
def __query_tooltip(self, widget, x_pos, y_pos, _keyboard_mode, tooltip):
|
||||||
window = widget.get_window(Gtk.TextWindowType.TEXT)
|
window = widget.get_window(Gtk.TextWindowType.TEXT)
|
||||||
x_pos, y_pos = self.window_to_buffer_coords(
|
x_pos, y_pos = self.window_to_buffer_coords(
|
||||||
Gtk.TextWindowType.TEXT, x_pos, y_pos)
|
Gtk.TextWindowType.TEXT, x_pos, y_pos)
|
||||||
|
@ -876,7 +882,7 @@ class HtmlTextView(Gtk.TextView):
|
||||||
if menu is None:
|
if menu is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
def destroy(menu, pspec):
|
def destroy(menu, _pspec):
|
||||||
visible = menu.get_property('visible')
|
visible = menu.get_property('visible')
|
||||||
if not visible:
|
if not visible:
|
||||||
GLib.idle_add(menu.destroy)
|
GLib.idle_add(menu.destroy)
|
||||||
|
@ -942,8 +948,8 @@ class HtmlTextView(Gtk.TextView):
|
||||||
'mlat=%(lat)s&mlon=%(lon)s&zoom=16' % \
|
'mlat=%(lat)s&mlon=%(lon)s&zoom=16' % \
|
||||||
{'lat': lat, 'lon': lon}
|
{'lat': lat, 'lon': lon}
|
||||||
helpers.launch_browser_mailer(kind, uri)
|
helpers.launch_browser_mailer(kind, uri)
|
||||||
# other URIs
|
|
||||||
else:
|
else:
|
||||||
|
# other URIs
|
||||||
helpers.launch_browser_mailer(kind, word)
|
helpers.launch_browser_mailer(kind, word)
|
||||||
|
|
||||||
def display_html(self, html, textview, conv_textview, iter_=None):
|
def display_html(self, html, textview, conv_textview, iter_=None):
|
||||||
|
@ -952,17 +958,10 @@ class HtmlTextView(Gtk.TextView):
|
||||||
eob = iter_
|
eob = iter_
|
||||||
else:
|
else:
|
||||||
eob = buffer_.get_end_iter()
|
eob = buffer_.get_end_iter()
|
||||||
## this works too if libxml2 is not available
|
|
||||||
# parser = xml.sax.make_parser(['drv_libxml2'])
|
|
||||||
# parser.setFeature(xml.sax.handler.feature_validation, True)
|
|
||||||
parser = xml.sax.make_parser()
|
parser = xml.sax.make_parser()
|
||||||
parser.setContentHandler(HtmlHandler(textview, conv_textview, eob))
|
parser.setContentHandler(HtmlHandler(textview, conv_textview, eob))
|
||||||
parser.parse(StringIO(html))
|
parser.parse(StringIO(html))
|
||||||
|
|
||||||
# too much space after :)
|
|
||||||
#if not eob.starts_line():
|
|
||||||
# buffer_.insert(eob, '\n')
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _on_copy_clipboard(textview):
|
def _on_copy_clipboard(textview):
|
||||||
clipboard = textview.get_clipboard(Gdk.SELECTION_CLIPBOARD)
|
clipboard = textview.get_clipboard(Gdk.SELECTION_CLIPBOARD)
|
||||||
|
|
Loading…
Reference in New Issue