Migrating code into the new classes
This commit is contained in:
parent
8d42f5d0f0
commit
f195c47ea7
|
@ -1,13 +0,0 @@
|
||||||
Index: src/roster_window.py
|
|
||||||
===================================================================
|
|
||||||
--- src/roster_window.py (revision 4923)
|
|
||||||
+++ src/roster_window.py (working copy)
|
|
||||||
@@ -87,6 +87,8 @@
|
|
||||||
model = self.tree.get_model()
|
|
||||||
root = self.get_account_iter(account)
|
|
||||||
group_iter = model.iter_children(root)
|
|
||||||
+ # C_NAME column contacts the pango escaped group name
|
|
||||||
+ name = gtkgui_helpers.escape_for_pango_markup(name)
|
|
||||||
while group_iter:
|
|
||||||
group_name = model[group_iter][C_NAME].decode('utf-8')
|
|
||||||
if name == group_name:
|
|
|
@ -188,11 +188,11 @@ class ChatControlBase(MessageControl):
|
||||||
|
|
||||||
if event.keyval == gtk.keysyms.Up:
|
if event.keyval == gtk.keysyms.Up:
|
||||||
if event.state & gtk.gdk.CONTROL_MASK: # Ctrl+UP
|
if event.state & gtk.gdk.CONTROL_MASK: # Ctrl+UP
|
||||||
self.sent_messages_scroll(jid, 'up', widget.get_buffer())
|
self.sent_messages_scroll('up', widget.get_buffer())
|
||||||
return
|
return
|
||||||
elif event.keyval == gtk.keysyms.Down:
|
elif event.keyval == gtk.keysyms.Down:
|
||||||
if event.state & gtk.gdk.CONTROL_MASK: # Ctrl+Down
|
if event.state & gtk.gdk.CONTROL_MASK: # Ctrl+Down
|
||||||
self.sent_messages_scroll(jid, 'down', widget.get_buffer())
|
self.sent_messages_scroll('down', widget.get_buffer())
|
||||||
return
|
return
|
||||||
elif event.keyval == gtk.keysyms.Return or \
|
elif event.keyval == gtk.keysyms.Return or \
|
||||||
event.keyval == gtk.keysyms.KP_Enter: # ENTER
|
event.keyval == gtk.keysyms.KP_Enter: # ENTER
|
||||||
|
@ -501,6 +501,30 @@ class ChatControlBase(MessageControl):
|
||||||
gajim.interface.systray.remove_jid(jid, self.account,
|
gajim.interface.systray.remove_jid(jid, self.account,
|
||||||
self.type_id)
|
self.type_id)
|
||||||
|
|
||||||
|
def sent_messages_scroll(self, direction, conv_buf):
|
||||||
|
size = len(self.sent_history)
|
||||||
|
if self.typing_new:
|
||||||
|
#user was typing something and then went into history, so save
|
||||||
|
#whatever is already typed
|
||||||
|
start_iter = conv_buf.get_start_iter()
|
||||||
|
end_iter = conv_buf.get_end_iter()
|
||||||
|
self.orig_msg = conv_buf.get_text(start_iter, end_iter, 0).decode('utf-8')
|
||||||
|
self.typing_new = False
|
||||||
|
if direction == 'up':
|
||||||
|
if self.sent_history_pos == 0:
|
||||||
|
return
|
||||||
|
self.sent_history_pos = self.sent_history_pos - 1
|
||||||
|
conv_buf.set_text(self.sent_history[self.sent_history_pos])
|
||||||
|
elif direction == 'down':
|
||||||
|
if self.sent_history_pos >= size - 1:
|
||||||
|
conv_buf.set_text(self.orig_msg);
|
||||||
|
self.typing_new = True
|
||||||
|
self.sent_history_pos = size
|
||||||
|
return
|
||||||
|
|
||||||
|
self.sent_history_pos = self.sent_history_pos + 1
|
||||||
|
conv_buf.set_text(self.sent_history[self.sent_history_pos])
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
class ChatControl(ChatControlBase):
|
class ChatControl(ChatControlBase):
|
||||||
'''A control for standard 1-1 chat'''
|
'''A control for standard 1-1 chat'''
|
||||||
|
@ -512,16 +536,50 @@ class ChatControl(ChatControlBase):
|
||||||
self.compact_view_always = gajim.config.get('always_compact_view_chat')
|
self.compact_view_always = gajim.config.get('always_compact_view_chat')
|
||||||
self.set_compact_view(self.compact_view_always)
|
self.set_compact_view(self.compact_view_always)
|
||||||
|
|
||||||
# chatstate timers and state
|
|
||||||
self._schedule_activity_timers()
|
|
||||||
self.reset_kbd_mouse_timeout_vars()
|
|
||||||
|
|
||||||
xm = gtk.glade.XML(GTKGUI_GLADE, 'chat_control_popup_menu', APP)
|
xm = gtk.glade.XML(GTKGUI_GLADE, 'chat_control_popup_menu', APP)
|
||||||
xm.signal_autoconnect(self)
|
xm.signal_autoconnect(self)
|
||||||
self.popup_menu = xm.get_widget('chat_control_popup_menu')
|
self.popup_menu = xm.get_widget('chat_control_popup_menu')
|
||||||
xm = gtk.glade.XML(GTKGUI_GLADE, 'banner_eventbox', APP)
|
xm = gtk.glade.XML(GTKGUI_GLADE, 'banner_eventbox', APP)
|
||||||
xm.signal_autoconnect(self)
|
xm.signal_autoconnect(self)
|
||||||
|
|
||||||
|
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)
|
||||||
|
self.widget.drag_dest_set(gtk.DEST_DEFAULT_MOTION | gtk.DEST_DEFAULT_HIGHLIGHT |
|
||||||
|
gtk.DEST_DEFAULT_DROP,
|
||||||
|
self.dnd_list, gtk.gdk.ACTION_COPY)
|
||||||
|
|
||||||
|
# keep timeout id and window obj for possible big avatar
|
||||||
|
# it is on enter-notify and leave-notify so no need to be per jid
|
||||||
|
self.show_bigger_avatar_timeout_id = None
|
||||||
|
self.bigger_avatar_window = None
|
||||||
|
self.show_avatar(self.contact.resource)
|
||||||
|
|
||||||
|
# chatstate timers and state
|
||||||
|
self.reset_kbd_mouse_timeout_vars()
|
||||||
|
self._schedule_activity_timers()
|
||||||
|
self.parent_win.window.connect('motion-notify-event',
|
||||||
|
self._on_window_motion_notify)
|
||||||
|
|
||||||
|
def save_var(self, jid):
|
||||||
|
gpg_enabled = self.xmls[jid].get_widget('gpg_togglebutton').get_active()
|
||||||
|
return {'gpg_enabled': gpg_enabled}
|
||||||
|
|
||||||
|
def load_var(self, jid, var):
|
||||||
|
if not self.xmls.has_key(jid):
|
||||||
|
return
|
||||||
|
self.xmls[jid].get_widget('gpg_togglebutton').set_active(
|
||||||
|
var['gpg_enabled'])
|
||||||
|
|
||||||
|
def _on_window_motion_notify(self, widget, event):
|
||||||
|
'''it gets called no matter if it is the active window or not'''
|
||||||
|
print "_on_window_motion_notify"
|
||||||
|
if widget.get_property('has-toplevel-focus'):
|
||||||
|
# change chatstate only if window is the active one
|
||||||
|
self.mouse_over_in_last_5_secs = True
|
||||||
|
self.mouse_over_in_last_30_secs = True
|
||||||
|
|
||||||
|
|
||||||
def _schedule_activity_timers(self):
|
def _schedule_activity_timers(self):
|
||||||
self.possible_paused_timeout_id = gobject.timeout_add(5000,
|
self.possible_paused_timeout_id = gobject.timeout_add(5000,
|
||||||
self.check_for_possible_paused_chatstate, None)
|
self.check_for_possible_paused_chatstate, None)
|
||||||
|
@ -1013,3 +1071,41 @@ class ChatControl(ChatControlBase):
|
||||||
self.send_chatstate('active', self.contact.jid)
|
self.send_chatstate('active', self.contact.jid)
|
||||||
else:
|
else:
|
||||||
self.send_chatstate('inactive', self.contact.jid)
|
self.send_chatstate('inactive', self.contact.jid)
|
||||||
|
|
||||||
|
def show_avatar(self, resource = None):
|
||||||
|
jid = self.contact.jid
|
||||||
|
jid_with_resource = jid
|
||||||
|
if resource:
|
||||||
|
jid_with_resource += '/' + resource
|
||||||
|
|
||||||
|
# we assume contact has no avatar
|
||||||
|
scaled_pixbuf = None
|
||||||
|
|
||||||
|
real_jid = gajim.get_real_jid_from_fjid(self.account, jid)
|
||||||
|
pixbuf = None
|
||||||
|
if real_jid:
|
||||||
|
pixbuf = gtkgui_helpers.get_avatar_pixbuf_from_cache(real_jid)
|
||||||
|
if not real_jid or pixbuf == 'ask':
|
||||||
|
# we don't have the vcard or it's pm and we don't have the real jid
|
||||||
|
gajim.connections[self.account].request_vcard(jid_with_resource)
|
||||||
|
return
|
||||||
|
if pixbuf is not None:
|
||||||
|
scaled_pixbuf = gtkgui_helpers.get_scaled_pixbuf(pixbuf, 'chat')
|
||||||
|
|
||||||
|
image = self.xml.get_widget('avatar_image')
|
||||||
|
image.set_from_pixbuf(scaled_pixbuf)
|
||||||
|
image.show_all()
|
||||||
|
|
||||||
|
def _on_drag_data_received(self, widget, context, x, y, selection, target_type,
|
||||||
|
timestamp):
|
||||||
|
# If not resource, we can't send file
|
||||||
|
if not self.contact.resource:
|
||||||
|
return
|
||||||
|
if target_type == self.TARGET_TYPE_URI_LIST:
|
||||||
|
uri = selection.data.strip()
|
||||||
|
uri_splitted = uri.split() # we may have more than one file dropped
|
||||||
|
for uri in uri_splitted:
|
||||||
|
path = helpers.get_file_path_from_dnd_dropped_uri(uri)
|
||||||
|
if os.path.isfile(path): # is it file?
|
||||||
|
ft = gajim.interface.instances['file_transfers']
|
||||||
|
ft.send_file(self.account, self.contact, path)
|
||||||
|
|
|
@ -650,13 +650,11 @@ class Interface:
|
||||||
if gajim.interface.msg_win_mgr.has_window(jid):
|
if gajim.interface.msg_win_mgr.has_window(jid):
|
||||||
win = gajim.interface.msg_type.get_window(jid)
|
win = gajim.interface.msg_type.get_window(jid)
|
||||||
ctl = win.get_control(jid)
|
ctl = win.get_control(jid)
|
||||||
# FIXME: Why is this needed
|
|
||||||
elif resource and gajim.interface.msg_win_mgr.has_window(jid + '/' + resource):
|
elif resource and gajim.interface.msg_win_mgr.has_window(jid + '/' + resource):
|
||||||
win = gajim.interface.msg_type.get_window(jid + '/' + resource)
|
win = gajim.interface.msg_type.get_window(jid + '/' + resource)
|
||||||
ctl = win.get_control(jid + '/' + resource)
|
ctl = win.get_control(jid + '/' + resource)
|
||||||
if win:
|
if win:
|
||||||
# FIXME: Are these args needed
|
ctl.show_avatar()
|
||||||
ctl.show_avatar(jid, resource)
|
|
||||||
# Show avatar in roster
|
# Show avatar in roster
|
||||||
self.roster.draw_avatar(jid, account)
|
self.roster.draw_avatar(jid, account)
|
||||||
if self.remote_ctrl:
|
if self.remote_ctrl:
|
||||||
|
|
|
@ -1330,7 +1330,7 @@ current room topic.') % command, room_jid)
|
||||||
room_jid, show='offline', status=reason)
|
room_jid, show='offline', status=reason)
|
||||||
del self.nicks[room_jid]
|
del self.nicks[room_jid]
|
||||||
# They can already be removed by the destroy function
|
# They can already be removed by the destroy function
|
||||||
if room_jid in gajim.contacts.get_room_list(self.account):
|
if room_jid in gajim.contacts.get_gc_list(self.account):
|
||||||
gajim.contacts.remove_room(self.account, room_jid)
|
gajim.contacts.remove_room(self.account, room_jid)
|
||||||
del gajim.gc_connected[self.account][room_jid]
|
del gajim.gc_connected[self.account][room_jid]
|
||||||
del self.list_treeview[room_jid]
|
del self.list_treeview[room_jid]
|
||||||
|
|
|
@ -34,12 +34,10 @@ APP = i18n.APP
|
||||||
GTKGUI_GLADE = 'gtkgui.glade'
|
GTKGUI_GLADE = 'gtkgui.glade'
|
||||||
####################
|
####################
|
||||||
|
|
||||||
class MessageControl(gtk.VBox):
|
class MessageControl:
|
||||||
'''An abstract base widget that can embed in the gtk.Notebook of a MessageWindow'''
|
'''An abstract base widget that can embed in the gtk.Notebook of a MessageWindow'''
|
||||||
|
|
||||||
def __init__(self, type_id, parent_win, widget_name, display_name, contact, account):
|
def __init__(self, type_id, parent_win, widget_name, display_name, contact, account):
|
||||||
gtk.VBox.__init__(self)
|
|
||||||
|
|
||||||
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
|
||||||
|
@ -50,7 +48,7 @@ class MessageControl(gtk.VBox):
|
||||||
self.compact_view_current = False
|
self.compact_view_current = False
|
||||||
self.nb_unread = 0
|
self.nb_unread = 0
|
||||||
self.print_time_timeout_id = None
|
self.print_time_timeout_id = None
|
||||||
# FIXME: Make this a member like all the others
|
# FIXME: Make this a member
|
||||||
gajim.last_message_time[self.account][contact.jid] = 0
|
gajim.last_message_time[self.account][contact.jid] = 0
|
||||||
|
|
||||||
self.xml = gtk.glade.XML(GTKGUI_GLADE, widget_name, APP)
|
self.xml = gtk.glade.XML(GTKGUI_GLADE, widget_name, APP)
|
||||||
|
@ -101,6 +99,14 @@ class MessageControl(gtk.VBox):
|
||||||
# NOTE: Derived classes MAY implement this
|
# NOTE: Derived classes MAY implement this
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def save_var(self, jid):
|
||||||
|
'''When called, the derived type should serialize it's state in the form of a
|
||||||
|
name/value (i.e. dict) result.
|
||||||
|
the return value must be compatible with wthe one given to load_var'''
|
||||||
|
pass # Derived classes SHOULD implement this
|
||||||
|
def load_var(self, jid, var):
|
||||||
|
pass # Derived classes SHOULD implement this
|
||||||
|
|
||||||
def send_message(self, message, keyID = '', type = 'chat', chatstate = None):
|
def send_message(self, message, keyID = '', type = 'chat', chatstate = None):
|
||||||
'''Send the given message to the active tab'''
|
'''Send the given message to the active tab'''
|
||||||
# refresh timers
|
# refresh timers
|
||||||
|
|
|
@ -42,6 +42,10 @@ class MessageWindow:
|
||||||
self.widget_name = 'message_window'
|
self.widget_name = 'message_window'
|
||||||
self.xml = gtk.glade.XML(GTKGUI_GLADE, self.widget_name, APP)
|
self.xml = gtk.glade.XML(GTKGUI_GLADE, self.widget_name, APP)
|
||||||
self.window = self.xml.get_widget(self.widget_name)
|
self.window = self.xml.get_widget(self.widget_name)
|
||||||
|
# FIXME: assertion that !GTK_WIDGET_REALIZED fails
|
||||||
|
# gtk+ doesn't make use of the motion notify on gtkwindow by default
|
||||||
|
# so this line adds that
|
||||||
|
#self.window.set_events(gtk.gdk.POINTER_MOTION_MASK)
|
||||||
self.alignment = self.xml.get_widget('alignment')
|
self.alignment = self.xml.get_widget('alignment')
|
||||||
self.notebook = self.xml.get_widget('notebook')
|
self.notebook = self.xml.get_widget('notebook')
|
||||||
|
|
||||||
|
@ -70,6 +74,8 @@ class MessageWindow:
|
||||||
self.notebook.set_show_border(gajim.config.get('tabs_border'))
|
self.notebook.set_show_border(gajim.config.get('tabs_border'))
|
||||||
self.notebook.connect('switch-page',
|
self.notebook.connect('switch-page',
|
||||||
self._on_notebook_switch_page)
|
self._on_notebook_switch_page)
|
||||||
|
self.notebook.connect('key-press-event',
|
||||||
|
self._on_notebook_key_press)
|
||||||
|
|
||||||
# Connect event handling for this Window
|
# Connect event handling for this Window
|
||||||
self.window.connect('delete-event', self._on_window_delete)
|
self.window.connect('delete-event', self._on_window_delete)
|
||||||
|
@ -85,12 +91,8 @@ class MessageWindow:
|
||||||
gtkgui_helpers.resize_window(self.window,
|
gtkgui_helpers.resize_window(self.window,
|
||||||
gajim.config.get('msgwin-width'),
|
gajim.config.get('msgwin-width'),
|
||||||
gajim.config.get('msgwin-height'))
|
gajim.config.get('msgwin-height'))
|
||||||
|
|
||||||
self.window.show_all()
|
|
||||||
|
|
||||||
def _on_window_focus(self, widget, event):
|
def _on_window_focus(self, widget, event):
|
||||||
# FIXME:
|
|
||||||
print "_on_window_focus"
|
|
||||||
# window received focus, so if we had urgency REMOVE IT
|
# window received focus, so if we had urgency REMOVE IT
|
||||||
# NOTE: we do not have to read the message (it maybe in a bg tab)
|
# NOTE: we do not have to read the message (it maybe in a bg tab)
|
||||||
# to remove urgency hint so this functions does that
|
# to remove urgency hint so this functions does that
|
||||||
|
@ -253,21 +255,26 @@ class MessageWindow:
|
||||||
self.notebook.set_current_page(ctl_page)
|
self.notebook.set_current_page(ctl_page)
|
||||||
|
|
||||||
def remove_tab(self, contact):
|
def remove_tab(self, contact):
|
||||||
|
# Shutdown the MessageControl
|
||||||
ctl = self.get_control(contact.jid)
|
ctl = self.get_control(contact.jid)
|
||||||
if len(self._controls) == 1 or not ctl.allow_shutdown():
|
if not ctl.allow_shutdown():
|
||||||
return
|
return
|
||||||
|
|
||||||
if gajim.interface.systray_enabled:
|
|
||||||
gajim.interface.systray.remove_jid(contact.jid, ctl.account,
|
|
||||||
ctl.type)
|
|
||||||
ctl.shutdown()
|
ctl.shutdown()
|
||||||
|
|
||||||
self.notebook.remove_page(self.notebook.page_num(self.childs[jid]))
|
# Update external state
|
||||||
|
if gajim.interface.systray_enabled:
|
||||||
|
gajim.interface.systray.remove_jid(contact.jid, ctl.account,
|
||||||
|
ctl.type_id)
|
||||||
|
del gajim.last_message_time[ctl.account][ctl.contact.jid]
|
||||||
|
|
||||||
|
if len(self._controls) == 1:
|
||||||
|
self.window.destroy()
|
||||||
|
return
|
||||||
|
|
||||||
|
self.notebook.remove_page(self.notebook.page_num(ctl.widget))
|
||||||
|
|
||||||
del self._controls[contact.jid]
|
del self._controls[contact.jid]
|
||||||
del gajim.last_message_time[self.account][jid]
|
if len(self._controls) == 1: # we now have only one tab
|
||||||
|
|
||||||
if len(self.xmls) == 1: # we now have only one tab
|
|
||||||
show_tabs_if_one_tab = gajim.config.get('tabs_always_visible')
|
show_tabs_if_one_tab = gajim.config.get('tabs_always_visible')
|
||||||
self.notebook.set_show_tabs(show_tabs_if_one_tab)
|
self.notebook.set_show_tabs(show_tabs_if_one_tab)
|
||||||
if not show_tabs_if_one_tab:
|
if not show_tabs_if_one_tab:
|
||||||
|
@ -442,6 +449,112 @@ class MessageWindow:
|
||||||
new_ctl = self._widget_to_control(notebook.get_nth_page(page_num))
|
new_ctl = self._widget_to_control(notebook.get_nth_page(page_num))
|
||||||
new_ctl.set_control_active(True)
|
new_ctl.set_control_active(True)
|
||||||
|
|
||||||
|
def _on_notebook_key_press(self, widget, event):
|
||||||
|
st = '1234567890' # alt+1 means the first tab (tab 0)
|
||||||
|
ctl = self.get_active_control()
|
||||||
|
jid = ctl.jid
|
||||||
|
if event.keyval == gtk.keysyms.Escape: # ESCAPE
|
||||||
|
if ctl.type == TYPE_CHAT:
|
||||||
|
self.remove_tab(jid)
|
||||||
|
elif event.keyval == gtk.keysyms.F4 and \
|
||||||
|
(event.state & gtk.gdk.CONTROL_MASK): # CTRL + F4
|
||||||
|
self.remove_tab(jid)
|
||||||
|
elif event.keyval == gtk.keysyms.w and \
|
||||||
|
(event.state & gtk.gdk.CONTROL_MASK): # CTRL + W
|
||||||
|
self.remove_tab(jid)
|
||||||
|
elif event.string and event.string in st and \
|
||||||
|
(event.state & gtk.gdk.MOD1_MASK): # alt + 1,2,3..
|
||||||
|
self.notebook.set_current_page(st.index(event.string))
|
||||||
|
elif event.keyval == gtk.keysyms.c and \
|
||||||
|
(event.state & gtk.gdk.MOD1_MASK): # alt + C toggles compact view
|
||||||
|
ctl.set_compact_view(not self.compact_view_current_state)
|
||||||
|
# FIXME: Move this to ChatControlBase
|
||||||
|
elif event.keyval == gtk.keysyms.e and \
|
||||||
|
(event.state & gtk.gdk.MOD1_MASK): # alt + E opens emoticons menu
|
||||||
|
if gajim.config.get('useemoticons'):
|
||||||
|
msg_tv = self.message_textviews[jid]
|
||||||
|
def set_emoticons_menu_position(w, msg_tv = msg_tv):
|
||||||
|
window = msg_tv.get_window(gtk.TEXT_WINDOW_WIDGET)
|
||||||
|
# get the window position
|
||||||
|
origin = window.get_origin()
|
||||||
|
size = window.get_size()
|
||||||
|
buf = msg_tv.get_buffer()
|
||||||
|
# get the cursor position
|
||||||
|
cursor = msg_tv.get_iter_location(buf.get_iter_at_mark(
|
||||||
|
buf.get_insert()))
|
||||||
|
cursor = msg_tv.buffer_to_window_coords(gtk.TEXT_WINDOW_TEXT,
|
||||||
|
cursor.x, cursor.y)
|
||||||
|
x = origin[0] + cursor[0]
|
||||||
|
y = origin[1] + size[1]
|
||||||
|
menu_width, menu_height = self.emoticons_menu.size_request()
|
||||||
|
#FIXME: get_line_count is not so good
|
||||||
|
#get the iter of cursor, then tv.get_line_yrange
|
||||||
|
# so we know in which y we are typing (not how many lines we have
|
||||||
|
# then go show just above the current cursor line for up
|
||||||
|
# or just below the current cursor line for down
|
||||||
|
#TEST with having 3 lines and writing in the 2nd
|
||||||
|
if y + menu_height > gtk.gdk.screen_height():
|
||||||
|
# move menu just above cursor
|
||||||
|
y -= menu_height + (msg_tv.allocation.height / buf.get_line_count())
|
||||||
|
#else: # move menu just below cursor
|
||||||
|
# y -= (msg_tv.allocation.height / buf.get_line_count())
|
||||||
|
return (x, y, True) # push_in True
|
||||||
|
self.emoticons_menu.popup(None, None, set_emoticons_menu_position, 1, 0)
|
||||||
|
# FIXME Move to ChatControlBase
|
||||||
|
elif event.keyval == gtk.keysyms.Page_Down:
|
||||||
|
if event.state & gtk.gdk.SHIFT_MASK: # SHIFT + PAGE DOWN
|
||||||
|
conv_textview = self.conversation_textviews[jid]
|
||||||
|
rect = conv_textview.get_visible_rect()
|
||||||
|
iter = conv_textview.get_iter_at_location(rect.x,
|
||||||
|
rect.y + rect.height)
|
||||||
|
conv_textview.scroll_to_iter(iter, 0.1, True, 0, 0)
|
||||||
|
# FIXME Move to ChatControlBase
|
||||||
|
elif event.keyval == gtk.keysyms.Page_Up:
|
||||||
|
if event.state & gtk.gdk.SHIFT_MASK: # SHIFT + PAGE UP
|
||||||
|
conv_textview = self.conversation_textviews[jid]
|
||||||
|
rect = conv_textview.get_visible_rect()
|
||||||
|
iter = conv_textview.get_iter_at_location(rect.x, rect.y)
|
||||||
|
conv_textview.scroll_to_iter(iter, 0.1, True, 0, 1)
|
||||||
|
# FIXME Move to ChatControlBase
|
||||||
|
elif event.keyval == gtk.keysyms.Up:
|
||||||
|
if event.state & gtk.gdk.SHIFT_MASK: # SHIFT + UP
|
||||||
|
conversation_scrolledwindow = self.xml.get_widget('conversation_scrolledwindow')
|
||||||
|
conversation_scrolledwindow.emit('scroll-child',
|
||||||
|
gtk.SCROLL_PAGE_BACKWARD, False)
|
||||||
|
elif event.keyval == gtk.keysyms.ISO_Left_Tab: # SHIFT + TAB
|
||||||
|
if event.state & gtk.gdk.CONTROL_MASK: # CTRL + SHIFT + TAB
|
||||||
|
self.move_to_next_unread_tab(False)
|
||||||
|
elif event.keyval == gtk.keysyms.Tab: # TAB
|
||||||
|
if event.state & gtk.gdk.CONTROL_MASK: # CTRL + TAB
|
||||||
|
self.move_to_next_unread_tab(True)
|
||||||
|
# FIXME Move to ChatControlBase
|
||||||
|
elif (event.keyval == gtk.keysyms.l or event.keyval == gtk.keysyms.L) \
|
||||||
|
and event.state & gtk.gdk.CONTROL_MASK: # CTRL + L
|
||||||
|
conv_textview = self.conversation_textviews[jid]
|
||||||
|
conv_textview.get_buffer().set_text('')
|
||||||
|
# FIXME Move to ChatControlBase
|
||||||
|
elif event.keyval == gtk.keysyms.v and event.state & gtk.gdk.CONTROL_MASK:
|
||||||
|
# CTRL + V
|
||||||
|
msg_textview = self.message_textviews[jid]
|
||||||
|
if not msg_textview.is_focus():
|
||||||
|
msg_textview.grab_focus()
|
||||||
|
msg_textview.emit('key_press_event', event)
|
||||||
|
elif event.state & gtk.gdk.CONTROL_MASK or \
|
||||||
|
(event.keyval == gtk.keysyms.Control_L) or \
|
||||||
|
(event.keyval == gtk.keysyms.Control_R):
|
||||||
|
# we pressed a control key or ctrl+sth: we don't block
|
||||||
|
# the event in order to let ctrl+c (copy text) and
|
||||||
|
# others do their default work
|
||||||
|
pass
|
||||||
|
# FIXME Move to ChatControlBase
|
||||||
|
else: # it's a normal key press make sure message_textview has focus
|
||||||
|
msg_textview = self.message_textviews[jid]
|
||||||
|
if msg_textview.get_property('sensitive'):
|
||||||
|
if not msg_textview.is_focus():
|
||||||
|
msg_textview.grab_focus()
|
||||||
|
msg_textview.emit('key_press_event', event)
|
||||||
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
class MessageWindowMgr:
|
class MessageWindowMgr:
|
||||||
'''A manager and factory for MessageWindow objects'''
|
'''A manager and factory for MessageWindow objects'''
|
||||||
|
@ -468,6 +581,7 @@ class MessageWindowMgr:
|
||||||
|
|
||||||
def _new_window(self):
|
def _new_window(self):
|
||||||
win = MessageWindow()
|
win = MessageWindow()
|
||||||
|
win.window.show_all()
|
||||||
# we track the lifetime of this window
|
# we track the lifetime of this window
|
||||||
win.window.connect('destroy', self._on_window_destroy)
|
win.window.connect('destroy', self._on_window_destroy)
|
||||||
return win
|
return win
|
||||||
|
|
|
@ -250,7 +250,8 @@ class Systray:
|
||||||
contacts_menu = gtk.Menu()
|
contacts_menu = gtk.Menu()
|
||||||
item.set_submenu(contacts_menu)
|
item.set_submenu(contacts_menu)
|
||||||
for jid in gajim.contacts.get_jid_list(account):
|
for jid in gajim.contacts.get_jid_list(account):
|
||||||
contact = gajim.get_contact_with_highest_priority(account, jid)
|
contact = gajim.contacts.get_contact_with_highest_priority(account,
|
||||||
|
jid)
|
||||||
if group in contact.groups and contact.show != 'offline' and \
|
if group in contact.groups and contact.show != 'offline' and \
|
||||||
contact.show != 'error':
|
contact.show != 'error':
|
||||||
at_least_one = True
|
at_least_one = True
|
||||||
|
|
Loading…
Reference in New Issue