Skip to content
Snippets Groups Projects
Commit bdda090d authored by Yann Leboulanger's avatar Yann Leboulanger
Browse files

add ability to handle urls in htmltextview.

parent a17d235a
No related branches found
No related tags found
No related merge requests found
...@@ -298,31 +298,7 @@ class ConversationTextview(gobject.GObject): ...@@ -298,31 +298,7 @@ class ConversationTextview(gobject.GObject):
color = gajim.config.get('restored_messages_color') color = gajim.config.get('restored_messages_color')
tag.set_property('foreground', color) tag.set_property('foreground', color)
self.tagURL = buffer_.create_tag('url') self.tv.create_tags()
color = gajim.config.get('urlmsgcolor')
self.tagURL.set_property('foreground', color)
self.tagURL.set_property('underline', pango.UNDERLINE_SINGLE)
id_ = self.tagURL.connect('event', self.hyperlink_handler, 'url')
self.handlers[id_] = self.tagURL
self.tagMail = buffer_.create_tag('mail')
self.tagMail.set_property('foreground', color)
self.tagMail.set_property('underline', pango.UNDERLINE_SINGLE)
id_ = self.tagMail.connect('event', self.hyperlink_handler, 'mail')
self.handlers[id_] = self.tagMail
self.tagXMPP = buffer_.create_tag('xmpp')
self.tagXMPP.set_property('foreground', color)
self.tagXMPP.set_property('underline', pango.UNDERLINE_SINGLE)
id_ = self.tagXMPP.connect('event', self.hyperlink_handler, 'xmpp')
self.handlers[id_] = self.tagXMPP
self.tagSthAtSth = buffer_.create_tag('sth_at_sth')
self.tagSthAtSth.set_property('foreground', color)
self.tagSthAtSth.set_property('underline', pango.UNDERLINE_SINGLE)
id_ = self.tagSthAtSth.connect('event', self.hyperlink_handler,
'sth_at_sth')
self.handlers[id_] = self.tagSthAtSth
tag = buffer_.create_tag('bold') tag = buffer_.create_tag('bold')
tag.set_property('weight', pango.WEIGHT_BOLD) tag.set_property('weight', pango.WEIGHT_BOLD)
...@@ -369,8 +345,11 @@ class ConversationTextview(gobject.GObject): ...@@ -369,8 +345,11 @@ class ConversationTextview(gobject.GObject):
self.tagOut.set_property('foreground', gajim.config.get('outmsgcolor')) self.tagOut.set_property('foreground', gajim.config.get('outmsgcolor'))
self.tagStatus.set_property('foreground', self.tagStatus.set_property('foreground',
gajim.config.get('statusmsgcolor')) gajim.config.get('statusmsgcolor'))
self.tagURL.set_property('foreground', gajim.config.get('urlmsgcolor')) color = gajim.config.get('urlmsgcolor')
self.tagMail.set_property('foreground', gajim.config.get('urlmsgcolor')) self.tv.tagURL.set_property('foreground', color)
self.tv.tagMail.set_property('foreground', color)
self.tv.tagXMPP.set_property('foreground', color)
self.tv.tagSthAtSth.set_property('foreground', color)
def at_the_end(self): def at_the_end(self):
buffer_ = self.tv.get_buffer() buffer_ = self.tv.get_buffer()
...@@ -1463,7 +1442,7 @@ class ConversationTextview(gobject.GObject): ...@@ -1463,7 +1442,7 @@ class ConversationTextview(gobject.GObject):
try: try:
if name and (text.startswith('/me ') or text.startswith('/me\n')): if name and (text.startswith('/me ') or text.startswith('/me\n')):
xhtml = xhtml.replace('/me', '<i>* %s</i>' % (name,), 1) xhtml = xhtml.replace('/me', '<i>* %s</i>' % (name,), 1)
self.tv.display_html(xhtml.encode('utf-8'), self) self.tv.display_html(xhtml.encode('utf-8'), self.tv, self)
return return
except Exception, e: except Exception, e:
gajim.log.debug('Error processing xhtml' + str(e)) gajim.log.debug('Error processing xhtml' + str(e))
......
...@@ -210,10 +210,10 @@ class HtmlHandler(xml.sax.handler.ContentHandler): ...@@ -210,10 +210,10 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
It keeps a stack of "style spans" (start/end element pairs) and a stack of It keeps a stack of "style spans" (start/end element pairs) and a stack of
list counters, for nested lists. list counters, for nested lists.
""" """
def __init__(self, conv_textview, startiter): def __init__(self, textview, conv_textview, startiter):
xml.sax.handler.ContentHandler.__init__(self) xml.sax.handler.ContentHandler.__init__(self)
self.textbuf = conv_textview.tv.get_buffer() self.textbuf = textview.get_buffer()
self.textview = conv_textview.tv self.textview = textview
self.iter = startiter self.iter = startiter
self.conv_textview = conv_textview self.conv_textview = conv_textview
self.text = '' self.text = ''
...@@ -512,15 +512,16 @@ class HtmlHandler(xml.sax.handler.ContentHandler): ...@@ -512,15 +512,16 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
(mem, alt, replace_mark) = loaded (mem, alt, replace_mark) = loaded
update = True update = True
else: else:
img_mark = self.textbuf.create_mark(None, self.iter, True) if self.conv_textview:
gajim.thread_interface(helpers.download_image, [ img_mark = self.textbuf.create_mark(None, self.iter, True)
self.conv_textview.account, attrs], self._update_img, gajim.thread_interface(helpers.download_image, [
[attrs, img_mark]) self.conv_textview.account, attrs], self._update_img,
alt = attrs.get('alt', '') [attrs, img_mark])
if alt: alt = attrs.get('alt', '')
alt += '\n' if alt:
alt += _('Loading') alt += '\n'
pixbuf = get_icon_pixmap('gajim-receipt_missing') alt += _('Loading')
pixbuf = get_icon_pixmap('gajim-receipt_missing')
if mem: if mem:
# Caveat: GdkPixbuf is known not to be safe to load # Caveat: GdkPixbuf is known not to be safe to load
# images from network... this program is now potentially # images from network... this program is now potentially
...@@ -653,8 +654,11 @@ class HtmlHandler(xml.sax.handler.ContentHandler): ...@@ -653,8 +654,11 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
return False return False
def handle_specials(self, text): def handle_specials(self, text):
self.iter = self.conv_textview.detect_and_print_special_text(text, if self.conv_textview:
self._get_style_tags()) self.iter = self.conv_textview.detect_and_print_special_text(text,
self._get_style_tags())
else:
self._insert_text(text)
def characters(self, content): def characters(self, content):
if self.preserve: if self.preserve:
...@@ -758,9 +762,11 @@ class HtmlHandler(xml.sax.handler.ContentHandler): ...@@ -758,9 +762,11 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
#FIXME: plenty of unused attributes (width, height,...) :) #FIXME: plenty of unused attributes (width, height,...) :)
self._jump_line() self._jump_line()
try: try:
self.textbuf.insert_pixbuf(self.iter, if self.conv_textbuf:
self.textview.focus_out_line_pixbuf) self.conv_textbuf.insert_pixbuf(self.iter,
#self._insert_text(u'\u2550'*40) self.conv_textview.focus_out_line_pixbuf)
else:
self._insert_text(u'\u2550'*40)
self._jump_line() self._jump_line()
except Exception, e: except Exception, e:
log.debug(str('Error in hr'+e)) log.debug(str('Error in hr'+e))
...@@ -808,12 +814,38 @@ class HtmlTextView(gtk.TextView): ...@@ -808,12 +814,38 @@ class HtmlTextView(gtk.TextView):
self.connect('copy-clipboard', self.on_html_text_view_copy_clipboard) self.connect('copy-clipboard', self.on_html_text_view_copy_clipboard)
self.id_ = self.connect('button-release-event', self.id_ = self.connect('button-release-event',
self.on_left_mouse_button_release) self.on_left_mouse_button_release)
self.get_buffer().create_tag('eol', scale = pango.SCALE_XX_SMALL) buffer_ = self.get_buffer()
buffer_.create_tag('eol', scale = pango.SCALE_XX_SMALL)
self.tooltip = tooltips.BaseTooltip() self.tooltip = tooltips.BaseTooltip()
self.config = gajim.config self.config = gajim.config
self.interface = gajim.interface self.interface = gajim.interface
# end big hack # end big hack
def create_tags(self):
buffer_ = self.get_buffer()
self.tagURL = buffer_.create_tag('url')
color = gajim.config.get('urlmsgcolor')
self.tagURL.set_property('foreground', color)
self.tagURL.set_property('underline', pango.UNDERLINE_SINGLE)
self.tagURL.connect('event', self._hyperlink_handler, 'url')
self.tagMail = buffer_.create_tag('mail')
self.tagMail.set_property('foreground', color)
self.tagMail.set_property('underline', pango.UNDERLINE_SINGLE)
self.tagMail.connect('event', self._hyperlink_handler, 'mail')
self.tagXMPP = buffer_.create_tag('xmpp')
self.tagXMPP.set_property('foreground', color)
self.tagXMPP.set_property('underline', pango.UNDERLINE_SINGLE)
self.tagXMPP.connect('event', self._hyperlink_handler, 'xmpp')
self.tagSthAtSth = buffer_.create_tag('sth_at_sth')
self.tagSthAtSth.set_property('foreground', color)
self.tagSthAtSth.set_property('underline', pango.UNDERLINE_SINGLE)
self.tagSthAtSth.connect('event', self._hyperlink_handler, 'sth_at_sth')
def __destroy_event(self, widget): def __destroy_event(self, widget):
if self.tooltip.timeout != 0: if self.tooltip.timeout != 0:
self.tooltip.hide_tooltip() self.tooltip.hide_tooltip()
...@@ -864,14 +896,136 @@ class HtmlTextView(gtk.TextView): ...@@ -864,14 +896,136 @@ class HtmlTextView(gtk.TextView):
self._changed_cursor = False self._changed_cursor = False
return False return False
def display_html(self, html, conv_textview): def on_open_link_activate(self, widget, kind, text):
helpers.launch_browser_mailer(kind, text)
def on_copy_link_activate(self, widget, text):
clip = gtk.clipboard_get()
clip.set_text(text)
# def on_start_chat_activate(self, widget, jid):
# gajim.interface.new_chat_from_jid(self.account, jid)
def on_join_group_chat_menuitem_activate(self, widget, room_jid):
try:
dialogs.JoinGroupchatWindow(room_jid=room_jid)
except GajimGeneralException:
pass
def on_add_to_roster_activate(self, widget, jid):
dialogs.AddNewContactWindow(self.account, jid)
def make_link_menu(self, event, kind, text):
xml = gtkgui_helpers.get_gtk_builder('chat_context_menu.ui')
menu = xml.get_object('chat_context_menu')
childs = menu.get_children()
if kind == 'url':
childs[0].connect('activate', self.on_copy_link_activate, text)
childs[1].connect('activate', self.on_open_link_activate, kind,
text)
childs[2].hide() # copy mail address
childs[3].hide() # open mail composer
childs[4].hide() # jid section separator
childs[5].hide() # start chat
childs[6].hide() # join group chat
childs[7].hide() # add to roster
else: # It's a mail or a JID
# load muc icon
join_group_chat_menuitem = xml.get_object('join_group_chat_menuitem')
muc_icon = gtkgui_helpers.load_icon('muc_active')
if muc_icon:
join_group_chat_menuitem.set_image(muc_icon)
text = text.lower()
if text.startswith('xmpp:'):
text = text[5:]
childs[2].connect('activate', self.on_copy_link_activate, text)
childs[3].connect('activate', self.on_open_link_activate, kind,
text)
# childs[5].connect('activate', self.on_start_chat_activate, text)
childs[6].connect('activate',
self.on_join_group_chat_menuitem_activate, text)
# if self.account and gajim.connections[self.account].\
# roster_supported:
# childs[7].connect('activate',
# self.on_add_to_roster_activate, text)
# childs[7].show() # show add to roster menuitem
# else:
# childs[7].hide() # hide add to roster menuitem
if kind == 'xmpp':
childs[0].connect('activate', self.on_copy_link_activate,
'xmpp:' + text)
childs[2].hide() # copy mail address
childs[3].hide() # open mail composer
elif kind == 'mail':
childs[6].hide() # join group chat
if kind != 'xmpp':
childs[0].hide() # copy link location
childs[1].hide() # open link in browser
childs[4].hide() # jid section separator
childs[5].hide() # start chat
childs[7].hide() # add to roster
menu.popup(None, None, None, event.button, event.time)
def hyperlink_handler(self, texttag, widget, event, iter_, kind):
if event.type == gtk.gdk.BUTTON_PRESS:
begin_iter = iter_.copy()
# we get the begining of the tag
while not begin_iter.begins_tag(texttag):
begin_iter.backward_char()
end_iter = iter_.copy()
# 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.textview.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':
word = word[5:]
if '?' in word:
(jid, action) = word.split('?')
if action == 'join':
self.on_join_group_chat_menuitem_activate(None, jid)
else:
self.on_start_chat_activate(None, jid)
else:
self.on_start_chat_activate(None, word)
else:
helpers.launch_browser_mailer(kind, word)
def _hyperlink_handler(self, texttag, widget, event, iter_, kind):
# self.hyperlink_handler can be overwritten, so call it when needed
self.hyperlink_handler(texttag, widget, event, iter_, kind)
def display_html(self, html, textview, conv_textview):
buffer_ = self.get_buffer() buffer_ = self.get_buffer()
eob = buffer_.get_end_iter() eob = buffer_.get_end_iter()
## this works too if libxml2 is not available ## this works too if libxml2 is not available
# parser = xml.sax.make_parser(['drv_libxml2']) # parser = xml.sax.make_parser(['drv_libxml2'])
# parser.setFeature(xml.sax.handler.feature_validation, True) # parser.setFeature(xml.sax.handler.feature_validation, True)
parser = xml.sax.make_parser() parser = xml.sax.make_parser()
parser.setContentHandler(HtmlHandler(conv_textview, eob)) parser.setContentHandler(HtmlHandler(textview, conv_textview, eob))
parser.parse(StringIO(html)) parser.parse(StringIO(html))
# too much space after :) # too much space after :)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment