diff --git a/src/chat_control.py b/src/chat_control.py
index 881b286cf..2ab0b5191 100644
--- a/src/chat_control.py
+++ b/src/chat_control.py
@@ -101,36 +101,43 @@ class ChatControlBase(MessageControl):
def __init__(self, type_id, parent_win, widget_name, display_names, contact, acct, resource = None):
MessageControl.__init__(self, type_id, parent_win, widget_name,
display_names, contact, acct, resource = resource);
-
- # FIXME: XHTML-IM
- for w in ('bold_togglebutton', 'italic_togglebutton',
- 'underline_togglebutton'):
- self.xml.get_widget(w).set_no_show_all(True)
-
- self.widget.connect('key_press_event', self._on_keypress_event)
-
+ # when/if we do XHTML we will but formatting buttons back
+ widget = self.xml.get_widget('emoticons_button')
+ id = widget.connect('clicked', self.on_emoticons_button_clicked)
+ self.handlers[id] = widget
+
+ id = self.widget.connect('key_press_event', self._on_keypress_event)
+ self.handlers[id] = self.widget
+
# Create textviews and connect signals
self.conv_textview = ConversationTextview(self.account)
self.conv_textview.show_all()
self.conv_scrolledwindow = self.xml.get_widget(
'conversation_scrolledwindow')
self.conv_scrolledwindow.add(self.conv_textview)
- self.conv_scrolledwindow.get_vadjustment().connect('value-changed',
+ widget = self.conv_scrolledwindow.get_vadjustment()
+ id = widget.connect('value-changed',
self.on_conversation_vadjustment_value_changed)
+ self.handlers[id] = widget
# add MessageTextView to UI and connect signals
self.msg_scrolledwindow = self.xml.get_widget('message_scrolledwindow')
self.msg_textview = MessageTextView()
- self.msg_textview.connect('mykeypress',
+ id = self.msg_textview.connect('mykeypress',
self._on_message_textview_mykeypress_event)
+ self.handlers[id] = self.msg_textview
self.msg_scrolledwindow.add(self.msg_textview)
- self.msg_textview.connect('key_press_event',
+ id = self.msg_textview.connect('key_press_event',
self._on_message_textview_key_press_event)
- self.msg_textview.connect('size-request', self.size_request)
+ self.handlers[id] = self.msg_textview
+ id = self.msg_textview.connect('size-request', self.size_request)
+ self.handlers[id] = self.msg_textview
self.update_font()
# Hook up send button
- self.xml.get_widget('send_button').connect('clicked',
+ widget = self.xml.get_widget('send_button')
+ id = widget.connect('clicked',
self._on_send_button_clicked)
+ self.handlers[id] = widget
# the following vars are used to keep history of user's messages
self.sent_history = []
@@ -207,12 +214,14 @@ class ChatControlBase(MessageControl):
def disconnect_style_event(self, widget):
if self.style_event_id:
widget.disconnect(self.style_event_id)
- self.style_event_id = 0
+ del self.handlers[self.style_event_id]
+ self.style_event_id = 0
def connect_style_event(self, widget, set_fg = False, set_bg = False):
self.disconnect_style_event(widget)
self.style_event_id = widget.connect('style-set',
self._on_style_set_event, set_fg, set_bg)
+ self.handlers[self.style_event_id] = widget
def _on_style_set_event(self, widget, style, *opts):
'''set style of widget from style class *.Frame.Eventbox
@@ -478,11 +487,8 @@ class ChatControlBase(MessageControl):
self.msg_textview.grab_focus()
def on_emoticons_button_clicked(self, widget):
'''popup emoticons menu'''
- #FIXME: BUG http://bugs.gnome.org/show_bug.cgi?id=316786
- self.button_clicked = widget
gajim.interface.emoticon_menuitem_clicked = self.append_emoticon
- gajim.interface.emoticons_menu.popup(None, None,
- self.position_menu_under_button, 1, 0)
+ gajim.interface.popup_emoticons_under_button(widget, self.parent_win)
def on_actions_button_clicked(self, widget):
'''popup action menu'''
@@ -491,7 +497,7 @@ class ChatControlBase(MessageControl):
menu = self.prepare_context_menu()
menu.show_all()
- menu.popup(None, None, self.position_menu_under_button, 1, 0)
+ gtkgui_helpers.popup_emoticons_under_button(menu, widget, self.parent_win)
def update_font(self):
font = pango.FontDescription(gajim.config.get('conversation_font'))
@@ -687,13 +693,21 @@ class ChatControl(ChatControlBase):
def __init__(self, parent_win, contact, acct, resource = None):
ChatControlBase.__init__(self, self.TYPE_ID, parent_win, 'chat_child_vbox',
(_('Chat'), _('Chats')), contact, acct, resource)
+
+ # for muc use:
+ # widget = self.xml.get_widget('muc_window_actions_button')
+ widget = self.xml.get_widget('message_window_actions_button')
+ id = widget.connect('clicked', self.on_actions_button_clicked)
+ self.handlers[id] = widget
+
self.hide_chat_buttons_always = gajim.config.get('always_hide_chat_buttons')
self.chat_buttons_set_visible(self.hide_chat_buttons_always)
self.widget_set_visible(self.xml.get_widget('banner_eventbox'), gajim.config.get('hide_chat_banner'))
# Initialize drag-n-drop
self.TARGET_TYPE_URI_LIST = 80
self.dnd_list = [ ( 'text/uri-list', 0, self.TARGET_TYPE_URI_LIST ) ]
- self.widget.connect('drag_data_received', self._on_drag_data_received)
+ id = self.widget.connect('drag_data_received', self._on_drag_data_received)
+ self.handlers[id] = self.widget
self.widget.drag_dest_set(gtk.DEST_DEFAULT_MOTION |
gtk.DEST_DEFAULT_HIGHLIGHT |
gtk.DEST_DEFAULT_DROP,
@@ -710,18 +724,29 @@ class ChatControl(ChatControlBase):
self._schedule_activity_timers()
# Hook up signals
- self.parent_win.window.connect('motion-notify-event',
+ id = self.parent_win.window.connect('motion-notify-event',
self._on_window_motion_notify)
+ self.handlers[id] = self.parent_win.window
message_tv_buffer = self.msg_textview.get_buffer()
- message_tv_buffer.connect('changed', self._on_message_tv_buffer_changed)
-
- self.xml.get_widget('banner_eventbox').connect('button-press-event',
+ id = message_tv_buffer.connect('changed', self._on_message_tv_buffer_changed)
+ 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
- xm = gtk.glade.XML(GTKGUI_GLADE, 'avatar_eventbox', APP)
- xm.signal_autoconnect(self)
- xm = gtk.glade.XML(GTKGUI_GLADE, 'gpg_togglebutton', APP)
- xm.signal_autoconnect(self)
+ widget = self.xml.get_widget('avatar_eventbox')
+ id = widget.connect('enter-notify-event', self.on_avatar_eventbox_enter_notify_event)
+ self.handlers[id] = widget
+
+ widget = self.xml.get_widget('avatar_eventbox')
+ id = widget.connect('leave-notify-event', self.on_avatar_eventbox_leave_notify_event)
+ self.handlers[id] = widget
+
+ widget = self.xml.get_widget('gpg_togglebutton')
+ id = widget.connect('clicked', self.on_toggle_gpg_togglebutton)
+ self.handlers[id] = widget
if self.contact.jid in gajim.encrypted_chats[self.account]:
self.xml.get_widget('gpg_togglebutton').set_active(True)
@@ -1138,6 +1163,7 @@ class ChatControl(ChatControlBase):
add_to_roster_menuitem = xml.get_widget('add_to_roster_menuitem')
send_file_menuitem = xml.get_widget('send_file_menuitem')
compact_view_menuitem = xml.get_widget('compact_view_menuitem')
+ information_menuitem = xml.get_widget('information_menuitem')
contact = self.parent_win.get_active_contact()
jid = contact.jid
@@ -1172,8 +1198,19 @@ class ChatControl(ChatControlBase):
# connect signals
- xml.signal_autoconnect(self)
-
+ history_menuitem.connect('activate',
+ self._on_history_menuitem_activate)
+ send_file_menuitem.connect('activate',
+ self._on_send_file_menuitem_activate)
+ compact_view_menuitem.connect('activate',
+ self._on_compact_view_menuitem_activate)
+ add_to_roster_menuitem.connect('activate',
+ self._on_add_to_roster_menuitem_activate)
+ toggle_gpg_menuitem.connect('activate',
+ self._on_toggle_gpg_menuitem_activate)
+ information_menuitem.connect('activate',
+ self._on_contact_information_menuitem_activate)
+ menu.connect('selection-done', gtkgui_helpers.destroy_widget)
return menu
def send_chatstate(self, state, contact = None):
@@ -1233,8 +1270,8 @@ class ChatControl(ChatControlBase):
# in JEP22, when we already sent stop composing
# notification on paused, don't resend it
if contact.composing_jep == 'JEP-0022' and \
- contact.our_chatstate in ('paused', 'active', 'inactive') and \
- state is not 'composing': # not composing == in (active, inactive, gone)
+ contact.our_chatstate in ('paused', 'active', 'inactive') and \
+ state is not 'composing': # not composing == in (active, inactive, gone)
contact.our_chatstate = 'active'
self.reset_kbd_mouse_timeout_vars()
return
@@ -1271,6 +1308,12 @@ class ChatControl(ChatControlBase):
if gajim.interface.systray_enabled and self.nb_unread > 0:
gajim.interface.systray.remove_jid(self.contact.jid, self.account,
self.type_id)
+ # remove all register handlers on wigets, created by self.xml
+ # to prevent circular references among objects
+ for i in self.handlers.keys():
+ self.handlers[i].disconnect(i)
+ del self.handlers[i]
+
def allow_shutdown(self):
if time.time() - gajim.last_message_time[self.account]\
diff --git a/src/gajim.py b/src/gajim.py
index 8f25bff34..aaecaa5c8 100755
--- a/src/gajim.py
+++ b/src/gajim.py
@@ -1504,13 +1504,23 @@ class Interface:
def on_launch_browser_mailer(self, widget, url, kind):
helpers.launch_browser_mailer(kind, url)
+ def popup_emoticons_under_button(self, button, parent_win):
+ ''' pops emoticons menu under button, located in parent_win'''
+ gtkgui_helpers.popup_emoticons_under_button(self.emoticons_menu,
+ button, parent_win)
+
def prepare_emoticons_menu(self):
menu = gtk.Menu()
-
def emoticon_clicked(w, str_):
if self.emoticon_menuitem_clicked:
self.emoticon_menuitem_clicked(str_)
-
+ # don't keep reference to CB of object
+ # this will prevent making it uncollectable
+ self.emoticon_menuitem_clicked = None
+ def selection_done(widget):
+ # remove reference to CB of object, which will
+ # make it uncollectable
+ self.emoticon_menuitem_clicked = None
counter = 0
# Calculate the side lenght of the popup to make it a square
size = int(round(math.sqrt(len(gajim.interface.emoticons_images))))
@@ -1527,6 +1537,7 @@ class Interface:
menu.attach(item, counter % size, counter % size + 1,
counter / size, counter / size + 1)
counter += 1
+ menu.connect('selection-done', selection_done)
menu.show_all()
return menu
diff --git a/src/groupchat_control.py b/src/groupchat_control.py
index 80127a217..c1b65f44d 100644
--- a/src/groupchat_control.py
+++ b/src/groupchat_control.py
@@ -58,6 +58,47 @@ C_NICK, # contact nickame or group name
C_TEXT, # text shown in the cellrenderer
C_AVATAR, # avatar of the contact
) = range(5)
+
+def set_renderer_color(treeview, renderer, set_background = True):
+ '''set style for group row, using PRELIGHT system color'''
+ if set_background:
+ bgcolor = treeview.style.bg[gtk.STATE_PRELIGHT]
+ renderer.set_property('cell-background-gdk', bgcolor)
+ else:
+ fgcolor = treeview.style.fg[gtk.STATE_PRELIGHT]
+ renderer.set_property('foreground-gdk', fgcolor)
+
+def tree_cell_data_func(column, renderer, model, iter, tv=None):
+ # cell data func is global, because we don't want it to keep
+ # reference to GroupchatControl instance (self)
+ theme = gajim.config.get('roster_theme')
+ if model.iter_parent(iter):
+ bgcolor = gajim.config.get_per('themes', theme, 'contactbgcolor')
+ if bgcolor:
+ renderer.set_property('cell-background', bgcolor)
+ else:
+ renderer.set_property('cell-background', None)
+ if isinstance(renderer, gtk.CellRendererText):
+ # foreground property is only with CellRendererText
+ color = gajim.config.get_per('themes', theme,
+ 'contacttextcolor')
+ if color:
+ renderer.set_property('foreground', color)
+ else:
+ renderer.set_property('foreground', None)
+ else: # it is root (eg. group)
+ bgcolor = gajim.config.get_per('themes', theme, 'groupbgcolor')
+ if bgcolor:
+ renderer.set_property('cell-background', bgcolor)
+ else:
+ set_renderer_color(tv, renderer)
+ if isinstance(renderer, gtk.CellRendererText):
+ # foreground property is only with CellRendererText
+ color = gajim.config.get_per('themes', theme, 'grouptextcolor')
+ if color:
+ renderer.set_property('foreground', color)
+ else:
+ set_renderer_color(tv, renderer, False)
class PrivateChatControl(ChatControl):
TYPE_ID = message_control.TYPE_PM
@@ -98,6 +139,38 @@ class GroupchatControl(ChatControlBase):
'muc_child_vbox', (_('Group Chat'), _('Group Chats')),
contact, acct);
+ widget = self.xml.get_widget('muc_window_actions_button')
+ id = widget.connect('clicked', self.on_actions_button_clicked)
+ self.handlers[id] = widget
+
+ widget = self.xml.get_widget('list_treeview')
+ id = widget.connect('row_expanded', self.on_list_treeview_row_expanded)
+ self.handlers[id] = widget
+
+ id = widget.connect('row_collapsed',
+ self.on_list_treeview_row_collapsed)
+ self.handlers[id] = widget
+
+ id = widget.connect('row_activated',
+ self.on_list_treeview_row_activated)
+ self.handlers[id] = widget
+
+ id = widget.connect('button_press_event',
+ self.on_list_treeview_button_press_event)
+ self.handlers[id] = widget
+
+ id = widget.connect('key_press_event',
+ self.on_list_treeview_key_press_event)
+ self.handlers[id] = widget
+
+ id = widget.connect('motion_notify_event',
+ self.on_list_treeview_motion_notify_event)
+ self.handlers[id] = widget
+
+ id = widget.connect('leave_notify_event',
+ self.on_list_treeview_leave_notify_event)
+ self.handlers[id] = widget
+
self.room_jid = self.contact.jid
self.nick = contact.name
self.name = self.room_jid.split('@')[0]
@@ -132,12 +205,37 @@ class GroupchatControl(ChatControlBase):
# connect the menuitems to their respective functions
xm = gtk.glade.XML(GTKGUI_GLADE, 'gc_control_popup_menu', APP)
- xm.signal_autoconnect(self)
+
+ widget = xm.get_widget('bookmark_room_menuitem')
+ id = widget.connect('activate', self._on_bookmark_room_menuitem_activate)
+ self.handlers[id] = widget
+
+ widget = xm.get_widget('change_nick_menuitem')
+ id = widget.connect('activate', self._on_change_nick_menuitem_activate)
+ self.handlers[id] = widget
+
+ widget = xm.get_widget('configure_room_menuitem')
+ id = widget.connect('activate', self._on_configure_room_menuitem_activate)
+ self.handlers[id] = widget
+
+ widget = xm.get_widget('change_subject_menuitem')
+ id = widget.connect('activate', self._on_change_subject_menuitem_activate)
+ self.handlers[id] = widget
+
+ widget = xm.get_widget('compact_view_menuitem')
+ id = widget.connect('activate', self._on_compact_view_menuitem_activate)
+ self.handlers[id] = widget
+
+ widget = xm.get_widget('history_menuitem')
+ id = widget.connect('activate', self._on_history_menuitem_activate)
+ self.handlers[id] = widget
+
self.gc_popup_menu = xm.get_widget('gc_control_popup_menu')
self.name_label = self.xml.get_widget('banner_name_label')
- self.parent_win.window.connect('focus-in-event',
+ id = self.parent_win.window.connect('focus-in-event',
self._on_window_focus_in_event)
+ self.handlers[id] = self.parent_win.window
# set the position of the current hpaned
self.hpaned_position = gajim.config.get('gc-hpaned-position')
@@ -145,15 +243,18 @@ class GroupchatControl(ChatControlBase):
self.hpaned.set_position(self.hpaned_position)
list_treeview = self.list_treeview = self.xml.get_widget('list_treeview')
- list_treeview.get_selection().connect('changed',
- self.on_list_treeview_selection_changed)
- list_treeview.connect('style-set', self.on_list_treeview_style_set)
+ selection = list_treeview.get_selection()
+ id = selection.connect('changed',
+ self.on_list_treeview_selection_changed)
+ self.handlers[id] = selection
+ id = list_treeview.connect('style-set', self.on_list_treeview_style_set)
+ self.handlers[id] = list_treeview
# we want to know when the the widget resizes, because that is
# an indication that the hpaned has moved...
# FIXME: Find a better indicator that the hpaned has moved.
- self.list_treeview.connect('size-allocate',
+ id = self.list_treeview.connect('size-allocate',
self.on_treeview_size_allocate)
-
+ self.handlers[id] = self.list_treeview
#status_image, type, nickname, shown_nick
store = gtk.TreeStore(gtk.Image, str, str, str, gtk.gdk.Pixbuf)
store.set_sort_column_id(C_TEXT, gtk.SORT_ASCENDING)
@@ -168,18 +269,20 @@ class GroupchatControl(ChatControlBase):
renderer_pixbuf = gtk.CellRendererPixbuf() # avatar image
column.pack_start(renderer_pixbuf, expand = False)
column.add_attribute(renderer_pixbuf, 'pixbuf', C_AVATAR)
- column.set_cell_data_func(renderer_pixbuf, self.avatar_cell_data_func,
- None)
+ column.set_cell_data_func(renderer_pixbuf, tree_cell_data_func,
+ self.list_treeview)
+ renderer_pixbuf.set_property('xalign', 1) # align pixbuf to the right
renderer_image = cell_renderer_image.CellRendererImage(0, 0) # status img
column.pack_start(renderer_image, expand = False)
column.add_attribute(renderer_image, 'image', C_IMG)
- column.set_cell_data_func(renderer_image, self.tree_cell_data_func, None)
+ column.set_cell_data_func(renderer_image, tree_cell_data_func,
+ self.list_treeview)
renderer_text = gtk.CellRendererText() # nickname
column.pack_start(renderer_text, expand = True)
column.add_attribute(renderer_text, 'markup', C_TEXT)
- column.set_cell_data_func(renderer_text, self.tree_cell_data_func, None)
+ column.set_cell_data_func(renderer_text, tree_cell_data_func, self.list_treeview)
self.list_treeview.append_column(column)
@@ -208,49 +311,6 @@ class GroupchatControl(ChatControlBase):
if self.parent_win.get_active_jid() == self.room_jid:
self.allow_focus_out_line = True
- def set_renderer_color(self, renderer, set_background = True):
- '''set style for group row, using PRELIGHT system color'''
- if set_background:
- bgcolor = self.list_treeview.style.bg[gtk.STATE_PRELIGHT]
- renderer.set_property('cell-background-gdk', bgcolor)
- else:
- fgcolor = self.list_treeview.style.fg[gtk.STATE_PRELIGHT]
- renderer.set_property('foreground-gdk', fgcolor)
-
- def tree_cell_data_func(self, column, renderer, model, iter, data=None):
- theme = gajim.config.get('roster_theme')
- if model.iter_parent(iter):
- bgcolor = gajim.config.get_per('themes', theme, 'contactbgcolor')
- if bgcolor:
- renderer.set_property('cell-background', bgcolor)
- else:
- renderer.set_property('cell-background', None)
- if isinstance(renderer, gtk.CellRendererText):
- # foreground property is only with CellRendererText
- color = gajim.config.get_per('themes', theme,
- 'contacttextcolor')
- if color:
- renderer.set_property('foreground', color)
- else:
- renderer.set_property('foreground', None)
- else: # it is root (eg. group)
- bgcolor = gajim.config.get_per('themes', theme, 'groupbgcolor')
- if bgcolor:
- renderer.set_property('cell-background', bgcolor)
- else:
- self.set_renderer_color(renderer)
- if isinstance(renderer, gtk.CellRendererText):
- # foreground property is only with CellRendererText
- color = gajim.config.get_per('themes', theme, 'grouptextcolor')
- if color:
- renderer.set_property('foreground', color)
- else:
- self.set_renderer_color(renderer, False)
-
- def avatar_cell_data_func(self, column, renderer, model, iter, data=None):
- self.tree_cell_data_func(column, renderer, model, iter, data)
- renderer.set_property('xalign', 1) # align pixbuf to the right
-
def on_treeview_size_allocate(self, widget, allocation):
'''The MUC treeview has resized. Move the hpaned in all tabs to match'''
self.hpaned_position = self.hpaned.get_position()
@@ -1116,6 +1176,11 @@ class GroupchatControl(ChatControlBase):
del gajim.gc_connected[self.account][self.room_jid]
# Save hpaned position
gajim.config.set('gc-hpaned-position', self.hpaned_position)
+ # remove all register handlers on wigets, created by self.xml
+ # to prevent circular references among objects
+ for i in self.handlers.keys():
+ self.handlers[i].disconnect(i)
+ del self.handlers[i]
def allow_shutdown(self):
retval = True
@@ -1354,7 +1419,8 @@ class GroupchatControl(ChatControlBase):
(user_affiliation == 'member' and target_affiliation in ('admin', 'owner')) or \
(user_affiliation == 'none' and target_affiliation != 'none'):
item.set_sensitive(False)
- item.connect('activate', self.kick, nick)
+ id = item.connect('activate', self.kick, nick)
+ self.handlers[id] = item
item = xml.get_widget('voice_checkmenuitem')
item.set_active(target_role != 'visitor')
@@ -1363,54 +1429,67 @@ class GroupchatControl(ChatControlBase):
(user_affiliation=='member' and target_affiliation!='none') or \
target_affiliation in ('admin', 'owner'):
item.set_sensitive(False)
- item.connect('activate', self.on_voice_checkmenuitem_activate, nick)
+ id = item.connect('activate', self.on_voice_checkmenuitem_activate,
+ nick)
+ self.handlers[id] = item
item = xml.get_widget('moderator_checkmenuitem')
item.set_active(target_role == 'moderator')
if not user_affiliation in ('admin', 'owner') or \
target_affiliation in ('admin', 'owner'):
item.set_sensitive(False)
- item.connect('activate', self.on_moderator_checkmenuitem_activate, nick)
-
+ id = item.connect('activate', self.on_moderator_checkmenuitem_activate,
+ nick)
+ self.handlers[id] = item
+
item = xml.get_widget('ban_menuitem')
if not user_affiliation in ('admin', 'owner') or \
(target_affiliation in ('admin', 'owner') and\
user_affiliation != 'owner'):
item.set_sensitive(False)
- item.connect('activate', self.ban, jid)
+ id = item.connect('activate', self.ban, jid)
+ self.handlers[id] = item
item = xml.get_widget('member_checkmenuitem')
item.set_active(target_affiliation != 'none')
if not user_affiliation in ('admin', 'owner') or \
(user_affiliation != 'owner' and target_affiliation in ('admin','owner')):
item.set_sensitive(False)
- item.connect('activate', self.on_member_checkmenuitem_activate, jid)
-
+ id = item.connect('activate', self.on_member_checkmenuitem_activate,
+ jid)
+ self.handlers[id] = item
+
item = xml.get_widget('admin_checkmenuitem')
item.set_active(target_affiliation in ('admin', 'owner'))
if not user_affiliation == 'owner':
item.set_sensitive(False)
- item.connect('activate', self.on_admin_checkmenuitem_activate, jid)
+ id = item.connect('activate', self.on_admin_checkmenuitem_activate, jid)
+ self.handlers[id] = item
item = xml.get_widget('owner_checkmenuitem')
item.set_active(target_affiliation == 'owner')
if not user_affiliation == 'owner':
item.set_sensitive(False)
- item.connect('activate', self.on_owner_checkmenuitem_activate, jid)
+ id = item.connect('activate', self.on_owner_checkmenuitem_activate, jid)
+ self.handlers[id] = item
item = xml.get_widget('information_menuitem')
- item.connect('activate', self.on_info, nick)
+ id = item.connect('activate', self.on_info, nick)
+ self.handlers[id] = item
item = xml.get_widget('history_menuitem')
- item.connect('activate', self.on_history, nick)
+ id = item.connect('activate', self.on_history, nick)
+ self.handlers[id] = item
item = xml.get_widget('add_to_roster_menuitem')
if not jid:
item.set_sensitive(False)
- item.connect('activate', self.on_add_to_roster, jid)
+ id = item.connect('activate', self.on_add_to_roster, jid)
+ self.handlers[id] = item
item = xml.get_widget('send_private_message_menuitem')
- item.connect('activate', self.on_send_pm, model, iter)
+ id = item.connect('activate', self.on_send_pm, model, iter)
+ self.handlers[id] = item
# show the popup now!
menu = xml.get_widget('gc_occupants_menu')
diff --git a/src/gtkgui.glade b/src/gtkgui.glade
index 26288f9ca..c77af03a1 100644
--- a/src/gtkgui.glade
+++ b/src/gtkgui.glade
@@ -3817,7 +3817,6 @@ Per type
True
False
True
-
0
@@ -15233,7 +15232,6 @@ Messages
Click to see past conversation in this room
_History
True
-
@@ -15253,7 +15251,6 @@ Messages
-
-
-
- Bold
- True
- GTK_RELIEF_NONE
- False
- False
- False
-
-
-
- True
- gtk-bold
- 3
- 0.5
- 0.5
- 0
- 0
-
-
-
-
- 0
- False
- False
-
-
-
-
-
- Italic
- True
- GTK_RELIEF_NONE
- False
- False
- False
-
-
-
- True
- gtk-italic
- 3
- 0.5
- 0.5
- 0
- 0
-
-
-
-
- 0
- False
- False
-
-
-
-
-
- Underline
- True
- GTK_RELIEF_NONE
- False
- False
- False
-
-
-
- True
- gtk-underline
- 3
- 0.5
- 0.5
- 0
- 0
-
-
-
-
- 0
- False
- False
-
-
0
@@ -18407,7 +18311,6 @@ Status message
True
GTK_RELIEF_NORMAL
True
-
@@ -18457,12 +18360,11 @@ Status message
-
+
True
True
GTK_RELIEF_NORMAL
True
-
@@ -18666,7 +18568,6 @@ Status message
True
False
False
-
@@ -18902,13 +18803,6 @@ topic
False
False
False
-
-
-
-
-
-
-
@@ -18933,103 +18827,7 @@ topic
0
-
- False
- 0
-
-
-
-
-
-
-
- Bold
- True
- GTK_RELIEF_NONE
- False
- False
- False
-
-
-
- True
- gtk-bold
- 3
- 0.5
- 0.5
- 0
- 0
-
-
-
-
- 0
- False
- False
-
-
-
-
-
- Italic
- True
- GTK_RELIEF_NONE
- False
- False
- False
-
-
-
- True
- gtk-italic
- 3
- 0.5
- 0.5
- 0
- 0
-
-
-
-
- 0
- False
- False
-
-
-
-
-
- Underline
- True
- GTK_RELIEF_NONE
- False
- False
- False
-
-
-
- True
- gtk-underline
- 3
- 0.5
- 0.5
- 0
- 0
-
-
-
-
- 0
- False
- False
-
-
-
-
- 0
- True
- True
-
+
@@ -19095,12 +18893,11 @@ topic
-
+
True
True
GTK_RELIEF_NORMAL
True
-
diff --git a/src/gtkgui_helpers.py b/src/gtkgui_helpers.py
index 8d4a1c681..4eb81e31f 100644
--- a/src/gtkgui_helpers.py
+++ b/src/gtkgui_helpers.py
@@ -45,6 +45,34 @@ from common import helpers
screen_w = gtk.gdk.screen_width()
screen_h = gtk.gdk.screen_height()
+def popup_emoticons_under_button(menu, button, parent_win):
+ ''' pops emoticons menu under button, which is in parent_win'''
+ def position_menu_under_button(menu):
+ # inline function, which will not keep refs, when used as CB
+ button_x, button_y = button.allocation.x, button.allocation.y
+
+ # now convert them to X11-relative
+ window_x, window_y = parent_win.get_origin()
+ x = window_x + button_x
+ y = window_y + button_y
+
+ menu_width, menu_height = menu.size_request()
+
+ ## should we pop down or up?
+ if (y + button.allocation.height + menu_height
+ < gtk.gdk.screen_height()):
+ # now move the menu below the button
+ y += button.allocation.height
+ else:
+ # now move the menu above the button
+ y -= menu_height
+
+ # push_in is True so all the menuitems are always inside screen
+ push_in = True
+ return (x, y, push_in)
+
+ menu.popup(None, None, position_menu_under_button, 1, 0)
+
def get_theme_font_for_option(theme, option):
'''return string description of the font, stored in
theme preferences'''
diff --git a/src/message_control.py b/src/message_control.py
index daf09e862..1d69c0ae1 100644
--- a/src/message_control.py
+++ b/src/message_control.py
@@ -36,6 +36,9 @@ class MessageControl:
def __init__(self, type_id, parent_win, widget_name, display_names, contact, account, resource = None):
'''The display_names argument is a two element tuple containing the desired
display name (pretty string) for the control in both singular and plural form'''
+ # dict { cb id : widget}
+ # keep all registered callbacks of widgets, created by self.xml
+ self.handlers = {}
self.type_id = type_id
self.parent_win = parent_win
self.widget_name = widget_name
@@ -51,8 +54,6 @@ class MessageControl:
self.xml = gtk.glade.XML(GTKGUI_GLADE, widget_name, APP)
self.widget = self.xml.get_widget(widget_name)
- # Autoconnect glade signals
- self.xml.signal_autoconnect(self)
def get_full_jid(self):
fjid = self.contact.jid
@@ -137,33 +138,3 @@ class MessageControl:
gajim.connections[self.account].send_message(jid, message, keyID,
type = type, chatstate = chatstate, msg_id = msg_id,
composing_jep = composing_jep, resource = self.resource)
-
- def position_menu_under_button(self, menu):
- #FIXME: BUG http://bugs.gnome.org/show_bug.cgi?id=316786
- # pass btn instance when this bug is over
- button = self.button_clicked
- # here I get the coordinates of the button relative to
- # window (self.window)
- button_x, button_y = button.allocation.x, button.allocation.y
-
- # now convert them to X11-relative
- window_x, window_y = self.parent_win.get_origin()
- x = window_x + button_x
- y = window_y + button_y
-
- menu_width, menu_height = menu.size_request()
-
- ## should we pop down or up?
- if (y + button.allocation.height + menu_height
- < gtk.gdk.screen_height()):
- # now move the menu below the button
- y += button.allocation.height
- else:
- # now move the menu above the button
- y -= menu_height
-
-
- # push_in is True so all the menuitems are always inside screen
- push_in = True
- return (x, y, push_in)
-
diff --git a/src/message_window.py b/src/message_window.py
index b693c80e9..c61dbe012 100644
--- a/src/message_window.py
+++ b/src/message_window.py
@@ -147,10 +147,12 @@ class MessageWindow:
# Add notebook page and connect up to the tab's close button
xml = gtk.glade.XML(GTKGUI_GLADE, 'chat_tab_ebox', APP)
tab_label_box = xml.get_widget('chat_tab_ebox')
- xml.signal_connect('on_close_button_clicked',
- self._on_close_button_clicked, control)
- xml.signal_connect('on_tab_eventbox_button_press_event',
- self.on_tab_eventbox_button_press_event, control.widget)
+ widget = xml.get_widget('tab_close_button')
+ id = widget.connect('clicked', self._on_close_button_clicked, control)
+ control.handlers[id] = widget
+
+ id = tab_label_box.connect('button-press-event', self.on_tab_eventbox_button_press_event, control.widget)
+ control.handlers[id] = tab_label_box
self.notebook.append_page(control.widget, tab_label_box)
self.setup_tab_dnd(control.widget)