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 Configure _Room True - @@ -15273,7 +15270,6 @@ Messages Change _Subject True - @@ -15293,7 +15289,6 @@ Messages Change _Nickname True - @@ -15313,7 +15308,6 @@ Messages _Bookmark This Room True - @@ -15334,7 +15328,6 @@ Messages _Compact View Alt+C True False - @@ -15347,7 +15340,6 @@ Messages Click to see past conversations with this contact _History True - @@ -15368,7 +15360,6 @@ Messages True gtk-dialog-info True - @@ -16770,7 +16761,7 @@ Maybe I'll refactor later - + True @@ -16811,21 +16802,21 @@ Maybe I'll refactor later - + - True + True _Discover Services... - True - - + True + + - True + True gtk-find - 1 - 0.5 - 0.5 - 0 - 0 + 1 + 0.5 + 0.5 + 0 + 0 @@ -18155,8 +18146,6 @@ Status message True False False - - @@ -18268,7 +18257,6 @@ Status message False False False - @@ -18301,90 +18289,6 @@ Status message True - - - - 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)