Correct display hyperlinks in XHTML-IM content.
Fixed the ability to run htmltextview.py as separate application. Cut long lines. Fixed # 6045
This commit is contained in:
parent
6bdf47d7e7
commit
5ee92b7a3c
|
@ -191,7 +191,7 @@ class ConversationTextview(gobject.GObject):
|
|||
|
||||
# no need to inherit TextView, use it as atrribute is safer
|
||||
self.tv = HtmlTextView()
|
||||
self.tv.html_hyperlink_handler = self.html_hyperlink_handler
|
||||
self.tv.hyperlink_handler = self.hyperlink_handler
|
||||
|
||||
# set properties
|
||||
self.tv.set_border_width(1)
|
||||
|
@ -946,10 +946,24 @@ class ConversationTextview(gobject.GObject):
|
|||
# we get the end of the tag
|
||||
while not end_iter.ends_tag(texttag):
|
||||
end_iter.forward_char()
|
||||
|
||||
# Detect XHTML-IM link
|
||||
word = getattr(texttag, 'href', None)
|
||||
if word:
|
||||
if word.startswith('xmpp'):
|
||||
kind = 'xmpp'
|
||||
elif word.startswith('mailto:'):
|
||||
kind = 'mail'
|
||||
elif gajim.interface.sth_at_sth_dot_sth_re.match(word):
|
||||
# it's a JID or mail
|
||||
kind = 'sth_at_sth'
|
||||
else:
|
||||
word = self.tv.get_buffer().get_text(begin_iter, end_iter).decode(
|
||||
'utf-8')
|
||||
|
||||
if event.button == 3: # right click
|
||||
self.make_link_menu(event, kind, word)
|
||||
return True
|
||||
else:
|
||||
# we launch the correct application
|
||||
if kind == 'xmpp':
|
||||
|
@ -965,16 +979,6 @@ class ConversationTextview(gobject.GObject):
|
|||
else:
|
||||
helpers.launch_browser_mailer(kind, word)
|
||||
|
||||
def html_hyperlink_handler(self, texttag, widget, event, iter_, kind, href):
|
||||
if event.type == gtk.gdk.BUTTON_PRESS:
|
||||
if event.button == 3: # right click
|
||||
self.make_link_menu(event, kind, href)
|
||||
return True
|
||||
else:
|
||||
# we launch the correct application
|
||||
helpers.launch_browser_mailer(kind, href)
|
||||
|
||||
|
||||
def detect_and_print_special_text(self, otext, other_tags, graphics=True):
|
||||
"""
|
||||
Detect special text (emots & links & formatting), print normal text
|
||||
|
@ -1039,6 +1043,14 @@ class ConversationTextview(gobject.GObject):
|
|||
gajim.config.get('show_ascii_formatting_chars')
|
||||
buffer_ = self.tv.get_buffer()
|
||||
|
||||
# Detect XHTML-IM link
|
||||
ttt = buffer_.get_tag_table()
|
||||
tags_ = [(ttt.lookup(t) if isinstance(t, str) else t) for t in other_tags]
|
||||
for t in tags_:
|
||||
is_xhtml_link = getattr(t, 'href', None)
|
||||
if is_xhtml_link:
|
||||
break
|
||||
|
||||
# Check if we accept this as an uri
|
||||
schemes = gajim.config.get('uri_schemes').split()
|
||||
for scheme in schemes:
|
||||
|
@ -1062,21 +1074,18 @@ class ConversationTextview(gobject.GObject):
|
|||
self.images.append(img)
|
||||
# add with possible animation
|
||||
self.tv.add_child_at_anchor(img, anchor)
|
||||
elif special_text.startswith('www.') or \
|
||||
elif not is_xhtml_link:
|
||||
if special_text.startswith('www.') or \
|
||||
special_text.startswith('ftp.') or \
|
||||
text_is_valid_uri:
|
||||
tags.append('url')
|
||||
use_other_tags = False
|
||||
elif special_text.startswith('mailto:'):
|
||||
tags.append('mail')
|
||||
use_other_tags = False
|
||||
elif special_text.startswith('xmpp:'):
|
||||
tags.append('xmpp')
|
||||
use_other_tags = False
|
||||
elif gajim.interface.sth_at_sth_dot_sth_re.match(special_text):
|
||||
# it's a JID or mail
|
||||
tags.append('sth_at_sth')
|
||||
use_other_tags = False
|
||||
elif special_text.startswith('*'): # it's a bold text
|
||||
tags.append('bold')
|
||||
if special_text[1] == '/' and special_text[-2] == '/' and\
|
||||
|
@ -1163,7 +1172,6 @@ class ConversationTextview(gobject.GObject):
|
|||
if use_other_tags:
|
||||
all_tags += other_tags
|
||||
# convert all names to TextTag
|
||||
ttt = buffer_.get_tag_table()
|
||||
all_tags = [(ttt.lookup(t) if isinstance(t, str) else t) for t in all_tags]
|
||||
buffer_.insert_with_tags(end_iter, special_text, *all_tags)
|
||||
|
||||
|
@ -1361,6 +1369,7 @@ class ConversationTextview(gobject.GObject):
|
|||
self.tv.display_html(xhtml.encode('utf-8'), self)
|
||||
return
|
||||
except Exception, e:
|
||||
print e
|
||||
gajim.log.debug('Error processing xhtml' + str(e))
|
||||
gajim.log.debug('with |' + xhtml + '|')
|
||||
|
||||
|
|
|
@ -50,7 +50,9 @@ import operator
|
|||
if __name__ == '__main__':
|
||||
from common import i18n
|
||||
import common.configpaths
|
||||
common.configpaths.gajimpaths.init_profile()
|
||||
common.configpaths.gajimpaths.init(None)
|
||||
import gtkgui_helpers
|
||||
from common import gajim
|
||||
|
||||
import tooltips
|
||||
|
@ -182,8 +184,7 @@ for name in BLOCK_HEAD:
|
|||
size = (num-1) // 2
|
||||
weigth = (num - 1) % 2
|
||||
element_styles[name] = '; font-size: %s; %s' % ( ('large', 'medium', 'small')[size],
|
||||
('font-weight: bold', 'font-style: oblique')[weigth],
|
||||
)
|
||||
('font-weight: bold', 'font-style: oblique')[weigth],)
|
||||
|
||||
def _parse_css_color(color):
|
||||
if color.startswith('rgb(') and color.endswith(')'):
|
||||
|
@ -234,11 +235,12 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
|||
self.iter.forward_char()
|
||||
return attrs
|
||||
|
||||
def __parse_length_frac_size_allocate(self, textview, allocation,
|
||||
frac, callback, args):
|
||||
def __parse_length_frac_size_allocate(self, textview, allocation, frac,
|
||||
callback, args):
|
||||
callback(allocation.width*frac, *args)
|
||||
|
||||
def _parse_length(self, value, font_relative, block_relative, minl, maxl, callback, *args):
|
||||
def _parse_length(self, value, font_relative, block_relative, minl, maxl,
|
||||
callback, *args):
|
||||
"""
|
||||
Parse/calc length, converting to pixels, calls callback(length, *args)
|
||||
when the length is first computed or changes
|
||||
|
@ -335,7 +337,8 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
|||
tag.set_property('scale', pango.SCALE_LARGE)
|
||||
return
|
||||
# font relative (5 ~ 4pt, 110 ~ 72pt)
|
||||
self._parse_length(value, True, False, 5, 110, self.__parse_font_size_cb, tag)
|
||||
self._parse_length(value, True, False, 5, 110,self.__parse_font_size_cb,
|
||||
tag)
|
||||
|
||||
def _parse_style_font_style(self, tag, value):
|
||||
try:
|
||||
|
@ -358,13 +361,13 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
|||
|
||||
def _parse_style_margin_left(self, tag, value):
|
||||
# block relative
|
||||
self._parse_length(value, False, True, 1, 1000, self.__frac_length_tag_cb,
|
||||
tag, 'left-margin')
|
||||
self._parse_length(value, False, True, 1, 1000,
|
||||
self.__frac_length_tag_cb, tag, 'left-margin')
|
||||
|
||||
def _parse_style_margin_right(self, tag, value):
|
||||
# block relative
|
||||
self._parse_length(value, False, True, 1, 1000, self.__frac_length_tag_cb,
|
||||
tag, 'right-margin')
|
||||
self._parse_length(value, False, True, 1, 1000,
|
||||
self.__frac_length_tag_cb, tag, 'right-margin')
|
||||
|
||||
def _parse_style_font_weight(self, tag, value):
|
||||
# TODO: missing 'bolder' and 'lighter'
|
||||
|
@ -473,7 +476,7 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
|||
if href and href[0] != '#':
|
||||
tag.href = href
|
||||
tag.type_ = type_ # to be used by the URL handler
|
||||
tag.connect('event', self.textview.html_hyperlink_handler, 'url', href)
|
||||
tag.connect('event', self.textview.hyperlink_handler, 'url')
|
||||
tag.set_property('foreground', gajim.config.get('urlmsgcolor'))
|
||||
tag.set_property('underline', pango.UNDERLINE_SINGLE)
|
||||
tag.is_anchor = True
|
||||
|
@ -517,8 +520,8 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
|||
try:
|
||||
temp = f.read(100)
|
||||
except socket.timeout, ex:
|
||||
gajim.log.debug('Timeout loading image %s ' % attrs['src'] + \
|
||||
str(ex))
|
||||
gajim.log.debug('Timeout loading image %s ' % \
|
||||
attrs['src'] + str(ex))
|
||||
alt = attrs.get('alt', '')
|
||||
if alt:
|
||||
alt += '\n'
|
||||
|
@ -658,14 +661,14 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
|||
return False
|
||||
|
||||
def handle_specials(self, text):
|
||||
self.iter = self.conv_textview.detect_and_print_special_text(text, self._get_style_tags())
|
||||
self.iter = self.conv_textview.detect_and_print_special_text(text,
|
||||
self._get_style_tags())
|
||||
|
||||
def characters(self, content):
|
||||
if self.preserve:
|
||||
self.text += content
|
||||
return
|
||||
if allwhitespace_rx.match(content) is not None and self._starts_line():
|
||||
self.text += ' '
|
||||
return
|
||||
self.text += content
|
||||
self.starting = False
|
||||
|
@ -763,7 +766,8 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
|||
#FIXME: plenty of unused attributes (width, height,...) :)
|
||||
self._jump_line()
|
||||
try:
|
||||
self.textbuf.insert_pixbuf(self.iter, self.textview.focus_out_line_pixbuf)
|
||||
self.textbuf.insert_pixbuf(self.iter,
|
||||
self.textview.focus_out_line_pixbuf)
|
||||
#self._insert_text(u'\u2550'*40)
|
||||
self._jump_line()
|
||||
except Exception, e:
|
||||
|
@ -859,7 +863,8 @@ class HtmlTextView(gtk.TextView):
|
|||
window = widget.get_window(gtk.TEXT_WINDOW_TEXT)
|
||||
window.set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND2))
|
||||
self._changed_cursor = True
|
||||
self.tooltip.timeout = gobject.timeout_add(500, self.show_tooltip, anchor_tags[0])
|
||||
self.tooltip.timeout = gobject.timeout_add(500, self.show_tooltip,
|
||||
anchor_tags[0])
|
||||
elif self._changed_cursor and not anchor_tags:
|
||||
window = widget.get_window(gtk.TEXT_WINDOW_TEXT)
|
||||
window.set_cursor(gtk.gdk.Cursor(gtk.gdk.XTERM))
|
||||
|
@ -886,10 +891,12 @@ class HtmlTextView(gtk.TextView):
|
|||
self.emit_stop_by_name('copy-clipboard')
|
||||
|
||||
def on_html_text_view_realized(self, unused_data):
|
||||
self.get_buffer().remove_selection_clipboard(self.get_clipboard(gtk.gdk.SELECTION_PRIMARY))
|
||||
self.get_buffer().remove_selection_clipboard(self.get_clipboard(
|
||||
gtk.gdk.SELECTION_PRIMARY))
|
||||
|
||||
def on_html_text_view_unrealized(self, unused_data):
|
||||
self.get_buffer().add_selection_clipboard(self.get_clipboard(gtk.gdk.SELECTION_PRIMARY))
|
||||
self.get_buffer().add_selection_clipboard(self.get_clipboard(
|
||||
gtk.gdk.SELECTION_PRIMARY))
|
||||
|
||||
def on_text_buffer_mark_set(self, location, mark, unused_data):
|
||||
bounds = self.get_buffer().get_selection_bounds()
|
||||
|
@ -955,8 +962,8 @@ if __name__ == '__main__':
|
|||
"""
|
||||
global change_cursor
|
||||
pointer_x, pointer_y = htmlview.tv.window.get_pointer()[0:2]
|
||||
x, y = htmlview.tv.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, pointer_x,
|
||||
pointer_y)
|
||||
x, y = htmlview.tv.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT,
|
||||
pointer_x, pointer_y)
|
||||
tags = htmlview.tv.get_iter_at_location(x, y).get_tags()
|
||||
if change_cursor:
|
||||
htmlview.tv.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(
|
||||
|
@ -987,22 +994,30 @@ if __name__ == '__main__':
|
|||
|
||||
htmlview.tv.connect('motion_notify_event', on_textview_motion_notify_event)
|
||||
|
||||
def handler(texttag, widget, event, iter_, kind, href):
|
||||
def handler(texttag, widget, event, iter_, kind):
|
||||
if event.type == gtk.gdk.BUTTON_PRESS:
|
||||
print href
|
||||
pass
|
||||
|
||||
htmlview.tv.html_hyperlink_handler = handler
|
||||
htmlview.tv.hyperlink_handler = htmlview.hyperlink_handler
|
||||
|
||||
htmlview.print_real_text(None, xhtml='<div><span style="color: red; text-decoration:underline">Hello</span><br/>\n'
|
||||
htmlview.print_real_text(None, xhtml='<div>'
|
||||
'<span style="color: red; text-decoration:underline">Hello</span><br/>\n'
|
||||
' <img src="http://images.slashdot.org/topics/topicsoftware.gif"/><br/>\n'
|
||||
' <span style="font-size: 500%; font-family: serif">World</span>\n'
|
||||
'<span style="font-size: 500%; font-family: serif">World</span>\n'
|
||||
'</div>\n')
|
||||
htmlview.print_real_text(None, xhtml='<hr />')
|
||||
htmlview.print_real_text(None, xhtml='''<body xmlns='http://www.w3.org/1999/xhtml'><p xmlns='http://www.w3.org/1999/xhtml'>a:b<a href='http://google.com/' xmlns='http://www.w3.org/1999/xhtml'>Google</a></p><br/></body>''')
|
||||
htmlview.print_real_text(None, xhtml='''
|
||||
<body xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<p xmlns='http://www.w3.org/1999/xhtml'>a:b
|
||||
<a href='http://google.com/' xmlns='http://www.w3.org/1999/xhtml'>Google
|
||||
</a>
|
||||
</p><br/>
|
||||
</body>''')
|
||||
htmlview.print_real_text(None, xhtml='''
|
||||
<body xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<p style='font-size:large'>
|
||||
<span style='font-style: italic'>O<span style='font-size:larger'>M</span>G</span>,
|
||||
<span style='font-style: italic'>O
|
||||
<span style='font-size:larger'>M</span>G</span>,
|
||||
I'm <span style='color:green'>green</span>
|
||||
with <span style='font-weight: bold'>envy</span>!
|
||||
</p>
|
||||
|
@ -1017,7 +1032,8 @@ if __name__ == '__main__':
|
|||
htmlview.print_real_text(None, xhtml='<hr />')
|
||||
htmlview.print_real_text(None, xhtml='''
|
||||
<body xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<p>As Emerson said in his essay <span style='font-style: italic; background-color:cyan'>Self-Reliance</span>:</p>
|
||||
<p>As Emerson said in his essay <span style='
|
||||
font-style: italic; background-color:cyan'>Self-Reliance</span>:</p>
|
||||
<p style='margin-left: 5px; margin-right: 2%'>
|
||||
"A foolish consistency is the hobgoblin of little minds."
|
||||
</p>
|
||||
|
@ -1026,11 +1042,13 @@ if __name__ == '__main__':
|
|||
htmlview.print_real_text(None, xhtml='<hr />')
|
||||
htmlview.print_real_text(None, xhtml='''
|
||||
<body xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<p style='text-align:center'>Hey, are you licensed to <a href='http://www.jabber.org/'>Jabber</a>?</p>
|
||||
<p style='text-align:right'><img src='http://www.jabber.org/images/psa-license.jpg'
|
||||
alt='A License to Jabber'
|
||||
width='50%' height='50%'
|
||||
/></p>
|
||||
<p style='text-align:center'>
|
||||
Hey, are you licensed to <a href='http://www.jabber.org/'>Jabber</a>?
|
||||
</p>
|
||||
<p style='text-align:right'>
|
||||
<img src='http://www.xmpp.org/images/psa-license.jpg'
|
||||
alt='A License to Jabber' width='50%' height='50%'/>
|
||||
</p>
|
||||
</body>
|
||||
''')
|
||||
htmlview.print_real_text(None, xhtml='<hr />')
|
||||
|
@ -1062,6 +1080,28 @@ return faciter(n,1)</pre>
|
|||
<li> Three </li></ol>
|
||||
</body>
|
||||
''')
|
||||
htmlview.print_real_text(None, xhtml='<hr />')
|
||||
htmlview.print_real_text(None, xhtml='''
|
||||
<body xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<p>
|
||||
<strong>
|
||||
<a href='xmpp:example@example.org'>xmpp link</a>
|
||||
</strong>: </p>
|
||||
<div xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<cite style='margin: 7px;' title='xmpp:examples@example.org'>
|
||||
<p>
|
||||
<strong>examples@example.org wrote:</strong>
|
||||
</p>
|
||||
<p>this cite - bla bla bla, smile- :-) ...</p>
|
||||
</cite>
|
||||
<div>
|
||||
<p>some text</p>
|
||||
</div>
|
||||
</div>
|
||||
<p/>
|
||||
<p>#232/1</p>
|
||||
</body>
|
||||
''')
|
||||
htmlview.tv.show()
|
||||
sw = gtk.ScrolledWindow()
|
||||
sw.set_property('hscrollbar-policy', gtk.POLICY_AUTOMATIC)
|
||||
|
|
Loading…
Reference in New Issue