make sure ChatControl instances are destroyed

when chat tab is closed
1/2 fixes #1829
This commit is contained in:
Dimitur Kirov 2006-04-17 21:59:04 +00:00
parent 0b9868b82a
commit b6ca28f342
7 changed files with 286 additions and 355 deletions

View file

@ -101,13 +101,13 @@ class ChatControlBase(MessageControl):
def __init__(self, type_id, parent_win, widget_name, display_names, contact, acct, resource = None): def __init__(self, type_id, parent_win, widget_name, display_names, contact, acct, resource = None):
MessageControl.__init__(self, type_id, parent_win, widget_name, MessageControl.__init__(self, type_id, parent_win, widget_name,
display_names, contact, acct, resource = resource); display_names, contact, acct, resource = resource);
# 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
# FIXME: XHTML-IM id = self.widget.connect('key_press_event', self._on_keypress_event)
for w in ('bold_togglebutton', 'italic_togglebutton', self.handlers[id] = self.widget
'underline_togglebutton'):
self.xml.get_widget(w).set_no_show_all(True)
self.widget.connect('key_press_event', self._on_keypress_event)
# Create textviews and connect signals # Create textviews and connect signals
self.conv_textview = ConversationTextview(self.account) self.conv_textview = ConversationTextview(self.account)
@ -115,22 +115,29 @@ class ChatControlBase(MessageControl):
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)
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.on_conversation_vadjustment_value_changed)
self.handlers[id] = widget
# add MessageTextView to UI and connect signals # add MessageTextView to UI and connect signals
self.msg_scrolledwindow = self.xml.get_widget('message_scrolledwindow') self.msg_scrolledwindow = self.xml.get_widget('message_scrolledwindow')
self.msg_textview = MessageTextView() self.msg_textview = MessageTextView()
self.msg_textview.connect('mykeypress', id = self.msg_textview.connect('mykeypress',
self._on_message_textview_mykeypress_event) self._on_message_textview_mykeypress_event)
self.handlers[id] = self.msg_textview
self.msg_scrolledwindow.add(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._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() self.update_font()
# Hook up send button # 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._on_send_button_clicked)
self.handlers[id] = widget
# the following vars are used to keep history of user's messages # the following vars are used to keep history of user's messages
self.sent_history = [] self.sent_history = []
@ -207,12 +214,14 @@ class ChatControlBase(MessageControl):
def disconnect_style_event(self, widget): def disconnect_style_event(self, widget):
if self.style_event_id: if self.style_event_id:
widget.disconnect(self.style_event_id) widget.disconnect(self.style_event_id)
del self.handlers[self.style_event_id]
self.style_event_id = 0 self.style_event_id = 0
def connect_style_event(self, widget, set_fg = False, set_bg = False): def connect_style_event(self, widget, set_fg = False, set_bg = False):
self.disconnect_style_event(widget) self.disconnect_style_event(widget)
self.style_event_id = widget.connect('style-set', self.style_event_id = widget.connect('style-set',
self._on_style_set_event, set_fg, set_bg) 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): def _on_style_set_event(self, widget, style, *opts):
'''set style of widget from style class *.Frame.Eventbox '''set style of widget from style class *.Frame.Eventbox
@ -478,11 +487,8 @@ class ChatControlBase(MessageControl):
self.msg_textview.grab_focus() self.msg_textview.grab_focus()
def on_emoticons_button_clicked(self, widget): def on_emoticons_button_clicked(self, widget):
'''popup emoticons menu''' '''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.emoticon_menuitem_clicked = self.append_emoticon
gajim.interface.emoticons_menu.popup(None, None, gajim.interface.popup_emoticons_under_button(widget, self.parent_win)
self.position_menu_under_button, 1, 0)
def on_actions_button_clicked(self, widget): def on_actions_button_clicked(self, widget):
'''popup action menu''' '''popup action menu'''
@ -491,7 +497,7 @@ class ChatControlBase(MessageControl):
menu = self.prepare_context_menu() menu = self.prepare_context_menu()
menu.show_all() 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): def update_font(self):
font = pango.FontDescription(gajim.config.get('conversation_font')) font = pango.FontDescription(gajim.config.get('conversation_font'))
@ -687,13 +693,21 @@ class ChatControl(ChatControlBase):
def __init__(self, parent_win, contact, acct, resource = None): def __init__(self, parent_win, contact, acct, resource = None):
ChatControlBase.__init__(self, self.TYPE_ID, parent_win, 'chat_child_vbox', ChatControlBase.__init__(self, self.TYPE_ID, parent_win, 'chat_child_vbox',
(_('Chat'), _('Chats')), contact, acct, resource) (_('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.hide_chat_buttons_always = gajim.config.get('always_hide_chat_buttons')
self.chat_buttons_set_visible(self.hide_chat_buttons_always) 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')) self.widget_set_visible(self.xml.get_widget('banner_eventbox'), gajim.config.get('hide_chat_banner'))
# Initialize drag-n-drop # Initialize drag-n-drop
self.TARGET_TYPE_URI_LIST = 80 self.TARGET_TYPE_URI_LIST = 80
self.dnd_list = [ ( 'text/uri-list', 0, self.TARGET_TYPE_URI_LIST ) ] 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 | self.widget.drag_dest_set(gtk.DEST_DEFAULT_MOTION |
gtk.DEST_DEFAULT_HIGHLIGHT | gtk.DEST_DEFAULT_HIGHLIGHT |
gtk.DEST_DEFAULT_DROP, gtk.DEST_DEFAULT_DROP,
@ -710,18 +724,29 @@ class ChatControl(ChatControlBase):
self._schedule_activity_timers() self._schedule_activity_timers()
# Hook up signals # 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._on_window_motion_notify)
self.handlers[id] = self.parent_win.window
message_tv_buffer = self.msg_textview.get_buffer() message_tv_buffer = self.msg_textview.get_buffer()
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.xml.get_widget('banner_eventbox').connect('button-press-event', widget = self.xml.get_widget('banner_eventbox')
id = widget.connect('button-press-event',
self._on_banner_eventbox_button_press_event) self._on_banner_eventbox_button_press_event)
self.handlers[id] = widget
xm = gtk.glade.XML(GTKGUI_GLADE, 'avatar_eventbox', APP) widget = self.xml.get_widget('avatar_eventbox')
xm.signal_autoconnect(self) id = widget.connect('enter-notify-event', self.on_avatar_eventbox_enter_notify_event)
xm = gtk.glade.XML(GTKGUI_GLADE, 'gpg_togglebutton', APP) self.handlers[id] = widget
xm.signal_autoconnect(self)
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]: if self.contact.jid in gajim.encrypted_chats[self.account]:
self.xml.get_widget('gpg_togglebutton').set_active(True) 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') add_to_roster_menuitem = xml.get_widget('add_to_roster_menuitem')
send_file_menuitem = xml.get_widget('send_file_menuitem') send_file_menuitem = xml.get_widget('send_file_menuitem')
compact_view_menuitem = xml.get_widget('compact_view_menuitem') compact_view_menuitem = xml.get_widget('compact_view_menuitem')
information_menuitem = xml.get_widget('information_menuitem')
contact = self.parent_win.get_active_contact() contact = self.parent_win.get_active_contact()
jid = contact.jid jid = contact.jid
@ -1172,8 +1198,19 @@ class ChatControl(ChatControlBase):
# connect signals # 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 return menu
def send_chatstate(self, state, contact = None): def send_chatstate(self, state, contact = None):
@ -1233,8 +1270,8 @@ class ChatControl(ChatControlBase):
# in JEP22, when we already sent stop composing # in JEP22, when we already sent stop composing
# notification on paused, don't resend it # notification on paused, don't resend it
if contact.composing_jep == 'JEP-0022' and \ if contact.composing_jep == 'JEP-0022' and \
contact.our_chatstate in ('paused', 'active', 'inactive') and \ contact.our_chatstate in ('paused', 'active', 'inactive') and \
state is not 'composing': # not composing == in (active, inactive, gone) state is not 'composing': # not composing == in (active, inactive, gone)
contact.our_chatstate = 'active' contact.our_chatstate = 'active'
self.reset_kbd_mouse_timeout_vars() self.reset_kbd_mouse_timeout_vars()
return return
@ -1271,6 +1308,12 @@ class ChatControl(ChatControlBase):
if gajim.interface.systray_enabled and self.nb_unread > 0: if gajim.interface.systray_enabled and self.nb_unread > 0:
gajim.interface.systray.remove_jid(self.contact.jid, self.account, gajim.interface.systray.remove_jid(self.contact.jid, self.account,
self.type_id) 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): def allow_shutdown(self):
if time.time() - gajim.last_message_time[self.account]\ if time.time() - gajim.last_message_time[self.account]\

View file

@ -1504,13 +1504,23 @@ class Interface:
def on_launch_browser_mailer(self, widget, url, kind): def on_launch_browser_mailer(self, widget, url, kind):
helpers.launch_browser_mailer(kind, url) 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): def prepare_emoticons_menu(self):
menu = gtk.Menu() menu = gtk.Menu()
def emoticon_clicked(w, str_): def emoticon_clicked(w, str_):
if self.emoticon_menuitem_clicked: if self.emoticon_menuitem_clicked:
self.emoticon_menuitem_clicked(str_) 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 counter = 0
# Calculate the side lenght of the popup to make it a square # Calculate the side lenght of the popup to make it a square
size = int(round(math.sqrt(len(gajim.interface.emoticons_images)))) size = int(round(math.sqrt(len(gajim.interface.emoticons_images))))
@ -1527,6 +1537,7 @@ class Interface:
menu.attach(item, counter % size, counter % size + 1, menu.attach(item, counter % size, counter % size + 1,
counter / size, counter / size + 1) counter / size, counter / size + 1)
counter += 1 counter += 1
menu.connect('selection-done', selection_done)
menu.show_all() menu.show_all()
return menu return menu

View file

@ -59,6 +59,47 @@ C_TEXT, # text shown in the cellrenderer
C_AVATAR, # avatar of the contact C_AVATAR, # avatar of the contact
) = range(5) ) = 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): class PrivateChatControl(ChatControl):
TYPE_ID = message_control.TYPE_PM TYPE_ID = message_control.TYPE_PM
@ -98,6 +139,38 @@ class GroupchatControl(ChatControlBase):
'muc_child_vbox', (_('Group Chat'), _('Group Chats')), 'muc_child_vbox', (_('Group Chat'), _('Group Chats')),
contact, acct); 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.room_jid = self.contact.jid
self.nick = contact.name self.nick = contact.name
self.name = self.room_jid.split('@')[0] self.name = self.room_jid.split('@')[0]
@ -132,12 +205,37 @@ class GroupchatControl(ChatControlBase):
# connect the menuitems to their respective functions # connect the menuitems to their respective functions
xm = gtk.glade.XML(GTKGUI_GLADE, 'gc_control_popup_menu', APP) 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.gc_popup_menu = xm.get_widget('gc_control_popup_menu')
self.name_label = self.xml.get_widget('banner_name_label') 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._on_window_focus_in_event)
self.handlers[id] = self.parent_win.window
# set the position of the current hpaned # set the position of the current hpaned
self.hpaned_position = gajim.config.get('gc-hpaned-position') self.hpaned_position = gajim.config.get('gc-hpaned-position')
@ -145,15 +243,18 @@ class GroupchatControl(ChatControlBase):
self.hpaned.set_position(self.hpaned_position) self.hpaned.set_position(self.hpaned_position)
list_treeview = self.list_treeview = self.xml.get_widget('list_treeview') list_treeview = self.list_treeview = self.xml.get_widget('list_treeview')
list_treeview.get_selection().connect('changed', selection = list_treeview.get_selection()
self.on_list_treeview_selection_changed) id = selection.connect('changed',
list_treeview.connect('style-set', self.on_list_treeview_style_set) 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 # we want to know when the the widget resizes, because that is
# an indication that the hpaned has moved... # an indication that the hpaned has moved...
# FIXME: Find a better indicator 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.on_treeview_size_allocate)
self.handlers[id] = self.list_treeview
#status_image, type, nickname, shown_nick #status_image, type, nickname, shown_nick
store = gtk.TreeStore(gtk.Image, str, str, str, gtk.gdk.Pixbuf) store = gtk.TreeStore(gtk.Image, str, str, str, gtk.gdk.Pixbuf)
store.set_sort_column_id(C_TEXT, gtk.SORT_ASCENDING) store.set_sort_column_id(C_TEXT, gtk.SORT_ASCENDING)
@ -168,18 +269,20 @@ class GroupchatControl(ChatControlBase):
renderer_pixbuf = gtk.CellRendererPixbuf() # avatar image renderer_pixbuf = gtk.CellRendererPixbuf() # avatar image
column.pack_start(renderer_pixbuf, expand = False) column.pack_start(renderer_pixbuf, expand = False)
column.add_attribute(renderer_pixbuf, 'pixbuf', C_AVATAR) column.add_attribute(renderer_pixbuf, 'pixbuf', C_AVATAR)
column.set_cell_data_func(renderer_pixbuf, self.avatar_cell_data_func, column.set_cell_data_func(renderer_pixbuf, tree_cell_data_func,
None) self.list_treeview)
renderer_pixbuf.set_property('xalign', 1) # align pixbuf to the right
renderer_image = cell_renderer_image.CellRendererImage(0, 0) # status img renderer_image = cell_renderer_image.CellRendererImage(0, 0) # status img
column.pack_start(renderer_image, expand = False) column.pack_start(renderer_image, expand = False)
column.add_attribute(renderer_image, 'image', C_IMG) 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 renderer_text = gtk.CellRendererText() # nickname
column.pack_start(renderer_text, expand = True) column.pack_start(renderer_text, expand = True)
column.add_attribute(renderer_text, 'markup', C_TEXT) 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) self.list_treeview.append_column(column)
@ -208,49 +311,6 @@ class GroupchatControl(ChatControlBase):
if self.parent_win.get_active_jid() == self.room_jid: if self.parent_win.get_active_jid() == self.room_jid:
self.allow_focus_out_line = True 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): def on_treeview_size_allocate(self, widget, allocation):
'''The MUC treeview has resized. Move the hpaned in all tabs to match''' '''The MUC treeview has resized. Move the hpaned in all tabs to match'''
self.hpaned_position = self.hpaned.get_position() self.hpaned_position = self.hpaned.get_position()
@ -1116,6 +1176,11 @@ class GroupchatControl(ChatControlBase):
del gajim.gc_connected[self.account][self.room_jid] del gajim.gc_connected[self.account][self.room_jid]
# Save hpaned position # Save hpaned position
gajim.config.set('gc-hpaned-position', self.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): def allow_shutdown(self):
retval = True retval = True
@ -1354,7 +1419,8 @@ class GroupchatControl(ChatControlBase):
(user_affiliation == 'member' and target_affiliation in ('admin', 'owner')) or \ (user_affiliation == 'member' and target_affiliation in ('admin', 'owner')) or \
(user_affiliation == 'none' and target_affiliation != 'none'): (user_affiliation == 'none' and target_affiliation != 'none'):
item.set_sensitive(False) 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 = xml.get_widget('voice_checkmenuitem')
item.set_active(target_role != 'visitor') item.set_active(target_role != 'visitor')
@ -1363,54 +1429,67 @@ class GroupchatControl(ChatControlBase):
(user_affiliation=='member' and target_affiliation!='none') or \ (user_affiliation=='member' and target_affiliation!='none') or \
target_affiliation in ('admin', 'owner'): target_affiliation in ('admin', 'owner'):
item.set_sensitive(False) 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 = xml.get_widget('moderator_checkmenuitem')
item.set_active(target_role == 'moderator') item.set_active(target_role == 'moderator')
if not user_affiliation in ('admin', 'owner') or \ if not user_affiliation in ('admin', 'owner') or \
target_affiliation in ('admin', 'owner'): target_affiliation in ('admin', 'owner'):
item.set_sensitive(False) 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') item = xml.get_widget('ban_menuitem')
if not user_affiliation in ('admin', 'owner') or \ if not user_affiliation in ('admin', 'owner') or \
(target_affiliation in ('admin', 'owner') and\ (target_affiliation in ('admin', 'owner') and\
user_affiliation != 'owner'): user_affiliation != 'owner'):
item.set_sensitive(False) 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 = xml.get_widget('member_checkmenuitem')
item.set_active(target_affiliation != 'none') item.set_active(target_affiliation != 'none')
if not user_affiliation in ('admin', 'owner') or \ if not user_affiliation in ('admin', 'owner') or \
(user_affiliation != 'owner' and target_affiliation in ('admin','owner')): (user_affiliation != 'owner' and target_affiliation in ('admin','owner')):
item.set_sensitive(False) 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 = xml.get_widget('admin_checkmenuitem')
item.set_active(target_affiliation in ('admin', 'owner')) item.set_active(target_affiliation in ('admin', 'owner'))
if not user_affiliation == 'owner': if not user_affiliation == 'owner':
item.set_sensitive(False) 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 = xml.get_widget('owner_checkmenuitem')
item.set_active(target_affiliation == 'owner') item.set_active(target_affiliation == 'owner')
if not user_affiliation == 'owner': if not user_affiliation == 'owner':
item.set_sensitive(False) 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 = 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 = 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') item = xml.get_widget('add_to_roster_menuitem')
if not jid: if not jid:
item.set_sensitive(False) 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 = 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! # show the popup now!
menu = xml.get_widget('gc_occupants_menu') menu = xml.get_widget('gc_occupants_menu')

View file

@ -3817,7 +3817,6 @@ Per type</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="add_tearoffs">False</property> <property name="add_tearoffs">False</property>
<property name="focus_on_click">True</property> <property name="focus_on_click">True</property>
<signal name="changed" handler="on_emoticons_combobox_changed" last_modification_time="Sun, 05 Feb 2006 14:06:24 GMT"/>
</widget> </widget>
<packing> <packing>
<property name="padding">0</property> <property name="padding">0</property>
@ -15233,7 +15232,6 @@ Messages</property>
<property name="tooltip" translatable="yes">Click to see past conversation in this room</property> <property name="tooltip" translatable="yes">Click to see past conversation in this room</property>
<property name="label" translatable="yes">_History</property> <property name="label" translatable="yes">_History</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="_on_history_menuitem_activate" last_modification_time="Thu, 12 Jan 2006 02:41:11 GMT"/>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1359"> <widget class="GtkImage" id="image1359">
@ -15253,7 +15251,6 @@ Messages</property>
<widget class="GtkImageMenuItem" id="configure_room_menuitem"> <widget class="GtkImageMenuItem" id="configure_room_menuitem">
<property name="label" translatable="yes">Configure _Room</property> <property name="label" translatable="yes">Configure _Room</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="_on_configure_room_menuitem_activate" last_modification_time="Thu, 12 Jan 2006 02:41:11 GMT"/>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1360"> <widget class="GtkImage" id="image1360">
@ -15273,7 +15270,6 @@ Messages</property>
<widget class="GtkImageMenuItem" id="change_subject_menuitem"> <widget class="GtkImageMenuItem" id="change_subject_menuitem">
<property name="label" translatable="yes">Change _Subject</property> <property name="label" translatable="yes">Change _Subject</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="_on_change_subject_menuitem_activate" last_modification_time="Thu, 12 Jan 2006 02:41:11 GMT"/>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1361"> <widget class="GtkImage" id="image1361">
@ -15293,7 +15289,6 @@ Messages</property>
<widget class="GtkImageMenuItem" id="change_nick_menuitem"> <widget class="GtkImageMenuItem" id="change_nick_menuitem">
<property name="label" translatable="yes">Change _Nickname</property> <property name="label" translatable="yes">Change _Nickname</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="_on_change_nick_menuitem_activate" last_modification_time="Thu, 12 Jan 2006 02:41:11 GMT"/>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1362"> <widget class="GtkImage" id="image1362">
@ -15313,7 +15308,6 @@ Messages</property>
<widget class="GtkImageMenuItem" id="bookmark_room_menuitem"> <widget class="GtkImageMenuItem" id="bookmark_room_menuitem">
<property name="label" translatable="yes">_Bookmark This Room</property> <property name="label" translatable="yes">_Bookmark This Room</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="_on_bookmark_room_menuitem_activate" last_modification_time="Thu, 12 Jan 2006 02:41:11 GMT"/>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1363"> <widget class="GtkImage" id="image1363">
@ -15334,7 +15328,6 @@ Messages</property>
<property name="label" translatable="yes">_Compact View Alt+C</property> <property name="label" translatable="yes">_Compact View Alt+C</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<property name="active">False</property> <property name="active">False</property>
<signal name="activate" handler="_on_compact_view_menuitem_activate" last_modification_time="Thu, 12 Jan 2006 02:41:11 GMT"/>
</widget> </widget>
</child> </child>
</widget> </widget>
@ -15347,7 +15340,6 @@ Messages</property>
<property name="tooltip" translatable="yes">Click to see past conversations with this contact</property> <property name="tooltip" translatable="yes">Click to see past conversations with this contact</property>
<property name="label" translatable="yes">_History</property> <property name="label" translatable="yes">_History</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="_on_history_menuitem_activate" last_modification_time="Thu, 12 Jan 2006 02:40:18 GMT"/>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1366"> <widget class="GtkImage" id="image1366">
@ -15368,7 +15360,6 @@ Messages</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="label">gtk-dialog-info</property> <property name="label">gtk-dialog-info</property>
<property name="use_stock">True</property> <property name="use_stock">True</property>
<signal name="activate" handler="_on_contact_information_menuitem_activate" last_modification_time="Thu, 12 Jan 2006 02:40:18 GMT"/>
</widget> </widget>
</child> </child>
@ -16811,21 +16802,21 @@ Maybe I'll refactor later</property>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkImageMenuItem" id="service_discovery_menuitem"> <widget class="GtkImageMenuItem" id="service_discovery_menuitem">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">_Discover Services...</property> <property name="label" translatable="yes">_Discover Services...</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<child internal-child="image"> <child internal-child="image">
<widget class="GtkImage" id="image1232"> <widget class="GtkImage" id="image1232">
<property name="visible">True</property> <property name="visible">True</property>
<property name="stock">gtk-find</property> <property name="stock">gtk-find</property>
<property name="icon_size">1</property> <property name="icon_size">1</property>
<property name="xalign">0.5</property> <property name="xalign">0.5</property>
<property name="yalign">0.5</property> <property name="yalign">0.5</property>
<property name="xpad">0</property> <property name="xpad">0</property>
<property name="ypad">0</property> <property name="ypad">0</property>
</widget> </widget>
</child> </child>
</widget> </widget>
@ -18155,8 +18146,6 @@ Status message</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="enter_notify_event" handler="on_avatar_eventbox_enter_notify_event" last_modification_time="Thu, 05 Jan 2006 03:19:02 GMT"/>
<signal name="leave_notify_event" handler="on_avatar_eventbox_leave_notify_event" last_modification_time="Thu, 05 Jan 2006 03:19:08 GMT"/>
<child> <child>
<widget class="GtkImage" id="avatar_image"> <widget class="GtkImage" id="avatar_image">
@ -18268,7 +18257,6 @@ Status message</property>
<property name="focus_on_click">False</property> <property name="focus_on_click">False</property>
<property name="active">False</property> <property name="active">False</property>
<property name="inconsistent">False</property> <property name="inconsistent">False</property>
<signal name="clicked" handler="on_toggle_gpg_togglebutton" last_modification_time="Fri, 14 Apr 2006 22:50:46 GMT"/>
<child> <child>
<widget class="GtkImage" id="image1333"> <widget class="GtkImage" id="image1333">
@ -18301,90 +18289,6 @@ Status message</property>
<property name="fill">True</property> <property name="fill">True</property>
</packing> </packing>
</child> </child>
<child>
<widget class="GtkToggleButton" id="bold_togglebutton">
<property name="tooltip" translatable="yes">Bold</property>
<property name="can_focus">True</property>
<property name="relief">GTK_RELIEF_NONE</property>
<property name="focus_on_click">False</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<child>
<widget class="GtkImage" id="image1334">
<property name="visible">True</property>
<property name="stock">gtk-bold</property>
<property name="icon_size">3</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkToggleButton" id="italic_togglebutton">
<property name="tooltip" translatable="yes">Italic</property>
<property name="can_focus">True</property>
<property name="relief">GTK_RELIEF_NONE</property>
<property name="focus_on_click">False</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<child>
<widget class="GtkImage" id="image1335">
<property name="visible">True</property>
<property name="stock">gtk-italic</property>
<property name="icon_size">3</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkToggleButton" id="underline_togglebutton">
<property name="tooltip" translatable="yes">Underline</property>
<property name="can_focus">True</property>
<property name="relief">GTK_RELIEF_NONE</property>
<property name="focus_on_click">False</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<child>
<widget class="GtkImage" id="image1336">
<property name="visible">True</property>
<property name="stock">gtk-underline</property>
<property name="icon_size">3</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget> </widget>
<packing> <packing>
<property name="padding">0</property> <property name="padding">0</property>
@ -18407,7 +18311,6 @@ Status message</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:04:40 GMT"/>
<child> <child>
<widget class="GtkHBox" id="hbox3008"> <widget class="GtkHBox" id="hbox3008">
@ -18457,12 +18360,11 @@ Status message</property>
</child> </child>
<child> <child>
<widget class="GtkButton" id="button29"> <widget class="GtkButton" id="message_window_actions_button">
<property name="visible">True</property> <property name="visible">True</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_actions_button_clicked" last_modification_time="Wed, 03 Aug 2005 15:06:36 GMT"/>
<child> <child>
<widget class="GtkAlignment" id="alignment101"> <widget class="GtkAlignment" id="alignment101">
@ -18666,7 +18568,6 @@ Status message</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="tab_hbox"> <widget class="GtkHBox" id="tab_hbox">
@ -18902,13 +18803,6 @@ topic</property>
<property name="fixed_height_mode">False</property> <property name="fixed_height_mode">False</property>
<property name="hover_selection">False</property> <property name="hover_selection">False</property>
<property name="hover_expand">False</property> <property name="hover_expand">False</property>
<signal name="row_activated" handler="on_list_treeview_row_activated" last_modification_time="Sat, 05 Mar 2005 00:31:45 GMT"/>
<signal name="row_collapsed" handler="on_list_treeview_row_collapsed" last_modification_time="Sat, 05 Mar 2005 00:31:52 GMT"/>
<signal name="row_expanded" handler="on_list_treeview_row_expanded" last_modification_time="Sat, 05 Mar 2005 00:31:57 GMT"/>
<signal name="button_press_event" handler="on_list_treeview_button_press_event" last_modification_time="Sat, 05 Mar 2005 00:32:05 GMT"/>
<signal name="key_press_event" handler="on_list_treeview_key_press_event" last_modification_time="Sat, 26 Mar 2005 20:42:24 GMT"/>
<signal name="motion_notify_event" handler="on_list_treeview_motion_notify_event" last_modification_time="Thu, 18 Aug 2005 23:11:24 GMT"/>
<signal name="leave_notify_event" handler="on_list_treeview_leave_notify_event" last_modification_time="Thu, 18 Aug 2005 23:11:51 GMT"/>
</widget> </widget>
</child> </child>
</widget> </widget>
@ -18933,103 +18827,7 @@ topic</property>
<property name="spacing">0</property> <property name="spacing">0</property>
<child> <child>
<widget class="GtkHBox" id="hbox3012"> <placeholder/>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<placeholder/>
</child>
<child>
<widget class="GtkToggleButton" id="bold_togglebutton">
<property name="tooltip" translatable="yes">Bold</property>
<property name="can_focus">True</property>
<property name="relief">GTK_RELIEF_NONE</property>
<property name="focus_on_click">False</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<child>
<widget class="GtkImage" id="image1340">
<property name="visible">True</property>
<property name="stock">gtk-bold</property>
<property name="icon_size">3</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkToggleButton" id="italic_togglebutton">
<property name="tooltip" translatable="yes">Italic</property>
<property name="can_focus">True</property>
<property name="relief">GTK_RELIEF_NONE</property>
<property name="focus_on_click">False</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<child>
<widget class="GtkImage" id="image1341">
<property name="visible">True</property>
<property name="stock">gtk-italic</property>
<property name="icon_size">3</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkToggleButton" id="underline_togglebutton">
<property name="tooltip" translatable="yes">Underline</property>
<property name="can_focus">True</property>
<property name="relief">GTK_RELIEF_NONE</property>
<property name="focus_on_click">False</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<child>
<widget class="GtkImage" id="image1342">
<property name="visible">True</property>
<property name="stock">gtk-underline</property>
<property name="icon_size">3</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child> </child>
<child> <child>
@ -19095,12 +18893,11 @@ topic</property>
</child> </child>
<child> <child>
<widget class="GtkButton" id="button32"> <widget class="GtkButton" id="muc_window_actions_button">
<property name="visible">True</property> <property name="visible">True</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_actions_button_clicked" last_modification_time="Mon, 13 Jun 2005 11:03:39 GMT"/>
<child> <child>
<widget class="GtkAlignment" id="alignment104"> <widget class="GtkAlignment" id="alignment104">

View file

@ -45,6 +45,34 @@ from common import helpers
screen_w = gtk.gdk.screen_width() screen_w = gtk.gdk.screen_width()
screen_h = gtk.gdk.screen_height() 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): def get_theme_font_for_option(theme, option):
'''return string description of the font, stored in '''return string description of the font, stored in
theme preferences''' theme preferences'''

View file

@ -36,6 +36,9 @@ class MessageControl:
def __init__(self, type_id, parent_win, widget_name, display_names, contact, account, resource = None): 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 '''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''' 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.type_id = type_id
self.parent_win = parent_win self.parent_win = parent_win
self.widget_name = widget_name self.widget_name = widget_name
@ -51,8 +54,6 @@ class MessageControl:
self.xml = gtk.glade.XML(GTKGUI_GLADE, widget_name, APP) self.xml = gtk.glade.XML(GTKGUI_GLADE, widget_name, APP)
self.widget = self.xml.get_widget(widget_name) self.widget = self.xml.get_widget(widget_name)
# Autoconnect glade signals
self.xml.signal_autoconnect(self)
def get_full_jid(self): def get_full_jid(self):
fjid = self.contact.jid fjid = self.contact.jid
@ -137,33 +138,3 @@ class MessageControl:
gajim.connections[self.account].send_message(jid, message, keyID, gajim.connections[self.account].send_message(jid, message, keyID,
type = type, chatstate = chatstate, msg_id = msg_id, type = type, chatstate = chatstate, msg_id = msg_id,
composing_jep = composing_jep, resource = self.resource) 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)

View file

@ -147,10 +147,12 @@ class MessageWindow:
# Add notebook page and connect up to the tab's close button # Add notebook page and connect up to the tab's close button
xml = gtk.glade.XML(GTKGUI_GLADE, 'chat_tab_ebox', APP) xml = gtk.glade.XML(GTKGUI_GLADE, 'chat_tab_ebox', APP)
tab_label_box = xml.get_widget('chat_tab_ebox') tab_label_box = xml.get_widget('chat_tab_ebox')
xml.signal_connect('on_close_button_clicked', widget = xml.get_widget('tab_close_button')
self._on_close_button_clicked, control) id = widget.connect('clicked', self._on_close_button_clicked, control)
xml.signal_connect('on_tab_eventbox_button_press_event', control.handlers[id] = widget
self.on_tab_eventbox_button_press_event, control.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.notebook.append_page(control.widget, tab_label_box)
self.setup_tab_dnd(control.widget) self.setup_tab_dnd(control.widget)