diff --git a/src/chat_control.py b/src/chat_control.py index 4c766e8d7..7fd008e23 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -216,59 +216,6 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): return self.print_conversation(_('Error.'), 'status') - def handle_message_textview_mykey_press(self, widget, event_keyval, - event_keymod): - """ - Derives types SHOULD implement this, rather than connection to the even - itself - """ - event = Gdk.Event(Gdk.EventType.KEY_PRESS) - event.keyval = event_keyval - event.state = event_keymod - event.time = 0 - - _buffer = widget.get_buffer() - start, end = _buffer.get_bounds() - - if event.keyval -- Gdk.KEY_Tab: - position = _buffer.get_insert() - end = _buffer.get_iter_at_mark(position) - - text = _buffer.get_text(start, end, False) - - splitted = text.split() - - if (text.startswith(self.COMMAND_PREFIX) and not - text.startswith(self.COMMAND_PREFIX * 2) and len(splitted) == 1): - - text = splitted[0] - bare = text.lstrip(self.COMMAND_PREFIX) - - if len(text) == 1: - self.command_hits = [] - for command in self.list_commands(): - for name in command.names: - self.command_hits.append(name) - else: - if (self.last_key_tabs and self.command_hits and - self.command_hits[0].startswith(bare)): - self.command_hits.append(self.command_hits.pop(0)) - else: - self.command_hits = [] - for command in self.list_commands(): - for name in command.names: - if name.startswith(bare): - self.command_hits.append(name) - - if self.command_hits: - _buffer.delete(start, end) - _buffer.insert_at_cursor(self.COMMAND_PREFIX + self.command_hits[0] + ' ') - self.last_key_tabs = True - - return True - - self.last_key_tabs = False - def status_url_clicked(self, widget, url): helpers.launch_browser_mailer('url', url) @@ -401,9 +348,6 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): # add MessageTextView to UI and connect signals self.msg_scrolledwindow = self.xml.get_object('message_scrolledwindow') self.msg_textview = MessageTextView() - id_ = self.msg_textview.connect('mykeypress', - self._on_message_textview_mykeypress_event) - self.handlers[id_] = self.msg_textview self.msg_scrolledwindow.add(self.msg_textview) id_ = self.msg_textview.connect('key_press_event', self._on_message_textview_key_press_event) @@ -708,10 +652,43 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): if event.keyval == Gdk.KEY_Tab: # CTRL + TAB self.parent_win.move_to_next_unread_tab(True) return True -################################################################################ - # temporary solution instead Gtk.binding_entry_add_signal + message_buffer = self.msg_textview.get_buffer() event_state = event.get_state() + if event.keyval == Gdk.KEY_Tab: + start, end = message_buffer.get_bounds() + position = message_buffer.get_insert() + end = message_buffer.get_iter_at_mark(position) + text = message_buffer.get_text(start, end, False) + splitted = text.split() + if (text.startswith(self.COMMAND_PREFIX) and not + text.startswith(self.COMMAND_PREFIX * 2) and len(splitted) == 1): + text = splitted[0] + bare = text.lstrip(self.COMMAND_PREFIX) + if len(text) == 1: + self.command_hits = [] + for command in self.list_commands(): + for name in command.names: + self.command_hits.append(name) + else: + if (self.last_key_tabs and self.command_hits and + self.command_hits[0].startswith(bare)): + self.command_hits.append(self.command_hits.pop(0)) + else: + self.command_hits = [] + for command in self.list_commands(): + for name in command.names: + if name.startswith(bare): + self.command_hits.append(name) + + if self.command_hits: + message_buffer.delete(start, end) + message_buffer.insert_at_cursor(self.COMMAND_PREFIX + \ + self.command_hits[0] + ' ') + self.last_key_tabs = True + return True + if self.widget_name != 'groupchat_control': + self.last_key_tabs = False if event.keyval == Gdk.KEY_Up: if event_state & Gdk.ModifierType.CONTROL_MASK: if event_state & Gdk.ModifierType.SHIFT_MASK: # Ctrl+Shift+UP @@ -764,81 +741,9 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): if event_state & Gdk.ModifierType.CONTROL_MASK: self.msg_textview.undo() return True -################################################################################ + return False - 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 - """ - # NOTE: handles mykeypress which is custom signal connected to this - # CB in new_tab(). for this singal see message_textview.py - message_textview = widget - message_buffer = message_textview.get_buffer() - start_iter, end_iter = message_buffer.get_bounds() - message = message_buffer.get_text(start_iter, end_iter, False) - xhtml = self.msg_textview.get_xhtml() - - # construct event instance from binding - event = Gdk.Event(Gdk.EventType.KEY_PRESS) # it's always a key-press here - event.keyval = event_keyval - event.state = event_keymod - event.time = 0 # assign current time - - if event.keyval == Gdk.KEY_Up: - if event.get_state() == Gdk.ModifierType.CONTROL_MASK: # Ctrl+UP - self.scroll_messages('up', message_buffer, 'sent') - # Ctrl+Shift+UP - elif event.get_state() == (Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.SHIFT_MASK): - self.scroll_messages('up', message_buffer, 'received') - elif event.keyval == Gdk.KEY_Down: - if event.get_state() == Gdk.ModifierType.CONTROL_MASK: # Ctrl+Down - self.scroll_messages('down', message_buffer, 'sent') - # Ctrl+Shift+Down - elif event.get_state() == (Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.SHIFT_MASK): - self.scroll_messages('down', message_buffer, 'received') - elif event.keyval == Gdk.KEY_Return or \ - event.keyval == Gdk.KEY_KP_Enter: # ENTER - # NOTE: SHIFT + ENTER is not needed to be emulated as it is not - # binding at all (textview's default action is newline) - - if gajim.config.get('send_on_ctrl_enter'): - # here, we emulate GTK default action on ENTER (add new line) - # normally I would add in keypress but it gets way to complex - # to get instant result on changing this advanced setting - if event.get_state() == 0: # no ctrl, no shift just ENTER add newline - end_iter = message_buffer.get_end_iter() - message_buffer.insert_at_cursor('\n') - send_message = False - elif event.get_state() & Gdk.ModifierType.CONTROL_MASK: # CTRL + ENTER - send_message = True - else: # send on Enter, do newline on Ctrl Enter - if event.get_state() & Gdk.ModifierType.CONTROL_MASK: # Ctrl + ENTER - end_iter = message_buffer.get_end_iter() - message_buffer.insert_at_cursor('\n') - send_message = False - else: # ENTER - send_message = True - - if gajim.connections[self.account].connected < 2 and send_message: - # we are not connected - dialogs.ErrorDialog(_('A connection is not available'), - _('Your message can not be sent until you are connected.'), - transient_for=self.parent_win.window) - send_message = False - - if send_message: - self.send_message(message, xhtml=xhtml) # send the message - elif event.keyval == Gdk.KEY_z: # CTRL+z - if event.get_state() & Gdk.ModifierType.CONTROL_MASK: - self.msg_textview.undo() - else: - # Give the control itself a chance to process - self.handle_message_textview_mykey_press(widget, event_keyval, - event_keymod) - def _on_drag_data_received(self, widget, context, x, y, selection, target_type, timestamp): """ diff --git a/src/groupchat_control.py b/src/groupchat_control.py index 5e58fcbf5..5b1f06be2 100644 --- a/src/groupchat_control.py +++ b/src/groupchat_control.py @@ -2290,39 +2290,21 @@ class GroupchatControl(ChatControlBase): self.print_conversation(_('%(jid)s has been invited in this room') % { 'jid': contact_jid}, graphics=False) - def handle_message_textview_mykey_press(self, widget, event_keyval, - event_keymod): - # NOTE: handles mykeypress which is custom signal connected to this - # CB in new_room(). for this singal see message_textview.py - - if not widget.get_sensitive(): - # Textview is not sensitive, don't handle keypress - return - # construct event instance from binding - event = Gdk.Event(Gdk.EventType.KEY_PRESS) # it's always a key-press here - event.keyval = event_keyval - event.state = event_keymod - event.time = 0 # assign current time - - message_buffer = widget.get_buffer() - start_iter, end_iter = message_buffer.get_bounds() + def _on_message_textview_key_press_event(self, widget, event): + res = ChatControlBase._on_message_textview_key_press_event(self, widget, + event) + if res: + return True if event.keyval == Gdk.KEY_Tab: # TAB + message_buffer = widget.get_buffer() + start_iter, end_iter = message_buffer.get_bounds() cursor_position = message_buffer.get_insert() end_iter = message_buffer.get_iter_at_mark(cursor_position) - text = message_buffer.get_text(start_iter, end_iter, False).decode( - 'utf-8') + text = message_buffer.get_text(start_iter, end_iter, False) splitted_text = text.split() - # HACK: Not the best soltution. - if (text.startswith(self.COMMAND_PREFIX) and not - text.startswith(self.COMMAND_PREFIX * 2) and \ - len(splitted_text) == 1): - return super(GroupchatControl, self).\ - handle_message_textview_mykey_press(widget, event_keyval, - event_keymod) - # nick completion # check if tab is pressed with empty message if len(splitted_text): # if there are any words @@ -2340,7 +2322,7 @@ class GroupchatControl(ChatControlBase): with_refer_to_nick_char = True after_nick_len = len(gc_refer_to_nick_char + ' ') if len(self.nick_hits) and self.last_key_tabs and \ - text[:-after_nick_len].endswith(self.nick_hits[0]): + text[:-after_nick_len].endswith(self.nick_hits[0]): # we should cycle # Previous nick in list may had a space inside, so we check text # and not splitted_text and store it into 'begin' var @@ -2349,7 +2331,7 @@ class GroupchatControl(ChatControlBase): else: self.nick_hits = [] # clear the hit list list_nick = gajim.contacts.get_nick_list(self.account, - self.room_jid) + self.room_jid) list_nick.sort(key=str.lower) # case-insensitive sort if begin == '': # empty message, show lasts nicks that highlighted us first @@ -2362,7 +2344,7 @@ class GroupchatControl(ChatControlBase): for nick in list_nick: fjid = self.room_jid + '/' + nick if nick.lower().startswith(begin.lower()) and not \ - helpers.jid_is_blocked(self.account, fjid): + helpers.jid_is_blocked(self.account, fjid): # the word is the begining of a nick self.nick_hits.append(nick) if len(self.nick_hits): @@ -2374,17 +2356,17 @@ class GroupchatControl(ChatControlBase): add = ' ' start_iter = end_iter.copy() if self.last_key_tabs and with_refer_to_nick_char or (text and \ - text[-1] == ' '): + text[-1] == ' '): # have to accomodate for the added space from last # completion # gc_refer_to_nick_char may be more than one char! start_iter.backward_chars(len(begin) + len(add)) elif self.last_key_tabs and not gajim.config.get( - 'shell_like_completion'): + 'shell_like_completion'): # have to accomodate for the added space from last # completion start_iter.backward_chars(len(begin) + \ - len(gc_refer_to_nick_char)) + len(gc_refer_to_nick_char)) else: start_iter.backward_chars(len(begin)) diff --git a/src/message_textview.py b/src/message_textview.py index e3c084a70..e266830f5 100644 --- a/src/message_textview.py +++ b/src/message_textview.py @@ -38,12 +38,6 @@ class MessageTextView(Gtk.TextView): chat/groupchat windows """ UNDO_LIMIT = 20 - __gsignals__ = dict( - mykeypress = (GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.ACTION, - None, # return value - (int, Gdk.ModifierType ) # arguments - ) - ) def __init__(self): GObject.GObject.__init__(self) @@ -316,72 +310,3 @@ class MessageTextView(Gtk.TextView): return super(MessageTextView, self).get_sensitive() except AttributeError: return self.get_property('sensitive') - -# We register depending on keysym and modifier some bindings -# but we also pass those as param so we can construct fake Event -# Here we register bindings for those combinations that there is NO DEFAULT -# action to be done by gtk TextView. In such case we should not add a binding -# as the default action comes first and our bindings is useless. In that case -# we catch and do stuff before default action in normal key_press_event -# and we also return True there to stop the default action from running - -# CTRL + SHIFT + TAB -#Gtk.binding_entry_add_signal(MessageTextView, Gdk.KEY_ISO_Left_Tab, - #Gdk.ModifierType.CONTROL_MASK, 'mykeypress', int, Gdk.KEY_ISO_Left_Tab, - #Gdk.ModifierType, Gdk.ModifierType.CONTROL_MASK) - -## CTRL + TAB -#Gtk.binding_entry_add_signal(MessageTextView, Gdk.KEY_Tab, - #Gdk.ModifierType.CONTROL_MASK, 'mykeypress', int, Gdk.KEY_Tab, - #Gdk.ModifierType, Gdk.ModifierType.CONTROL_MASK) - -## TAB -#Gtk.binding_entry_add_signal(MessageTextView, Gdk.KEY_Tab, - #0, 'mykeypress', int, Gdk.KEY_Tab, Gdk.ModifierType, 0) - -## CTRL + UP -#Gtk.binding_entry_add_signal(MessageTextView, Gdk.KEY_Up, - #Gdk.ModifierType.CONTROL_MASK, 'mykeypress', int, Gdk.KEY_Up, - #Gdk.ModifierType, Gdk.ModifierType.CONTROL_MASK) - -## CTRL + DOWN -#Gtk.binding_entry_add_signal(MessageTextView, Gdk.KEY_Down, - #Gdk.ModifierType.CONTROL_MASK, 'mykeypress', int, Gdk.KEY_Down, - #Gdk.ModifierType, Gdk.ModifierType.CONTROL_MASK) - -## CTRL + SHIFT + UP -#Gtk.binding_entry_add_signal(MessageTextView, Gdk.KEY_Up, - #Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.SHIFT_MASK, 'mykeypress', int, - #Gdk.KEY_Up, Gdk.ModifierType, Gdk.ModifierType.CONTROL_MASK | - #Gdk.ModifierType.SHIFT_MASK) - -## CTRL + SHIFT + DOWN -#Gtk.binding_entry_add_signal(MessageTextView, Gdk.KEY_Down, - #Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.SHIFT_MASK, 'mykeypress', int, - #Gdk.KEY_Down, Gdk.ModifierType, Gdk.ModifierType.CONTROL_MASK | - #Gdk.ModifierType.SHIFT_MASK) - -## ENTER -#Gtk.binding_entry_add_signal(MessageTextView, Gdk.KEY_Return, - #0, 'mykeypress', int, Gdk.KEY_Return, - #Gdk.ModifierType, 0) - -## Ctrl + Enter -#Gtk.binding_entry_add_signal(MessageTextView, Gdk.KEY_Return, - #Gdk.ModifierType.CONTROL_MASK, 'mykeypress', int, Gdk.KEY_Return, - #Gdk.ModifierType, Gdk.ModifierType.CONTROL_MASK) - -## Keypad Enter -#Gtk.binding_entry_add_signal(MessageTextView, Gdk.KEY_KP_Enter, - #0, 'mykeypress', int, Gdk.KEY_KP_Enter, - #Gdk.ModifierType, 0) - -## Ctrl + Keypad Enter -#Gtk.binding_entry_add_signal(MessageTextView, Gdk.KEY_KP_Enter, - #Gdk.ModifierType.CONTROL_MASK, 'mykeypress', int, Gdk.KEY_KP_Enter, - #Gdk.ModifierType, Gdk.ModifierType.CONTROL_MASK) - -## Ctrl + z -#Gtk.binding_entry_add_signal(MessageTextView, Gdk.KEY_z, - #Gdk.ModifierType.CONTROL_MASK, 'mykeypress', int, Gdk.KEY_z, - #Gdk.ModifierType, Gdk.ModifierType.CONTROL_MASK) diff --git a/src/message_window.py b/src/message_window.py index 4347483d9..579252f55 100644 --- a/src/message_window.py +++ b/src/message_window.py @@ -329,27 +329,6 @@ class MessageWindow(object): ctrl = self._widget_to_control(child) GLib.idle_add(ctrl.msg_textview.grab_focus) - def _on_message_textview_mykeypress_event(self, widget, event_keyval, - event_keymod): - # NOTE: handles mykeypress which is custom signal; see message_textview.py - - # construct event instance from binding - event = Gdk.Event(Gdk.EventType.KEY_PRESS) # it's always a key-press here - event.keyval = event_keyval - event.state = event_keymod - event.time = 0 # assign current time - - if event.get_state() & Gdk.ModifierType.CONTROL_MASK: - # Tab switch bindings - if event.keyval == Gdk.KEY_Tab: # CTRL + TAB - self.move_to_next_unread_tab(True) - elif event.keyval == Gdk.KEY_ISO_Left_Tab: # CTRL + SHIFT + TAB - self.move_to_next_unread_tab(False) - elif event.keyval == Gdk.KEY_Page_Down: # CTRL + PAGE DOWN - self.notebook.event(event) - elif event.keyval == Gdk.KEY_Page_Up: # CTRL + PAGE UP - self.notebook.event(event) - def accel_group_func(self, accel_group, acceleratable, keyval, modifier): st = '1234567890' # alt+1 means the first tab (tab 0) control = self.get_active_control()