All keybindings are working and with a biut less code duplication
This commit is contained in:
parent
f195c47ea7
commit
2726e33172
4 changed files with 257 additions and 138 deletions
|
@ -28,6 +28,8 @@ from common import helpers
|
|||
from message_control import MessageControl
|
||||
from conversation_textview import ConversationTextview
|
||||
from message_textview import MessageTextView
|
||||
from common.logger import Constants
|
||||
constants = Constants()
|
||||
|
||||
try:
|
||||
import gtkspell
|
||||
|
@ -76,6 +78,8 @@ class ChatControlBase(MessageControl):
|
|||
'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
|
||||
self.conv_textview = ConversationTextview(None) # FIXME: remove account arg
|
||||
self.conv_textview.show_all()
|
||||
|
@ -83,22 +87,21 @@ class ChatControlBase(MessageControl):
|
|||
self.conv_scrolledwindow.add(self.conv_textview)
|
||||
self.conv_scrolledwindow.get_vadjustment().connect('value-changed',
|
||||
self.on_conversation_vadjustment_value_changed)
|
||||
self.conv_textview.connect('key_press_event',
|
||||
self.on_conversation_textview_key_press_event)
|
||||
# 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',
|
||||
self.on_message_textview_mykeypress_event)
|
||||
self._on_message_textview_mykeypress_event)
|
||||
self.msg_scrolledwindow.add(self.msg_textview)
|
||||
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.xml)
|
||||
self.update_font()
|
||||
|
||||
|
||||
# the following vars are used to keep history of user's messages
|
||||
self.sent_history = []
|
||||
self.sent_history_pos = -1
|
||||
self.sent_history_pos = 0
|
||||
self.typing_new = False
|
||||
self.orig_msg = ''
|
||||
|
||||
|
@ -143,34 +146,43 @@ class ChatControlBase(MessageControl):
|
|||
banner_name_label.modify_fg(gtk.STATE_NORMAL, None)
|
||||
|
||||
|
||||
def on_conversation_textview_key_press_event(self, widget, event):
|
||||
'''Handle events from the ConversationTextview'''
|
||||
print "ChatControl.on_conversation_textview_key_press_event", event
|
||||
def _on_keypress_event(self, widget, event):
|
||||
if event.state & gtk.gdk.CONTROL_MASK:
|
||||
# CTRL + l|L
|
||||
# CTRL + l|L: clear conv_textview
|
||||
if event.keyval == gtk.keysyms.l or event.keyval == gtk.keysyms.L:
|
||||
self.conv_textview.get_buffer().set_text('')
|
||||
# CTRL + v
|
||||
return True
|
||||
# CTRL + v: Paste into msg_textview
|
||||
elif event.keyval == gtk.keysyms.v:
|
||||
if not self.msg_textview.is_focus():
|
||||
self.msg_textview.grab_focus()
|
||||
# Paste into the msg textview
|
||||
self.msg_textview.emit('key_press_event', event)
|
||||
return False
|
||||
|
||||
def on_message_textview_key_press_event(self, widget, event):
|
||||
print "ChatControl.on_message_textview_key_press_event", event
|
||||
|
||||
if event.keyval == gtk.keysyms.Page_Down: # PAGE DOWN
|
||||
if event.state & gtk.gdk.SHIFT_MASK: # SHIFT + PAGE DOWN
|
||||
self.conv_textview.emit('key_press_event', event)
|
||||
elif event.keyval == gtk.keysyms.Page_Up: # PAGE UP
|
||||
if event.state & gtk.gdk.SHIFT_MASK: # SHIFT + PAGE UP
|
||||
def _on_message_textview_key_press_event(self, widget, event):
|
||||
print "_on_message_textview_key_press_event"
|
||||
if event.state & gtk.gdk.SHIFT_MASK:
|
||||
# SHIFT + PAGE_[UP|DOWN]: send to conv_textview
|
||||
if event.keyval == gtk.keysyms.Page_Down or \
|
||||
event.keyval == gtk.keysyms.Page_Up:
|
||||
self.conv_textview.emit('key_press_event', event)
|
||||
return True
|
||||
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
|
||||
self.conv_textview.emit('key_press_event', event)
|
||||
return False
|
||||
|
||||
def on_message_textview_mykeypress_event(self, widget, event_keyval,
|
||||
def _on_message_textview_mykeypress_event(self, widget, event_keyval,
|
||||
event_keymod):
|
||||
'''When a key is pressed:
|
||||
if enter is pressed without the shift key, message (if not empty) is sent
|
||||
and printed in the conversation'''
|
||||
print "ChatControlBase._on_message_textview_mykeypress_event"
|
||||
|
||||
# NOTE: handles mykeypress which is custom signal connected to this
|
||||
# CB in new_tab(). for this singal see message_textview.py
|
||||
|
@ -189,11 +201,9 @@ class ChatControlBase(MessageControl):
|
|||
if event.keyval == gtk.keysyms.Up:
|
||||
if event.state & gtk.gdk.CONTROL_MASK: # Ctrl+UP
|
||||
self.sent_messages_scroll('up', widget.get_buffer())
|
||||
return
|
||||
elif event.keyval == gtk.keysyms.Down:
|
||||
if event.state & gtk.gdk.CONTROL_MASK: # Ctrl+Down
|
||||
self.sent_messages_scroll('down', widget.get_buffer())
|
||||
return
|
||||
elif event.keyval == gtk.keysyms.Return or \
|
||||
event.keyval == gtk.keysyms.KP_Enter: # ENTER
|
||||
# NOTE: SHIFT + ENTER is not needed to be emulated as it is not
|
||||
|
@ -295,8 +305,8 @@ class ChatControlBase(MessageControl):
|
|||
self.nb_unread += 1
|
||||
if gajim.interface.systray_enabled and\
|
||||
gajim.config.get('trayicon_notification_on_new_messages'):
|
||||
gajim.interface.systray.add_jid(jid, self.account, self.type)
|
||||
self.parent_win.redraw_tab(jid)
|
||||
gajim.interface.systray.add_jid(jid, self.account, self.type_id)
|
||||
self.parent_win.redraw_tab(self.contact)
|
||||
self.show_title(urgent)
|
||||
|
||||
def toggle_emoticons(self):
|
||||
|
@ -419,7 +429,7 @@ class ChatControlBase(MessageControl):
|
|||
gajim.interface.systray.remove_jid(jid,
|
||||
self.account,
|
||||
self.type)
|
||||
self.conv_textview.grab_focus()
|
||||
self.msg_textview.grab_focus()
|
||||
|
||||
def bring_scroll_to_end(self, textview, diff_y = 0):
|
||||
''' scrolls to the end of textview if end is not visible '''
|
||||
|
@ -539,9 +549,8 @@ class ChatControl(ChatControlBase):
|
|||
xm = gtk.glade.XML(GTKGUI_GLADE, 'chat_control_popup_menu', APP)
|
||||
xm.signal_autoconnect(self)
|
||||
self.popup_menu = xm.get_widget('chat_control_popup_menu')
|
||||
xm = gtk.glade.XML(GTKGUI_GLADE, 'banner_eventbox', APP)
|
||||
xm.signal_autoconnect(self)
|
||||
|
||||
# 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)
|
||||
|
@ -558,8 +567,58 @@ class ChatControl(ChatControlBase):
|
|||
# chatstate timers and state
|
||||
self.reset_kbd_mouse_timeout_vars()
|
||||
self._schedule_activity_timers()
|
||||
|
||||
# Hook up signals
|
||||
# FIXME: This does not seem to be working
|
||||
self.parent_win.window.connect('motion-notify-event',
|
||||
self._on_window_motion_notify)
|
||||
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',
|
||||
self._on_banner_eventbox_button_press_event)
|
||||
self.xml.get_widget('banner_eventbox').connect('button-press-event',
|
||||
self._on_banner_eventbox_button_press_event)
|
||||
xm = gtk.glade.XML(GTKGUI_GLADE, 'avatar_eventbox', APP)
|
||||
xm.signal_autoconnect(self)
|
||||
|
||||
if self.contact.jid in gajim.encrypted_chats[self.account]:
|
||||
self.xml.get_widget('gpg_togglebutton').set_active(True)
|
||||
|
||||
# restore previous conversation
|
||||
self.restore_conversation()
|
||||
|
||||
if gajim.awaiting_events[self.account].has_key(self.contact.jid):
|
||||
self.read_queue()
|
||||
|
||||
def _on_avatar_eventbox_enter_notify_event(self, widget, event):
|
||||
'''we enter the eventbox area so we under conditions add a timeout
|
||||
to show a bigger avatar after 0.5 sec'''
|
||||
jid = self.contact.jid
|
||||
real_jid = gajim.get_real_jid_from_fjid(self.account, jid)
|
||||
if not real_jid: # this can happend if we're in a moderate room
|
||||
return
|
||||
avatar_pixbuf = gtkgui_helpers.get_avatar_pixbuf_from_cache(real_jid)
|
||||
if avatar_pixbuf in ('ask', None):
|
||||
return
|
||||
avatar_w = avatar_pixbuf.get_width()
|
||||
avatar_h = avatar_pixbuf.get_height()
|
||||
|
||||
scaled_buf = self.xmls[jid].get_widget('avatar_image').get_pixbuf()
|
||||
scaled_buf_w = scaled_buf.get_width()
|
||||
scaled_buf_h = scaled_buf.get_height()
|
||||
|
||||
# do we have something bigger to show?
|
||||
if avatar_w > scaled_buf_w or avatar_h > scaled_buf_h:
|
||||
# wait for 0.5 sec in case we leave earlier
|
||||
self.show_bigger_avatar_timeout_id = gobject.timeout_add(500,
|
||||
self.show_bigger_avatar, widget)
|
||||
|
||||
def _on_avatar_eventbox_leave_notify_event(self, widget, event):
|
||||
'''we left the eventbox area that holds the avatar img'''
|
||||
# did we add a timeout? if yes remove it
|
||||
if self.show_bigger_avatar_timeout_id is not None:
|
||||
gobject.source_remove(self.show_bigger_avatar_timeout_id)
|
||||
|
||||
def save_var(self, jid):
|
||||
gpg_enabled = self.xmls[jid].get_widget('gpg_togglebutton').get_active()
|
||||
|
@ -949,8 +1008,7 @@ class ChatControl(ChatControlBase):
|
|||
|
||||
def send_chatstate(self, state, contact = None):
|
||||
''' sends OUR chatstate as STANDLONE chat state message (eg. no body)
|
||||
to jid only if new chatstate is different
|
||||
from the previous one
|
||||
to contact only if new chatstate is different from the previous one
|
||||
if jid is not specified, send to active tab'''
|
||||
# JEP 85 does not allow resending the same chatstate
|
||||
# this function checks for that and just returns so it's safe to call it
|
||||
|
@ -1058,7 +1116,7 @@ class ChatControl(ChatControlBase):
|
|||
# update chatstate in tab for this chat
|
||||
self.parent_win.redraw_tab(self.contact, self.contact.chatstate)
|
||||
|
||||
def on_banner_eventbox_button_press_event(self, widget, event):
|
||||
def _on_banner_eventbox_button_press_event(self, widget, event):
|
||||
'''If right-clicked, show popup'''
|
||||
if event.button == 3: # right click
|
||||
self.parent_win.popup_menu(event)
|
||||
|
@ -1109,3 +1167,117 @@ class ChatControl(ChatControlBase):
|
|||
if os.path.isfile(path): # is it file?
|
||||
ft = gajim.interface.instances['file_transfers']
|
||||
ft.send_file(self.account, self.contact, path)
|
||||
|
||||
def _on_message_tv_buffer_changed(self, textbuffer):
|
||||
self.kbd_activity_in_last_5_secs = True
|
||||
self.kbd_activity_in_last_30_secs = True
|
||||
if textbuffer.get_char_count():
|
||||
self.send_chatstate('composing', self.contact)
|
||||
else:
|
||||
self.send_chatstate('active', self.contact)
|
||||
|
||||
def restore_conversation(self):
|
||||
jid = self.contact.jid
|
||||
# don't restore lines if it's a transport
|
||||
if gajim.jid_is_transport(jid):
|
||||
return
|
||||
|
||||
# How many lines to restore and when to time them out
|
||||
restore_how_many = gajim.config.get('restore_lines')
|
||||
timeout = gajim.config.get('restore_timeout') # in minutes
|
||||
# number of messages that are in queue and are already logged
|
||||
pending_how_many = 0 # we want to avoid duplication
|
||||
|
||||
if gajim.awaiting_events[self.account].has_key(jid):
|
||||
events = gajim.awaiting_events[self.account][jid]
|
||||
for event in events:
|
||||
if event[0] == 'chat':
|
||||
pending_how_many += 1
|
||||
|
||||
rows = gajim.logger.get_last_conversation_lines(jid, restore_how_many,
|
||||
pending_how_many, timeout)
|
||||
|
||||
for row in rows: # row[0] time, row[1] has kind, row[2] the message
|
||||
if not row[2]: # message is empty, we don't print it
|
||||
continue
|
||||
if row[1] in (constants.KIND_CHAT_MSG_SENT,
|
||||
constants.KIND_SINGLE_MSG_SENT):
|
||||
kind = 'outgoing'
|
||||
name = gajim.nicks[self.account]
|
||||
elif row[1] in (constants.KIND_SINGLE_MSG_RECV,
|
||||
constants.KIND_CHAT_MSG_RECV):
|
||||
kind = 'incoming'
|
||||
name = self.contact.name
|
||||
|
||||
tim = time.localtime(float(row[0]))
|
||||
|
||||
ChatControlBase.print_conversation_line(self, row[2], kind, name, tim,
|
||||
['small'],
|
||||
['small', 'restored_message'],
|
||||
['small', 'restored_message'],
|
||||
False)
|
||||
if len(rows):
|
||||
self.conv_textview.print_empty_line()
|
||||
|
||||
def read_queue(self):
|
||||
'''read queue and print messages containted in it'''
|
||||
jid = self.contact.jid
|
||||
l = gajim.awaiting_events[self.account][jid]
|
||||
|
||||
# Is it a pm ?
|
||||
is_pm = False
|
||||
room_jid, nick = gajim.get_room_and_nick_from_fjid(jid)
|
||||
# FIXME: Accessing gc's, here?
|
||||
gcs = gajim.interface.instances[self.account]['gc']
|
||||
if gcs.has_key(room_jid):
|
||||
is_pm = True
|
||||
events_to_keep = []
|
||||
for event in l:
|
||||
typ = event[0]
|
||||
if typ != 'chat':
|
||||
events_to_keep.append(event)
|
||||
continue
|
||||
data = event[1]
|
||||
kind = data[2]
|
||||
if kind == 'error':
|
||||
kind = 'status'
|
||||
else:
|
||||
kind = 'print_queue'
|
||||
self.print_conversation(data[0], kind, tim = data[3],
|
||||
encrypted = data[4], subject = data[1])
|
||||
|
||||
# remove from gc nb_unread if it's pm or from roster
|
||||
if is_pm:
|
||||
gcs[room_jid].nb_unread[room_jid] -= 1
|
||||
else:
|
||||
gajim.interface.roster.nb_unread -= 1
|
||||
|
||||
if is_pm:
|
||||
gcs[room_jid].show_title()
|
||||
else:
|
||||
gajim.interface.roster.show_title()
|
||||
# Keep only non-messages events
|
||||
if len(events_to_keep):
|
||||
gajim.awaiting_events[self.account][jid] = events_to_keep
|
||||
else:
|
||||
del gajim.awaiting_events[self.account][jid]
|
||||
typ = 'chat' # Is it a normal chat or a pm ?
|
||||
# reset to status image in gc if it is a pm
|
||||
# FIXME: New data structure
|
||||
gcs = gajim.interface.instances[self.account]['gc']
|
||||
if gcs.has_key(room_jid):
|
||||
gcs[room_jid].draw_all_roster()
|
||||
typ = 'pm'
|
||||
|
||||
gajim.interface.roster.draw_contact(jid, self.account)
|
||||
if gajim.interface.systray_enabled:
|
||||
gajim.interface.systray.remove_jid(jid, self.account, typ)
|
||||
if (self.contact.show == 'offline' or self.contact.show == 'error'):
|
||||
showOffline = gajim.config.get('showoffline')
|
||||
if not showOffline and typ == 'chat' and \
|
||||
len(gajim.contacts[self.account][jid]) == 1:
|
||||
gajim.interface.roster.really_remove_contact(self.contact,
|
||||
self.account)
|
||||
elif typ == 'pm':
|
||||
gcs[room_jid].remove_contact(room_jid, nick)
|
||||
|
||||
|
|
|
@ -19081,7 +19081,6 @@ Maybe I'll refactor later</property>
|
|||
<property name="visible">True</property>
|
||||
<property name="visible_window">True</property>
|
||||
<property name="above_child">False</property>
|
||||
<signal name="button_press_event" handler="on_banner_eventbox_button_press_event" last_modification_time="Mon, 08 Aug 2005 10:39:20 GMT"/>
|
||||
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox3004">
|
||||
|
@ -19150,8 +19149,8 @@ Status message</property>
|
|||
<property name="visible">True</property>
|
||||
<property name="visible_window">False</property>
|
||||
<property name="above_child">False</property>
|
||||
<signal name="enter_notify_event" handler="on_avatar_eventbox_enter_notify_event" last_modification_time="Sun, 02 Oct 2005 22:58:47 GMT"/>
|
||||
<signal name="leave_notify_event" handler="on_avatar_eventbox_leave_notify_event" last_modification_time="Sun, 02 Oct 2005 22:58:52 GMT"/>
|
||||
<signal name="enter_notify_event" handler="_on_avatar_eventbox_enter_notify_event" last_modification_time="Mon, 02 Jan 2006 23:13:50 GMT"/>
|
||||
<signal name="leave_notify_event" handler="_on_avatar_eventbox_leave_notify_event" last_modification_time="Mon, 02 Jan 2006 23:13:55 GMT"/>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImage" id="avatar_image">
|
||||
|
|
|
@ -61,6 +61,12 @@ class MessageControl:
|
|||
or inactive (state is False)'''
|
||||
pass # Derived types MUST implement this method
|
||||
|
||||
def allow_shutdown(self):
|
||||
'''Called to check is a control is allowed to shutdown.
|
||||
If a control is not in a suitable shutdown state this method
|
||||
should return False'''
|
||||
# NOTE: Derived classes MAY implement this
|
||||
return True
|
||||
def shutdown(self):
|
||||
# NOTE: Derived classes MUST implement this
|
||||
assert(False)
|
||||
|
@ -92,12 +98,6 @@ class MessageControl:
|
|||
def set_compact_view(self, state):
|
||||
# NOTE: Derived classes MAY implement this
|
||||
self.compact_view_current = state
|
||||
def allow_shutdown(self):
|
||||
'''Called to check is a control is allowed to shutdown.
|
||||
If a control is not in a suitable shutdown state this method
|
||||
should return False'''
|
||||
# NOTE: Derived classes MAY implement this
|
||||
return True
|
||||
|
||||
def save_var(self, jid):
|
||||
'''When called, the derived type should serialize it's state in the form of a
|
||||
|
@ -107,6 +107,9 @@ class MessageControl:
|
|||
def load_var(self, jid, var):
|
||||
pass # Derived classes SHOULD implement this
|
||||
|
||||
def get_specific_unread(self, jid):
|
||||
return 0
|
||||
|
||||
def send_message(self, message, keyID = '', type = 'chat', chatstate = None):
|
||||
'''Send the given message to the active tab'''
|
||||
# refresh timers
|
||||
|
|
|
@ -20,6 +20,7 @@ import gobject
|
|||
import common
|
||||
import gtkgui_helpers
|
||||
import message_control
|
||||
from chat_control import ChatControlBase
|
||||
|
||||
from common import gajim
|
||||
|
||||
|
@ -47,7 +48,12 @@ class MessageWindow:
|
|||
# so this line adds that
|
||||
#self.window.set_events(gtk.gdk.POINTER_MOTION_MASK)
|
||||
self.alignment = self.xml.get_widget('alignment')
|
||||
|
||||
self.notebook = self.xml.get_widget('notebook')
|
||||
self.notebook.connect('switch-page',
|
||||
self._on_notebook_switch_page)
|
||||
self.notebook.connect('key-press-event',
|
||||
self._on_notebook_key_press)
|
||||
|
||||
# Remove the glade pages
|
||||
while self.notebook.get_n_pages():
|
||||
|
@ -72,10 +78,6 @@ class MessageWindow:
|
|||
else:
|
||||
self.notebook.set_show_tabs(False)
|
||||
self.notebook.set_show_border(gajim.config.get('tabs_border'))
|
||||
self.notebook.connect('switch-page',
|
||||
self._on_notebook_switch_page)
|
||||
self.notebook.connect('key-press-event',
|
||||
self._on_notebook_key_press)
|
||||
|
||||
# Connect event handling for this Window
|
||||
self.window.connect('delete-event', self._on_window_delete)
|
||||
|
@ -92,6 +94,8 @@ class MessageWindow:
|
|||
gajim.config.get('msgwin-width'),
|
||||
gajim.config.get('msgwin-height'))
|
||||
|
||||
self.window.show_all()
|
||||
|
||||
def _on_window_focus(self, widget, event):
|
||||
# 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)
|
||||
|
@ -144,13 +148,9 @@ class MessageWindow:
|
|||
self.alignment.set_property('top-padding', 2)
|
||||
|
||||
# Connect to keyboard events
|
||||
control.widget.connect('key_press_event',
|
||||
self.on_conversation_textview_key_press_event)
|
||||
# FIXME: need to get this event without access to message_textvier
|
||||
#control.widget.connect('mykeypress',
|
||||
# self.on_message_textview_mykeypress_event)
|
||||
control.widget.connect('key_press_event',
|
||||
self.on_message_textview_key_press_event)
|
||||
if isinstance(control, ChatControlBase):
|
||||
control.msg_textview.connect('mykeypress',
|
||||
self._on_message_textview_mykeypress_event)
|
||||
|
||||
# Add notebook page and connect up to the tab's close button
|
||||
xml = gtk.glade.XML(GTKGUI_GLADE, 'chat_tab_ebox', APP)
|
||||
|
@ -163,10 +163,11 @@ class MessageWindow:
|
|||
|
||||
|
||||
self.redraw_tab(control.contact)
|
||||
self.show_title()
|
||||
control.draw_widgets()
|
||||
self.window.show_all()
|
||||
# NOTE: we do not call set_control_active(True) since we don't know whether
|
||||
# the tab is the active one.
|
||||
self.show_title()
|
||||
|
||||
def on_tab_eventbox_button_press_event(self, widget, event, child):
|
||||
if event.button == 3:
|
||||
|
@ -174,10 +175,8 @@ class MessageWindow:
|
|||
self.notebook.set_current_page(n)
|
||||
self.popup_menu(event)
|
||||
|
||||
def on_message_textview_mykeypress_event(self, widget, event_keyval,
|
||||
def _on_message_textview_mykeypress_event(self, widget, event_keyval,
|
||||
event_keymod):
|
||||
# FIXME: Not called yet
|
||||
print "MessageWindow.on_message_textview_mykeypress_event:", event
|
||||
# NOTE: handles mykeypress which is custom signal; see message_textview.py
|
||||
|
||||
# construct event instance from binding
|
||||
|
@ -186,26 +185,8 @@ class MessageWindow:
|
|||
event.state = event_keymod
|
||||
event.time = 0 # assign current time
|
||||
|
||||
if event.keyval == gtk.keysyms.ISO_Left_Tab: # SHIFT + TAB
|
||||
if event.state & gtk.gdk.CONTROL_MASK: # CTRL + SHIFT + TAB
|
||||
self.notebook.emit('key_press_event', event)
|
||||
if event.keyval == gtk.keysyms.Tab:
|
||||
if event.state & gtk.gdk.CONTROL_MASK: # CTRL + TAB
|
||||
self.notebook.emit('key_press_event', event)
|
||||
|
||||
def on_message_textview_key_press_event(self, widget, event):
|
||||
print "MessageWindow.on_message_textview_key_press_event:", event
|
||||
if event.keyval == gtk.keysyms.Page_Down: # PAGE DOWN
|
||||
if event.state & gtk.gdk.CONTROL_MASK: # CTRL + PAGE DOWN
|
||||
self.notebook.emit('key_press_event', event)
|
||||
elif event.keyval == gtk.keysyms.Page_Up: # PAGE UP
|
||||
if event.state & gtk.gdk.CONTROL_MASK: # CTRL + PAGE UP
|
||||
self.notebook.emit('key_press_event', event)
|
||||
|
||||
def on_conversation_textview_key_press_event(self, widget, event):
|
||||
'''Do not block these events and send them to the notebook'''
|
||||
print "MessageWindow.on_conversation_textview_key_press_event:", event
|
||||
if event.state & gtk.gdk.CONTROL_MASK:
|
||||
# Tab switch bindings
|
||||
if event.keyval == gtk.keysyms.Tab: # CTRL + TAB
|
||||
self.notebook.emit('key_press_event', event)
|
||||
elif event.keyval == gtk.keysyms.ISO_Left_Tab: # CTRL + SHIFT + TAB
|
||||
|
@ -283,6 +264,7 @@ class MessageWindow:
|
|||
self.show_title()
|
||||
|
||||
def redraw_tab(self, contact, chatstate = None):
|
||||
print self._controls
|
||||
ctl = self._controls[contact.jid]
|
||||
ctl.update_state()
|
||||
|
||||
|
@ -430,7 +412,7 @@ class MessageWindow:
|
|||
jid = ctl.contact.jid
|
||||
if jid != self.get_active_jid():
|
||||
item = gtk.ImageMenuItem(_('Switch to %s') %\
|
||||
self.names[jid])
|
||||
ctl.contact.name)
|
||||
img = gtk.image_new_from_stock(gtk.STOCK_JUMP_TO,
|
||||
gtk.ICON_SIZE_MENU)
|
||||
item.set_image(img)
|
||||
|
@ -450,24 +432,42 @@ class MessageWindow:
|
|||
new_ctl.set_control_active(True)
|
||||
|
||||
def _on_notebook_key_press(self, widget, event):
|
||||
print "MessageWindow._on_notebook_key_press 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)
|
||||
contact = ctl.contact
|
||||
jid = ctl.contact.jid
|
||||
|
||||
# MOD1 (ALT) mask
|
||||
if event.state & gtk.gdk.MOD1_MASK:
|
||||
# Tab switch bindings
|
||||
if event.keyval == gtk.keysyms.Right: # ALT + RIGHT
|
||||
new = self.notebook.get_current_page() + 1
|
||||
if new >= self.notebook.get_n_pages():
|
||||
new = 0
|
||||
self.notebook.set_current_page(new)
|
||||
elif event.keyval == gtk.keysyms.Left: # ALT + LEFT
|
||||
new = self.notebook.get_current_page() - 1
|
||||
if new < 0:
|
||||
new = self.notebook.get_n_pages() - 1
|
||||
self.notebook.set_current_page(new)
|
||||
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))
|
||||
# Close tab bindings
|
||||
elif event.keyval == gtk.keysyms.Escape: # ESCAPE
|
||||
if ctl.type_id == message_control.TYPE_CHAT:
|
||||
self.remove_tab(contact)
|
||||
elif event.keyval == gtk.keysyms.F4 and \
|
||||
(event.state & gtk.gdk.CONTROL_MASK): # CTRL + F4
|
||||
self.remove_tab(jid)
|
||||
self.remove_tab(contact)
|
||||
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))
|
||||
self.remove_tab(contact)
|
||||
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)
|
||||
ctl.set_compact_view(not ctl.compact_view_current)
|
||||
|
||||
# FIXME: Move this to ChatControlBase
|
||||
elif event.keyval == gtk.keysyms.e and \
|
||||
(event.state & gtk.gdk.MOD1_MASK): # alt + E opens emoticons menu
|
||||
|
@ -500,60 +500,6 @@ class MessageWindow:
|
|||
# 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:
|
||||
|
@ -581,7 +527,6 @@ class MessageWindowMgr:
|
|||
|
||||
def _new_window(self):
|
||||
win = MessageWindow()
|
||||
win.window.show_all()
|
||||
# we track the lifetime of this window
|
||||
win.window.connect('destroy', self._on_window_destroy)
|
||||
return win
|
||||
|
|
Loading…
Add table
Reference in a new issue