break more circular references that keep
objects alive (the other 1/2 of #1829) context menu for groupchat banner
This commit is contained in:
parent
365d9d4eb6
commit
5c9613db65
|
@ -109,12 +109,17 @@ class ChatControlBase(MessageControl):
|
||||||
id = self.widget.connect('key_press_event', self._on_keypress_event)
|
id = self.widget.connect('key_press_event', self._on_keypress_event)
|
||||||
self.handlers[id] = self.widget
|
self.handlers[id] = self.widget
|
||||||
|
|
||||||
|
widget = self.xml.get_widget('banner_eventbox')
|
||||||
|
id = widget.connect('button-press-event',
|
||||||
|
self._on_banner_eventbox_button_press_event)
|
||||||
|
self.handlers[id] = widget
|
||||||
|
|
||||||
# Create textviews and connect signals
|
# Create textviews and connect signals
|
||||||
self.conv_textview = ConversationTextview(self.account)
|
self.conv_textview = ConversationTextview(self.account)
|
||||||
self.conv_textview.show_all()
|
|
||||||
self.conv_scrolledwindow = self.xml.get_widget(
|
self.conv_scrolledwindow = self.xml.get_widget(
|
||||||
'conversation_scrolledwindow')
|
'conversation_scrolledwindow')
|
||||||
self.conv_scrolledwindow.add(self.conv_textview)
|
self.conv_scrolledwindow.add(self.conv_textview.tv)
|
||||||
widget = self.conv_scrolledwindow.get_vadjustment()
|
widget = self.conv_scrolledwindow.get_vadjustment()
|
||||||
id = widget.connect('value-changed',
|
id = widget.connect('value-changed',
|
||||||
self.on_conversation_vadjustment_value_changed)
|
self.on_conversation_vadjustment_value_changed)
|
||||||
|
@ -170,6 +175,12 @@ class ChatControlBase(MessageControl):
|
||||||
gajim.config.set('use_speller', False)
|
gajim.config.set('use_speller', False)
|
||||||
|
|
||||||
self.style_event_id = 0
|
self.style_event_id = 0
|
||||||
|
self.conv_textview.tv.show()
|
||||||
|
# moved from ChatControl
|
||||||
|
def _on_banner_eventbox_button_press_event(self, widget, event):
|
||||||
|
'''If right-clicked, show popup'''
|
||||||
|
if event.button == 3: # right click
|
||||||
|
self.parent_win.popup_menu(event)
|
||||||
|
|
||||||
def _on_send_button_clicked(self, widget):
|
def _on_send_button_clicked(self, widget):
|
||||||
'''When send button is pressed: send the current message'''
|
'''When send button is pressed: send the current message'''
|
||||||
|
@ -241,7 +252,7 @@ class ChatControlBase(MessageControl):
|
||||||
if event.state & gtk.gdk.CONTROL_MASK:
|
if event.state & gtk.gdk.CONTROL_MASK:
|
||||||
# CTRL + l|L: clear conv_textview
|
# CTRL + l|L: clear conv_textview
|
||||||
if event.keyval == gtk.keysyms.l or event.keyval == gtk.keysyms.L:
|
if event.keyval == gtk.keysyms.l or event.keyval == gtk.keysyms.L:
|
||||||
self.conv_textview.get_buffer().set_text('')
|
self.conv_textview.tv.get_buffer().set_text('')
|
||||||
return True
|
return True
|
||||||
# CTRL + v: Paste into msg_textview
|
# CTRL + v: Paste into msg_textview
|
||||||
elif event.keyval == gtk.keysyms.v:
|
elif event.keyval == gtk.keysyms.v:
|
||||||
|
@ -313,7 +324,7 @@ class ChatControlBase(MessageControl):
|
||||||
# SHIFT + PAGE_[UP|DOWN]: send to conv_textview
|
# SHIFT + PAGE_[UP|DOWN]: send to conv_textview
|
||||||
elif event.keyval == gtk.keysyms.Page_Down or \
|
elif event.keyval == gtk.keysyms.Page_Down or \
|
||||||
event.keyval == gtk.keysyms.Page_Up:
|
event.keyval == gtk.keysyms.Page_Up:
|
||||||
self.conv_textview.emit('key_press_event', event)
|
self.conv_textview.tv.emit('key_press_event', event)
|
||||||
return True
|
return True
|
||||||
elif event.state & gtk.gdk.CONTROL_MASK:
|
elif event.state & gtk.gdk.CONTROL_MASK:
|
||||||
if event.keyval == gtk.keysyms.Tab: # CTRL + TAB
|
if event.keyval == gtk.keysyms.Tab: # CTRL + TAB
|
||||||
|
@ -327,7 +338,7 @@ class ChatControlBase(MessageControl):
|
||||||
# we pressed a control key or ctrl+sth: we don't block
|
# we pressed a control key or ctrl+sth: we don't block
|
||||||
# the event in order to let ctrl+c (copy text) and
|
# the event in order to let ctrl+c (copy text) and
|
||||||
# others do their default work
|
# others do their default work
|
||||||
self.conv_textview.emit('key_press_event', event)
|
self.conv_textview.tv.emit('key_press_event', event)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _on_message_textview_mykeypress_event(self, widget, event_keyval,
|
def _on_message_textview_mykeypress_event(self, widget, event_keyval,
|
||||||
|
@ -394,7 +405,7 @@ class ChatControlBase(MessageControl):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if message == '/clear':
|
if message == '/clear':
|
||||||
self.conv_textview.clear() # clear conversation
|
self.conv_textview.tv.clear() # clear conversation
|
||||||
self.clear(self.msg_textview) # clear message textview too
|
self.clear(self.msg_textview) # clear message textview too
|
||||||
return True
|
return True
|
||||||
elif message == '/compact':
|
elif message == '/compact':
|
||||||
|
@ -501,7 +512,7 @@ class ChatControlBase(MessageControl):
|
||||||
|
|
||||||
def update_font(self):
|
def update_font(self):
|
||||||
font = pango.FontDescription(gajim.config.get('conversation_font'))
|
font = pango.FontDescription(gajim.config.get('conversation_font'))
|
||||||
self.conv_textview.modify_font(font)
|
self.conv_textview.tv.modify_font(font)
|
||||||
self.msg_textview.modify_font(font)
|
self.msg_textview.modify_font(font)
|
||||||
|
|
||||||
def update_tags(self):
|
def update_tags(self):
|
||||||
|
@ -569,7 +580,7 @@ class ChatControlBase(MessageControl):
|
||||||
return
|
return
|
||||||
|
|
||||||
min_height = self.conv_scrolledwindow.get_property('height-request')
|
min_height = self.conv_scrolledwindow.get_property('height-request')
|
||||||
conversation_height = self.conv_textview.window.get_size()[1]
|
conversation_height = self.conv_textview.tv.window.get_size()[1]
|
||||||
message_height = msg_textview.window.get_size()[1]
|
message_height = msg_textview.window.get_size()[1]
|
||||||
message_width = msg_textview.window.get_size()[0]
|
message_width = msg_textview.window.get_size()[0]
|
||||||
# new tab is not exposed yet
|
# new tab is not exposed yet
|
||||||
|
@ -731,11 +742,6 @@ class ChatControl(ChatControlBase):
|
||||||
id = message_tv_buffer.connect('changed', self._on_message_tv_buffer_changed)
|
id = message_tv_buffer.connect('changed', self._on_message_tv_buffer_changed)
|
||||||
self.handlers[id] = message_tv_buffer
|
self.handlers[id] = message_tv_buffer
|
||||||
|
|
||||||
widget = self.xml.get_widget('banner_eventbox')
|
|
||||||
id = widget.connect('button-press-event',
|
|
||||||
self._on_banner_eventbox_button_press_event)
|
|
||||||
self.handlers[id] = widget
|
|
||||||
|
|
||||||
widget = self.xml.get_widget('avatar_eventbox')
|
widget = self.xml.get_widget('avatar_eventbox')
|
||||||
id = widget.connect('enter-notify-event', self.on_avatar_eventbox_enter_notify_event)
|
id = widget.connect('enter-notify-event', self.on_avatar_eventbox_enter_notify_event)
|
||||||
self.handlers[id] = widget
|
self.handlers[id] = widget
|
||||||
|
@ -1198,19 +1204,25 @@ class ChatControl(ChatControlBase):
|
||||||
|
|
||||||
|
|
||||||
# connect signals
|
# connect signals
|
||||||
history_menuitem.connect('activate',
|
id = history_menuitem.connect('activate',
|
||||||
self._on_history_menuitem_activate)
|
self._on_history_menuitem_activate)
|
||||||
send_file_menuitem.connect('activate',
|
self.handlers[id] = history_menuitem
|
||||||
|
id = send_file_menuitem.connect('activate',
|
||||||
self._on_send_file_menuitem_activate)
|
self._on_send_file_menuitem_activate)
|
||||||
compact_view_menuitem.connect('activate',
|
self.handlers[id] = send_file_menuitem
|
||||||
|
id = compact_view_menuitem.connect('activate',
|
||||||
self._on_compact_view_menuitem_activate)
|
self._on_compact_view_menuitem_activate)
|
||||||
add_to_roster_menuitem.connect('activate',
|
self.handlers[id] = compact_view_menuitem
|
||||||
|
id = add_to_roster_menuitem.connect('activate',
|
||||||
self._on_add_to_roster_menuitem_activate)
|
self._on_add_to_roster_menuitem_activate)
|
||||||
toggle_gpg_menuitem.connect('activate',
|
self.handlers[id] = add_to_roster_menuitem
|
||||||
|
id = toggle_gpg_menuitem.connect('activate',
|
||||||
self._on_toggle_gpg_menuitem_activate)
|
self._on_toggle_gpg_menuitem_activate)
|
||||||
information_menuitem.connect('activate',
|
self.handlers[id] = toggle_gpg_menuitem
|
||||||
|
id = information_menuitem.connect('activate',
|
||||||
self._on_contact_information_menuitem_activate)
|
self._on_contact_information_menuitem_activate)
|
||||||
menu.connect('selection-done', gtkgui_helpers.destroy_widget)
|
self.handlers[id] = information_menuitem
|
||||||
|
menu.connect('selection-done', lambda w:w.destroy())
|
||||||
return menu
|
return menu
|
||||||
|
|
||||||
def send_chatstate(self, state, contact = None):
|
def send_chatstate(self, state, contact = None):
|
||||||
|
@ -1311,8 +1323,11 @@ class ChatControl(ChatControlBase):
|
||||||
# remove all register handlers on wigets, created by self.xml
|
# remove all register handlers on wigets, created by self.xml
|
||||||
# to prevent circular references among objects
|
# to prevent circular references among objects
|
||||||
for i in self.handlers.keys():
|
for i in self.handlers.keys():
|
||||||
|
if self.handlers[i].handler_is_connected(i):
|
||||||
self.handlers[i].disconnect(i)
|
self.handlers[i].disconnect(i)
|
||||||
del self.handlers[i]
|
del self.handlers[i]
|
||||||
|
self.conv_textview.del_handlers()
|
||||||
|
self.msg_textview.destroy()
|
||||||
|
|
||||||
|
|
||||||
def allow_shutdown(self):
|
def allow_shutdown(self):
|
||||||
|
@ -1334,11 +1349,6 @@ class ChatControl(ChatControlBase):
|
||||||
# update chatstate in tab for this chat
|
# update chatstate in tab for this chat
|
||||||
self.parent_win.redraw_tab(self, self.contact.chatstate)
|
self.parent_win.redraw_tab(self, self.contact.chatstate)
|
||||||
|
|
||||||
def _on_banner_eventbox_button_press_event(self, widget, event):
|
|
||||||
'''If right-clicked, show popup'''
|
|
||||||
if event.button == 3: # right click
|
|
||||||
self.parent_win.popup_menu(event)
|
|
||||||
|
|
||||||
def set_control_active(self, state):
|
def set_control_active(self, state):
|
||||||
ChatControlBase.set_control_active(self, state)
|
ChatControlBase.set_control_active(self, state)
|
||||||
# send chatstate inactive to the one we're leaving
|
# send chatstate inactive to the one we're leaving
|
||||||
|
|
|
@ -44,33 +44,38 @@ gtk.glade.textdomain(APP)
|
||||||
|
|
||||||
GTKGUI_GLADE = 'gtkgui.glade'
|
GTKGUI_GLADE = 'gtkgui.glade'
|
||||||
|
|
||||||
class ConversationTextview(gtk.TextView):
|
class ConversationTextview:
|
||||||
'''Class for the conversation textview (where user reads already said messages)
|
'''Class for the conversation textview (where user reads already said messages)
|
||||||
for chat/groupchat windows'''
|
for chat/groupchat windows'''
|
||||||
def __init__(self, account):
|
def __init__(self, account):
|
||||||
gtk.TextView.__init__(self)
|
# no need to inherit TextView, use it as property is safer
|
||||||
|
self.tv = gtk.TextView()
|
||||||
|
|
||||||
# set properties
|
# set properties
|
||||||
self.set_border_width(1)
|
self.tv.set_border_width(1)
|
||||||
self.set_accepts_tab(True)
|
self.tv.set_accepts_tab(True)
|
||||||
self.set_editable(False)
|
self.tv.set_editable(False)
|
||||||
self.set_cursor_visible(False)
|
self.tv.set_cursor_visible(False)
|
||||||
self.set_wrap_mode(gtk.WRAP_WORD)
|
self.tv.set_wrap_mode(gtk.WRAP_WORD)
|
||||||
self.set_left_margin(2)
|
self.tv.set_left_margin(2)
|
||||||
self.set_right_margin(2)
|
self.tv.set_right_margin(2)
|
||||||
|
self.handlers = {}
|
||||||
|
|
||||||
# connect signals
|
# connect signals
|
||||||
self.connect('motion_notify_event', self.on_textview_motion_notify_event)
|
id = self.tv.connect('motion_notify_event', self.on_textview_motion_notify_event)
|
||||||
self.connect('populate_popup', self.on_textview_populate_popup)
|
self.handlers[id] = self.tv
|
||||||
self.connect('button_press_event', self.on_textview_button_press_event)
|
id = self.tv.connect('populate_popup', self.on_textview_populate_popup)
|
||||||
|
self.handlers[id] = self.tv
|
||||||
|
id = self.tv.connect('button_press_event', self.on_textview_button_press_event)
|
||||||
|
self.handlers[id] = self.tv
|
||||||
|
|
||||||
self.account = account
|
self.account = account
|
||||||
self.change_cursor = None
|
self.change_cursor = None
|
||||||
self.last_time_printout = 0
|
self.last_time_printout = 0
|
||||||
|
|
||||||
font = pango.FontDescription(gajim.config.get('conversation_font'))
|
font = pango.FontDescription(gajim.config.get('conversation_font'))
|
||||||
self.modify_font(font)
|
self.tv.modify_font(font)
|
||||||
buffer = self.get_buffer()
|
buffer = self.tv.get_buffer()
|
||||||
end_iter = buffer.get_end_iter()
|
end_iter = buffer.get_end_iter()
|
||||||
buffer.create_mark('end', end_iter, False)
|
buffer.create_mark('end', end_iter, False)
|
||||||
|
|
||||||
|
@ -105,12 +110,14 @@ class ConversationTextview(gtk.TextView):
|
||||||
color = gajim.config.get('urlmsgcolor')
|
color = gajim.config.get('urlmsgcolor')
|
||||||
tag.set_property('foreground', color)
|
tag.set_property('foreground', color)
|
||||||
tag.set_property('underline', pango.UNDERLINE_SINGLE)
|
tag.set_property('underline', pango.UNDERLINE_SINGLE)
|
||||||
tag.connect('event', self.hyperlink_handler, 'url')
|
id = tag.connect('event', self.hyperlink_handler, 'url')
|
||||||
|
self.handlers[id] = tag
|
||||||
|
|
||||||
tag = buffer.create_tag('mail')
|
tag = buffer.create_tag('mail')
|
||||||
tag.set_property('foreground', color)
|
tag.set_property('foreground', color)
|
||||||
tag.set_property('underline', pango.UNDERLINE_SINGLE)
|
tag.set_property('underline', pango.UNDERLINE_SINGLE)
|
||||||
tag.connect('event', self.hyperlink_handler, 'mail')
|
id = tag.connect('event', self.hyperlink_handler, 'mail')
|
||||||
|
self.handlers[id] = tag
|
||||||
|
|
||||||
tag = buffer.create_tag('bold')
|
tag = buffer.create_tag('bold')
|
||||||
tag.set_property('weight', pango.WEIGHT_BOLD)
|
tag.set_property('weight', pango.WEIGHT_BOLD)
|
||||||
|
@ -125,6 +132,14 @@ class ConversationTextview(gtk.TextView):
|
||||||
|
|
||||||
self.line_tooltip = tooltips.BaseTooltip()
|
self.line_tooltip = tooltips.BaseTooltip()
|
||||||
|
|
||||||
|
def del_handlers(self):
|
||||||
|
for i in self.handlers.keys():
|
||||||
|
self.handlers[i].disconnect(i)
|
||||||
|
del self.handlers
|
||||||
|
self.tv.destroy()
|
||||||
|
#TODO
|
||||||
|
# self.line_tooltip.destroy()
|
||||||
|
|
||||||
def update_tags(self):
|
def update_tags(self):
|
||||||
self.tagIn.set_property('foreground', gajim.config.get('inmsgcolor'))
|
self.tagIn.set_property('foreground', gajim.config.get('inmsgcolor'))
|
||||||
self.tagOut.set_property('foreground', gajim.config.get('outmsgcolor'))
|
self.tagOut.set_property('foreground', gajim.config.get('outmsgcolor'))
|
||||||
|
@ -132,44 +147,44 @@ class ConversationTextview(gtk.TextView):
|
||||||
gajim.config.get('statusmsgcolor'))
|
gajim.config.get('statusmsgcolor'))
|
||||||
|
|
||||||
def at_the_end(self):
|
def at_the_end(self):
|
||||||
buffer = self.get_buffer()
|
buffer = self.tv.get_buffer()
|
||||||
end_iter = buffer.get_end_iter()
|
end_iter = buffer.get_end_iter()
|
||||||
end_rect = self.get_iter_location(end_iter)
|
end_rect = self.tv.get_iter_location(end_iter)
|
||||||
visible_rect = self.get_visible_rect()
|
visible_rect = self.tv.get_visible_rect()
|
||||||
if end_rect.y <= (visible_rect.y + visible_rect.height):
|
if end_rect.y <= (visible_rect.y + visible_rect.height):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def scroll_to_end(self):
|
def scroll_to_end(self):
|
||||||
parent = self.get_parent()
|
parent = self.tv.get_parent()
|
||||||
buffer = self.get_buffer()
|
buffer = self.tv.get_buffer()
|
||||||
self.scroll_to_mark(buffer.get_mark('end'), 0, True, 0, 1)
|
self.tv.scroll_to_mark(buffer.get_mark('end'), 0, True, 0, 1)
|
||||||
adjustment = parent.get_hadjustment()
|
adjustment = parent.get_hadjustment()
|
||||||
adjustment.set_value(0)
|
adjustment.set_value(0)
|
||||||
return False # when called in an idle_add, just do it once
|
return False # when called in an idle_add, just do it once
|
||||||
|
|
||||||
def bring_scroll_to_end(self, diff_y = 0):
|
def bring_scroll_to_end(self, diff_y = 0):
|
||||||
''' scrolls to the end of textview if end is not visible '''
|
''' scrolls to the end of textview if end is not visible '''
|
||||||
buffer = self.get_buffer()
|
buffer = self.tv.get_buffer()
|
||||||
end_iter = buffer.get_end_iter()
|
end_iter = buffer.get_end_iter()
|
||||||
end_rect = self.get_iter_location(end_iter)
|
end_rect = self.tv.get_iter_location(end_iter)
|
||||||
visible_rect = self.get_visible_rect()
|
visible_rect = self.tv.get_visible_rect()
|
||||||
# scroll only if expected end is not visible
|
# scroll only if expected end is not visible
|
||||||
if end_rect.y >= (visible_rect.y + visible_rect.height + diff_y):
|
if end_rect.y >= (visible_rect.y + visible_rect.height + diff_y):
|
||||||
gobject.idle_add(self.scroll_to_end_iter)
|
gobject.idle_add(self.scroll_to_end_iter)
|
||||||
|
|
||||||
def scroll_to_end_iter(self):
|
def scroll_to_end_iter(self):
|
||||||
buffer = self.get_buffer()
|
buffer = self.tv.get_buffer()
|
||||||
end_iter = buffer.get_end_iter()
|
end_iter = buffer.get_end_iter()
|
||||||
self.scroll_to_iter(end_iter, 0, False, 1, 1)
|
self.tv.scroll_to_iter(end_iter, 0, False, 1, 1)
|
||||||
return False # when called in an idle_add, just do it once
|
return False # when called in an idle_add, just do it once
|
||||||
|
|
||||||
def show_line_tooltip(self):
|
def show_line_tooltip(self):
|
||||||
pointer = self.get_pointer()
|
pointer = self.tv.get_pointer()
|
||||||
x, y = self.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, pointer[0],
|
x, y = self.tv.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, pointer[0],
|
||||||
pointer[1])
|
pointer[1])
|
||||||
tags = self.get_iter_at_location(x, y).get_tags()
|
tags = self.tv.get_iter_at_location(x, y).get_tags()
|
||||||
tag_table = self.get_buffer().get_tag_table()
|
tag_table = self.tv.get_buffer().get_tag_table()
|
||||||
over_line = False
|
over_line = False
|
||||||
for tag in tags:
|
for tag in tags:
|
||||||
if tag == tag_table.lookup('focus-out-line'):
|
if tag == tag_table.lookup('focus-out-line'):
|
||||||
|
@ -177,26 +192,26 @@ class ConversationTextview(gtk.TextView):
|
||||||
break
|
break
|
||||||
if over_line and not self.line_tooltip.win:
|
if over_line and not self.line_tooltip.win:
|
||||||
# check if the current pointer is still over the line
|
# check if the current pointer is still over the line
|
||||||
position = self.window.get_origin()
|
position = self.tv.window.get_origin()
|
||||||
win = self.get_toplevel()
|
win = self.tv.get_toplevel()
|
||||||
self.line_tooltip.show_tooltip(_('Text below this line is what has '
|
self.line_tooltip.show_tooltip(_('Text below this line is what has '
|
||||||
'been said since the last time you paid attention to this group chat'), 8, position[1] + pointer[1])
|
'been said since the last time you paid attention to this group chat'), 8, position[1] + pointer[1])
|
||||||
|
|
||||||
def on_textview_motion_notify_event(self, widget, event):
|
def on_textview_motion_notify_event(self, widget, event):
|
||||||
'''change the cursor to a hand when we are over a mail or an url'''
|
'''change the cursor to a hand when we are over a mail or an url'''
|
||||||
pointer_x, pointer_y, spam = self.window.get_pointer()
|
pointer_x, pointer_y, spam = self.tv.window.get_pointer()
|
||||||
x, y = self.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, pointer_x,
|
x, y = self.tv.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, pointer_x,
|
||||||
pointer_y)
|
pointer_y)
|
||||||
tags = self.get_iter_at_location(x, y).get_tags()
|
tags = self.tv.get_iter_at_location(x, y).get_tags()
|
||||||
if self.change_cursor:
|
if self.change_cursor:
|
||||||
self.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(
|
self.tv.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(
|
||||||
gtk.gdk.Cursor(gtk.gdk.XTERM))
|
gtk.gdk.Cursor(gtk.gdk.XTERM))
|
||||||
self.change_cursor = None
|
self.change_cursor = None
|
||||||
tag_table = self.get_buffer().get_tag_table()
|
tag_table = self.tv.get_buffer().get_tag_table()
|
||||||
over_line = False
|
over_line = False
|
||||||
for tag in tags:
|
for tag in tags:
|
||||||
if tag in (tag_table.lookup('url'), tag_table.lookup('mail')):
|
if tag in (tag_table.lookup('url'), tag_table.lookup('mail')):
|
||||||
self.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(
|
self.tv.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(
|
||||||
gtk.gdk.Cursor(gtk.gdk.HAND2))
|
gtk.gdk.Cursor(gtk.gdk.HAND2))
|
||||||
self.change_cursor = tag
|
self.change_cursor = tag
|
||||||
elif tag == tag_table.lookup('focus-out-line'):
|
elif tag == tag_table.lookup('focus-out-line'):
|
||||||
|
@ -209,13 +224,13 @@ class ConversationTextview(gtk.TextView):
|
||||||
if over_line and not self.line_tooltip.win:
|
if over_line and not self.line_tooltip.win:
|
||||||
self.line_tooltip.timeout = gobject.timeout_add(500,
|
self.line_tooltip.timeout = gobject.timeout_add(500,
|
||||||
self.show_line_tooltip)
|
self.show_line_tooltip)
|
||||||
self.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(
|
self.tv.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(
|
||||||
gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))
|
gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))
|
||||||
self.change_cursor = tag
|
self.change_cursor = tag
|
||||||
|
|
||||||
def clear(self, tv = None):
|
def clear(self, tv = None):
|
||||||
'''clear text in the textview'''
|
'''clear text in the textview'''
|
||||||
buffer = self.get_buffer()
|
buffer = self.tv.get_buffer()
|
||||||
start, end = buffer.get_bounds()
|
start, end = buffer.get_bounds()
|
||||||
buffer.delete(start, end)
|
buffer.delete(start, end)
|
||||||
|
|
||||||
|
@ -231,7 +246,8 @@ class ConversationTextview(gtk.TextView):
|
||||||
menu.prepend(item)
|
menu.prepend(item)
|
||||||
item = gtk.ImageMenuItem(gtk.STOCK_CLEAR)
|
item = gtk.ImageMenuItem(gtk.STOCK_CLEAR)
|
||||||
menu.prepend(item)
|
menu.prepend(item)
|
||||||
item.connect('activate', self.clear)
|
id = item.connect('activate', self.clear)
|
||||||
|
self.handlers[id] = item
|
||||||
if self.selected_phrase:
|
if self.selected_phrase:
|
||||||
s = self.selected_phrase
|
s = self.selected_phrase
|
||||||
if len(s) > 25:
|
if len(s) > 25:
|
||||||
|
@ -249,7 +265,8 @@ class ConversationTextview(gtk.TextView):
|
||||||
link = 'http://%s.wikipedia.org/wiki/Special:Search?search=%s'\
|
link = 'http://%s.wikipedia.org/wiki/Special:Search?search=%s'\
|
||||||
% (gajim.LANG, self.selected_phrase)
|
% (gajim.LANG, self.selected_phrase)
|
||||||
item = gtk.MenuItem(_('Read _Wikipedia Article'))
|
item = gtk.MenuItem(_('Read _Wikipedia Article'))
|
||||||
item.connect('activate', self.visit_url_from_menuitem, link)
|
id = item.connect('activate', self.visit_url_from_menuitem, link)
|
||||||
|
self.handlers[id] = item
|
||||||
submenu.append(item)
|
submenu.append(item)
|
||||||
|
|
||||||
item = gtk.MenuItem(_('Look it up in _Dictionary'))
|
item = gtk.MenuItem(_('Look it up in _Dictionary'))
|
||||||
|
@ -263,7 +280,8 @@ class ConversationTextview(gtk.TextView):
|
||||||
else:
|
else:
|
||||||
link = 'http://%s.wiktionary.org/wiki/Special:Search?search=%s'\
|
link = 'http://%s.wiktionary.org/wiki/Special:Search?search=%s'\
|
||||||
% (gajim.LANG, self.selected_phrase)
|
% (gajim.LANG, self.selected_phrase)
|
||||||
item.connect('activate', self.visit_url_from_menuitem, link)
|
id = item.connect('activate', self.visit_url_from_menuitem, link)
|
||||||
|
self.handlers[id] = item
|
||||||
else:
|
else:
|
||||||
if dict_link.find('%s') == -1:
|
if dict_link.find('%s') == -1:
|
||||||
#we must have %s in the url if not WIKTIONARY
|
#we must have %s in the url if not WIKTIONARY
|
||||||
|
@ -271,7 +289,8 @@ class ConversationTextview(gtk.TextView):
|
||||||
item.set_property('sensitive', False)
|
item.set_property('sensitive', False)
|
||||||
else:
|
else:
|
||||||
link = dict_link % self.selected_phrase
|
link = dict_link % self.selected_phrase
|
||||||
item.connect('activate', self.visit_url_from_menuitem, link)
|
id = item.connect('activate', self.visit_url_from_menuitem, link)
|
||||||
|
self.handlers[id] = item
|
||||||
submenu.append(item)
|
submenu.append(item)
|
||||||
|
|
||||||
|
|
||||||
|
@ -283,7 +302,8 @@ class ConversationTextview(gtk.TextView):
|
||||||
else:
|
else:
|
||||||
item = gtk.MenuItem(_('Web _Search for it'))
|
item = gtk.MenuItem(_('Web _Search for it'))
|
||||||
link = search_link % self.selected_phrase
|
link = search_link % self.selected_phrase
|
||||||
item.connect('activate', self.visit_url_from_menuitem, link)
|
id = item.connect('activate', self.visit_url_from_menuitem, link)
|
||||||
|
self.handlers[id] = item
|
||||||
submenu.append(item)
|
submenu.append(item)
|
||||||
|
|
||||||
menu.show_all()
|
menu.show_all()
|
||||||
|
@ -297,10 +317,10 @@ class ConversationTextview(gtk.TextView):
|
||||||
if event.button != 3: # if not right click
|
if event.button != 3: # if not right click
|
||||||
return False
|
return False
|
||||||
|
|
||||||
win = self.get_window(gtk.TEXT_WINDOW_TEXT)
|
win = self.tv.get_window(gtk.TEXT_WINDOW_TEXT)
|
||||||
x, y = self.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT,
|
x, y = self.tv.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT,
|
||||||
int(event.x), int(event.y))
|
int(event.x), int(event.y))
|
||||||
iter = self.get_iter_at_location(x, y)
|
iter = self.tv.get_iter_at_location(x, y)
|
||||||
tags = iter.get_tags()
|
tags = iter.get_tags()
|
||||||
|
|
||||||
|
|
||||||
|
@ -313,7 +333,7 @@ class ConversationTextview(gtk.TextView):
|
||||||
# we check if sth was selected and if it was we assign
|
# we check if sth was selected and if it was we assign
|
||||||
# selected_phrase variable
|
# selected_phrase variable
|
||||||
# so on_conversation_textview_populate_popup can use it
|
# so on_conversation_textview_populate_popup can use it
|
||||||
buffer = self.get_buffer()
|
buffer = self.tv.get_buffer()
|
||||||
return_val = buffer.get_selection_bounds()
|
return_val = buffer.get_selection_bounds()
|
||||||
if return_val: # if sth was selected when we right-clicked
|
if return_val: # if sth was selected when we right-clicked
|
||||||
# get the selected text
|
# get the selected text
|
||||||
|
@ -352,8 +372,10 @@ class ConversationTextview(gtk.TextView):
|
||||||
menu = xml.get_widget('chat_context_menu')
|
menu = xml.get_widget('chat_context_menu')
|
||||||
childs = menu.get_children()
|
childs = menu.get_children()
|
||||||
if kind == 'url':
|
if kind == 'url':
|
||||||
childs[0].connect('activate', self.on_copy_link_activate, text)
|
id = childs[0].connect('activate', self.on_copy_link_activate, text)
|
||||||
childs[1].connect('activate', self.on_open_link_activate, kind, text)
|
self.handlers[id] = childs[0]
|
||||||
|
id = childs[1].connect('activate', self.on_open_link_activate, kind, text)
|
||||||
|
self.handlers[id] = childs[1]
|
||||||
childs[2].hide() # copy mail address
|
childs[2].hide() # copy mail address
|
||||||
childs[3].hide() # open mail composer
|
childs[3].hide() # open mail composer
|
||||||
childs[4].hide() # jid section separator
|
childs[4].hide() # jid section separator
|
||||||
|
@ -361,11 +383,15 @@ class ConversationTextview(gtk.TextView):
|
||||||
childs[6].hide() # join group chat
|
childs[6].hide() # join group chat
|
||||||
childs[7].hide() # add to roster
|
childs[7].hide() # add to roster
|
||||||
else: # It's a mail or a JID
|
else: # It's a mail or a JID
|
||||||
childs[2].connect('activate', self.on_copy_link_activate, text)
|
id = childs[2].connect('activate', self.on_copy_link_activate, text)
|
||||||
childs[3].connect('activate', self.on_open_link_activate, kind, text)
|
self.handlers[id] = childs[2]
|
||||||
childs[5].connect('activate', self.on_start_chat_activate, text)
|
id = childs[3].connect('activate', self.on_open_link_activate, kind, text)
|
||||||
childs[6].connect('activate',
|
self.handlers[id] = childs[3]
|
||||||
|
id = childs[5].connect('activate', self.on_start_chat_activate, text)
|
||||||
|
self.handlers[id] = childs[5]
|
||||||
|
id = childs[6].connect('activate',
|
||||||
self.on_join_group_chat_menuitem_activate, text)
|
self.on_join_group_chat_menuitem_activate, text)
|
||||||
|
self.handlers[id] = childs[6]
|
||||||
|
|
||||||
allow_add = False
|
allow_add = False
|
||||||
c = gajim.contacts.get_first_contact_from_jid(self.account, text)
|
c = gajim.contacts.get_first_contact_from_jid(self.account, text)
|
||||||
|
@ -376,7 +402,8 @@ class ConversationTextview(gtk.TextView):
|
||||||
allow_add = True
|
allow_add = True
|
||||||
|
|
||||||
if allow_add:
|
if allow_add:
|
||||||
childs[7].connect('activate', self.on_add_to_roster_activate, text)
|
id = childs[7].connect('activate', self.on_add_to_roster_activate, text)
|
||||||
|
self.handlers[id] = childs[7]
|
||||||
childs[7].show() # show add to roster menuitem
|
childs[7].show() # show add to roster menuitem
|
||||||
else:
|
else:
|
||||||
childs[7].hide() # hide add to roster menuitem
|
childs[7].hide() # hide add to roster menuitem
|
||||||
|
@ -396,7 +423,7 @@ class ConversationTextview(gtk.TextView):
|
||||||
# we get the end of the tag
|
# we get the end of the tag
|
||||||
while not end_iter.ends_tag(texttag):
|
while not end_iter.ends_tag(texttag):
|
||||||
end_iter.forward_char()
|
end_iter.forward_char()
|
||||||
word = self.get_buffer().get_text(begin_iter, end_iter).decode('utf-8')
|
word = self.tv.get_buffer().get_text(begin_iter, end_iter).decode('utf-8')
|
||||||
if event.button == 3: # right click
|
if event.button == 3: # right click
|
||||||
self.make_link_menu(event, kind, word)
|
self.make_link_menu(event, kind, word)
|
||||||
else:
|
else:
|
||||||
|
@ -411,7 +438,7 @@ class ConversationTextview(gtk.TextView):
|
||||||
after *last* special text, so we can print it in
|
after *last* special text, so we can print it in
|
||||||
print_conversation_line()'''
|
print_conversation_line()'''
|
||||||
|
|
||||||
buffer = self.get_buffer()
|
buffer = self.tv.get_buffer()
|
||||||
|
|
||||||
start = 0
|
start = 0
|
||||||
end = 0
|
end = 0
|
||||||
|
@ -445,7 +472,7 @@ class ConversationTextview(gtk.TextView):
|
||||||
use_other_tags = True
|
use_other_tags = True
|
||||||
show_ascii_formatting_chars = \
|
show_ascii_formatting_chars = \
|
||||||
gajim.config.get('show_ascii_formatting_chars')
|
gajim.config.get('show_ascii_formatting_chars')
|
||||||
buffer = self.get_buffer()
|
buffer = self.tv.get_buffer()
|
||||||
|
|
||||||
possible_emot_ascii_caps = special_text.upper() # emoticons keys are CAPS
|
possible_emot_ascii_caps = special_text.upper() # emoticons keys are CAPS
|
||||||
if gajim.config.get('emoticons_theme') and \
|
if gajim.config.get('emoticons_theme') and \
|
||||||
|
@ -458,7 +485,7 @@ class ConversationTextview(gtk.TextView):
|
||||||
img.set_from_file(gajim.interface.emoticons[emot_ascii])
|
img.set_from_file(gajim.interface.emoticons[emot_ascii])
|
||||||
img.show()
|
img.show()
|
||||||
#add with possible animation
|
#add with possible animation
|
||||||
self.add_child_at_anchor(img, anchor)
|
self.tv.add_child_at_anchor(img, anchor)
|
||||||
elif special_text.startswith('http://') or \
|
elif special_text.startswith('http://') or \
|
||||||
special_text.startswith('www.') or \
|
special_text.startswith('www.') or \
|
||||||
special_text.startswith('ftp://') or \
|
special_text.startswith('ftp://') or \
|
||||||
|
@ -533,7 +560,7 @@ class ConversationTextview(gtk.TextView):
|
||||||
buffer.insert_with_tags_by_name(end_iter, special_text, *all_tags)
|
buffer.insert_with_tags_by_name(end_iter, special_text, *all_tags)
|
||||||
|
|
||||||
def print_empty_line(self):
|
def print_empty_line(self):
|
||||||
buffer = self.get_buffer()
|
buffer = self.tv.get_buffer()
|
||||||
end_iter = buffer.get_end_iter()
|
end_iter = buffer.get_end_iter()
|
||||||
buffer.insert(end_iter, '\n')
|
buffer.insert(end_iter, '\n')
|
||||||
|
|
||||||
|
@ -546,7 +573,7 @@ class ConversationTextview(gtk.TextView):
|
||||||
# kind = info, we print things as if it was a status: same color, ...
|
# kind = info, we print things as if it was a status: same color, ...
|
||||||
if kind == 'info':
|
if kind == 'info':
|
||||||
kind = 'status'
|
kind = 'status'
|
||||||
buffer = self.get_buffer()
|
buffer = self.tv.get_buffer()
|
||||||
buffer.begin_user_action()
|
buffer.begin_user_action()
|
||||||
end_iter = buffer.get_end_iter()
|
end_iter = buffer.get_end_iter()
|
||||||
at_the_end = False
|
at_the_end = False
|
||||||
|
@ -620,7 +647,7 @@ class ConversationTextview(gtk.TextView):
|
||||||
|
|
||||||
def print_name(self, name, kind, other_tags_for_name):
|
def print_name(self, name, kind, other_tags_for_name):
|
||||||
if name:
|
if name:
|
||||||
buffer = self.get_buffer()
|
buffer = self.tv.get_buffer()
|
||||||
end_iter = buffer.get_end_iter()
|
end_iter = buffer.get_end_iter()
|
||||||
name_tags = other_tags_for_name[:] # create a new list
|
name_tags = other_tags_for_name[:] # create a new list
|
||||||
name_tags.append(kind)
|
name_tags.append(kind)
|
||||||
|
@ -632,14 +659,14 @@ class ConversationTextview(gtk.TextView):
|
||||||
def print_subject(self, subject):
|
def print_subject(self, subject):
|
||||||
if subject: # if we have subject, show it too!
|
if subject: # if we have subject, show it too!
|
||||||
subject = _('Subject: %s\n') % subject
|
subject = _('Subject: %s\n') % subject
|
||||||
buffer = self.get_buffer()
|
buffer = self.tv.get_buffer()
|
||||||
end_iter = buffer.get_end_iter()
|
end_iter = buffer.get_end_iter()
|
||||||
buffer.insert(end_iter, subject)
|
buffer.insert(end_iter, subject)
|
||||||
self.print_empty_line()
|
self.print_empty_line()
|
||||||
|
|
||||||
def print_real_text(self, text, text_tags = [], name = None):
|
def print_real_text(self, text, text_tags = [], name = None):
|
||||||
'''this adds normal and special text. call this to add text'''
|
'''this adds normal and special text. call this to add text'''
|
||||||
buffer = self.get_buffer()
|
buffer = self.tv.get_buffer()
|
||||||
# /me is replaced by name if name is given
|
# /me is replaced by name if name is given
|
||||||
if name and (text.startswith('/me ') or text.startswith('/me\n')):
|
if name and (text.startswith('/me ') or text.startswith('/me\n')):
|
||||||
text = '* ' + name + text[3:]
|
text = '* ' + name + text[3:]
|
||||||
|
|
|
@ -299,7 +299,7 @@ class GroupchatControl(ChatControlBase):
|
||||||
self.got_disconnected() #init some variables
|
self.got_disconnected() #init some variables
|
||||||
|
|
||||||
self.update_ui()
|
self.update_ui()
|
||||||
self.conv_textview.grab_focus()
|
self.conv_textview.tv.grab_focus()
|
||||||
self.widget.show_all()
|
self.widget.show_all()
|
||||||
|
|
||||||
def notify_on_new_messages(self):
|
def notify_on_new_messages(self):
|
||||||
|
@ -568,7 +568,7 @@ class GroupchatControl(ChatControlBase):
|
||||||
return
|
return
|
||||||
|
|
||||||
print_focus_out_line = False
|
print_focus_out_line = False
|
||||||
buffer = self.conv_textview.get_buffer()
|
buffer = self.conv_textview.tv.get_buffer()
|
||||||
|
|
||||||
if self.focus_out_end_iter_offset is None:
|
if self.focus_out_end_iter_offset is None:
|
||||||
# this happens only first time we focus out on this room
|
# this happens only first time we focus out on this room
|
||||||
|
@ -1179,6 +1179,7 @@ class GroupchatControl(ChatControlBase):
|
||||||
# remove all register handlers on wigets, created by self.xml
|
# remove all register handlers on wigets, created by self.xml
|
||||||
# to prevent circular references among objects
|
# to prevent circular references among objects
|
||||||
for i in self.handlers.keys():
|
for i in self.handlers.keys():
|
||||||
|
if self.handlers[i].handler_is_connected(i):
|
||||||
self.handlers[i].disconnect(i)
|
self.handlers[i].disconnect(i)
|
||||||
del self.handlers[i]
|
del self.handlers[i]
|
||||||
|
|
||||||
|
|
|
@ -18028,9 +18028,6 @@ Maybe I'll refactor later</property>
|
||||||
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
|
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
|
||||||
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
|
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
|
||||||
<property name="focus_on_map">True</property>
|
<property name="focus_on_map">True</property>
|
||||||
<signal name="delete_event" handler="_on_window_delete" last_modification_time="Thu, 12 Jan 2006 02:55:53 GMT"/>
|
|
||||||
<signal name="destroy" handler="_on_window_destroy" last_modification_time="Thu, 12 Jan 2006 02:56:25 GMT"/>
|
|
||||||
<signal name="focus_in_event" handler="_on_window_focus" last_modification_time="Thu, 12 Jan 2006 02:56:55 GMT"/>
|
|
||||||
|
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkAlignment" id="msg_window_alignment">
|
<widget class="GtkAlignment" id="msg_window_alignment">
|
||||||
|
@ -18623,7 +18620,6 @@ Status message</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="relief">GTK_RELIEF_NONE</property>
|
<property name="relief">GTK_RELIEF_NONE</property>
|
||||||
<property name="focus_on_click">True</property>
|
<property name="focus_on_click">True</property>
|
||||||
<signal name="clicked" handler="on_close_button_clicked" last_modification_time="Sat, 12 Mar 2005 00:12:43 GMT"/>
|
|
||||||
|
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkImage" id="image1329">
|
<widget class="GtkImage" id="image1329">
|
||||||
|
@ -18674,7 +18670,6 @@ Status message</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="visible_window">True</property>
|
<property name="visible_window">True</property>
|
||||||
<property name="above_child">False</property>
|
<property name="above_child">False</property>
|
||||||
<signal name="button_press_event" handler="on_banner_eventbox_button_press_event" last_modification_time="Mon, 08 Aug 2005 15:32:39 GMT"/>
|
|
||||||
|
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkLabel" id="banner_name_label">
|
<widget class="GtkLabel" id="banner_name_label">
|
||||||
|
@ -18694,7 +18689,6 @@ topic</property>
|
||||||
<property name="width_chars">-1</property>
|
<property name="width_chars">-1</property>
|
||||||
<property name="single_line_mode">False</property>
|
<property name="single_line_mode">False</property>
|
||||||
<property name="angle">0</property>
|
<property name="angle">0</property>
|
||||||
<signal name="button_press_event" handler="on_banner_label_button_press_event" last_modification_time="Sun, 07 Aug 2005 15:07:13 GMT"/>
|
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -18856,7 +18850,6 @@ topic</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||||
<property name="focus_on_click">True</property>
|
<property name="focus_on_click">True</property>
|
||||||
<signal name="clicked" handler="on_emoticons_button_clicked" last_modification_time="Thu, 17 Nov 2005 18:06:37 GMT"/>
|
|
||||||
|
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkHBox" id="hbox3014">
|
<widget class="GtkHBox" id="hbox3014">
|
||||||
|
@ -19114,7 +19107,6 @@ topic</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="visible_window">False</property>
|
<property name="visible_window">False</property>
|
||||||
<property name="above_child">False</property>
|
<property name="above_child">False</property>
|
||||||
<signal name="button_press_event" handler="on_tab_eventbox_button_press_event" last_modification_time="Thu, 04 Aug 2005 09:38:11 GMT"/>
|
|
||||||
|
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkHBox" id="hbox3017">
|
<widget class="GtkHBox" id="hbox3017">
|
||||||
|
@ -19170,7 +19162,6 @@ topic</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="relief">GTK_RELIEF_NONE</property>
|
<property name="relief">GTK_RELIEF_NONE</property>
|
||||||
<property name="focus_on_click">True</property>
|
<property name="focus_on_click">True</property>
|
||||||
<signal name="clicked" handler="on_close_button_clicked" last_modification_time="Sat, 12 Mar 2005 00:12:43 GMT"/>
|
|
||||||
|
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkImage" id="image1347">
|
<widget class="GtkImage" id="image1347">
|
||||||
|
|
|
@ -47,12 +47,13 @@ screen_h = gtk.gdk.screen_height()
|
||||||
|
|
||||||
def popup_emoticons_under_button(menu, button, parent_win):
|
def popup_emoticons_under_button(menu, button, parent_win):
|
||||||
''' pops emoticons menu under button, which is in parent_win'''
|
''' pops emoticons menu under button, which is in parent_win'''
|
||||||
|
window_x1, window_y1 = parent_win.get_origin()
|
||||||
def position_menu_under_button(menu):
|
def position_menu_under_button(menu):
|
||||||
# inline function, which will not keep refs, when used as CB
|
# inline function, which will not keep refs, when used as CB
|
||||||
button_x, button_y = button.allocation.x, button.allocation.y
|
button_x, button_y = button.allocation.x, button.allocation.y
|
||||||
|
|
||||||
# now convert them to X11-relative
|
# now convert them to X11-relative
|
||||||
window_x, window_y = parent_win.get_origin()
|
window_x, window_y = window_x1, window_y1
|
||||||
x = window_x + button_x
|
x = window_x + button_x
|
||||||
y = window_y + button_y
|
y = window_y + button_y
|
||||||
|
|
||||||
|
|
|
@ -69,8 +69,8 @@ class HistoryWindow:
|
||||||
self.calendar = xml.get_widget('calendar')
|
self.calendar = xml.get_widget('calendar')
|
||||||
scrolledwindow = xml.get_widget('scrolledwindow')
|
scrolledwindow = xml.get_widget('scrolledwindow')
|
||||||
self.history_textview = conversation_textview.ConversationTextview(account)
|
self.history_textview = conversation_textview.ConversationTextview(account)
|
||||||
scrolledwindow.add(self.history_textview)
|
scrolledwindow.add(self.history_textview.tv)
|
||||||
self.history_buffer = self.history_textview.get_buffer()
|
self.history_buffer = self.history_textview.tv.get_buffer()
|
||||||
self.history_buffer.create_tag('highlight', background = 'yellow')
|
self.history_buffer.create_tag('highlight', background = 'yellow')
|
||||||
self.query_entry = xml.get_widget('query_entry')
|
self.query_entry = xml.get_widget('query_entry')
|
||||||
self.search_button = xml.get_widget('search_button')
|
self.search_button = xml.get_widget('search_button')
|
||||||
|
@ -142,6 +142,7 @@ class HistoryWindow:
|
||||||
# if user destroys the window, and we have a generator filling mark days
|
# if user destroys the window, and we have a generator filling mark days
|
||||||
# stop him!
|
# stop him!
|
||||||
gobject.source_remove(self.mark_days_idle_call_id)
|
gobject.source_remove(self.mark_days_idle_call_id)
|
||||||
|
self.history_textview.del_handlers()
|
||||||
del gajim.interface.instances['logs'][self.jid]
|
del gajim.interface.instances['logs'][self.jid]
|
||||||
|
|
||||||
def on_close_button_clicked(self, widget):
|
def on_close_button_clicked(self, widget):
|
||||||
|
@ -391,4 +392,4 @@ class HistoryWindow:
|
||||||
|
|
||||||
match_start_mark = self.history_buffer.create_mark('match_start',
|
match_start_mark = self.history_buffer.create_mark('match_start',
|
||||||
match_start_iter, True)
|
match_start_iter, True)
|
||||||
self.history_textview.scroll_to_mark(match_start_mark, 0, True)
|
self.history_textview.tv.scroll_to_mark(match_start_mark, 0, True)
|
||||||
|
|
|
@ -50,6 +50,9 @@ class MessageTextView(gtk.TextView):
|
||||||
self.set_pixels_above_lines(2)
|
self.set_pixels_above_lines(2)
|
||||||
self.set_pixels_below_lines(2)
|
self.set_pixels_below_lines(2)
|
||||||
|
|
||||||
|
def destroy(self):
|
||||||
|
import gc
|
||||||
|
gobject.idle_add(lambda:gc.collect())
|
||||||
if gobject.pygtk_version < (2, 8, 0):
|
if gobject.pygtk_version < (2, 8, 0):
|
||||||
gobject.type_register(MessageTextView)
|
gobject.type_register(MessageTextView)
|
||||||
|
|
||||||
|
|
|
@ -55,11 +55,19 @@ class MessageWindow:
|
||||||
self.account = acct
|
self.account = acct
|
||||||
# If None, the window is not tied to any specific type
|
# If None, the window is not tied to any specific type
|
||||||
self.type = type
|
self.type = type
|
||||||
|
# dict { handler id: widget}. Keeps callbacks, which
|
||||||
|
# lead to cylcular references
|
||||||
|
self.handlers = {}
|
||||||
|
|
||||||
self.widget_name = 'message_window'
|
self.widget_name = 'message_window'
|
||||||
self.xml = gtk.glade.XML(GTKGUI_GLADE, self.widget_name, APP)
|
self.xml = gtk.glade.XML(GTKGUI_GLADE, self.widget_name, APP)
|
||||||
self.xml.signal_autoconnect(self)
|
|
||||||
self.window = self.xml.get_widget(self.widget_name)
|
self.window = self.xml.get_widget(self.widget_name)
|
||||||
|
id = self.window.connect('delete-event', self._on_window_delete)
|
||||||
|
self.handlers[id] = self.window
|
||||||
|
id = self.window.connect('destroy', self._on_window_destroy)
|
||||||
|
self.handlers[id] = self.window
|
||||||
|
id = self.window.connect('focus-in-event', self._on_window_focus)
|
||||||
|
self.handlers[id] = self.window
|
||||||
|
|
||||||
# gtk+ doesn't make use of the motion notify on gtkwindow by default
|
# gtk+ doesn't make use of the motion notify on gtkwindow by default
|
||||||
# so this line adds that
|
# so this line adds that
|
||||||
|
@ -67,10 +75,12 @@ class MessageWindow:
|
||||||
self.alignment = self.xml.get_widget('alignment')
|
self.alignment = self.xml.get_widget('alignment')
|
||||||
|
|
||||||
self.notebook = self.xml.get_widget('notebook')
|
self.notebook = self.xml.get_widget('notebook')
|
||||||
self.notebook.connect('switch-page',
|
id = self.notebook.connect('switch-page',
|
||||||
self._on_notebook_switch_page)
|
self._on_notebook_switch_page)
|
||||||
self.notebook.connect('key-press-event',
|
self.handlers[id] = self.notebook
|
||||||
|
id = self.notebook.connect('key-press-event',
|
||||||
self._on_notebook_key_press)
|
self._on_notebook_key_press)
|
||||||
|
self.handlers[id] = self.notebook
|
||||||
|
|
||||||
# Remove the glade pages
|
# Remove the glade pages
|
||||||
while self.notebook.get_n_pages():
|
while self.notebook.get_n_pages():
|
||||||
|
@ -96,6 +106,8 @@ class MessageWindow:
|
||||||
# set up DnD
|
# set up DnD
|
||||||
self.hid = self.notebook.connect('drag_data_received',
|
self.hid = self.notebook.connect('drag_data_received',
|
||||||
self.on_tab_label_drag_data_received_cb)
|
self.on_tab_label_drag_data_received_cb)
|
||||||
|
self.handlers[self.hid] = self.notebook
|
||||||
|
|
||||||
self.notebook.drag_dest_set(gtk.DEST_DEFAULT_ALL, self.DND_TARGETS,
|
self.notebook.drag_dest_set(gtk.DEST_DEFAULT_ALL, self.DND_TARGETS,
|
||||||
gtk.gdk.ACTION_MOVE)
|
gtk.gdk.ACTION_MOVE)
|
||||||
|
|
||||||
|
@ -133,6 +145,11 @@ class MessageWindow:
|
||||||
for ctrl in self.controls():
|
for ctrl in self.controls():
|
||||||
ctrl.shutdown()
|
ctrl.shutdown()
|
||||||
self._controls.clear()
|
self._controls.clear()
|
||||||
|
for i in self.handlers.keys():
|
||||||
|
if self.handlers[i].handler_is_connected(i):
|
||||||
|
self.handlers[i].disconnect(i)
|
||||||
|
del self.handlers[i]
|
||||||
|
del self.handlers
|
||||||
|
|
||||||
def new_tab(self, control):
|
def new_tab(self, control):
|
||||||
if not self._controls.has_key(control.account):
|
if not self._controls.has_key(control.account):
|
||||||
|
@ -499,6 +516,7 @@ class MessageWindow:
|
||||||
tab_label = self.notebook.get_tab_label(child)
|
tab_label = self.notebook.get_tab_label(child)
|
||||||
tab_label.dnd_handler = tab_label.connect('drag_data_get',
|
tab_label.dnd_handler = tab_label.connect('drag_data_get',
|
||||||
self.on_tab_label_drag_data_get_cb)
|
self.on_tab_label_drag_data_get_cb)
|
||||||
|
self.handlers[tab_label.dnd_handler] = tab_label
|
||||||
tab_label.drag_source_set(gtk.gdk.BUTTON1_MASK, self.DND_TARGETS,
|
tab_label.drag_source_set(gtk.gdk.BUTTON1_MASK, self.DND_TARGETS,
|
||||||
gtk.gdk.ACTION_MOVE)
|
gtk.gdk.ACTION_MOVE)
|
||||||
tab_label.page_num = self.notebook.page_num(child)
|
tab_label.page_num = self.notebook.page_num(child)
|
||||||
|
|
Loading…
Reference in New Issue