2005-03-12 19:12:15 +01:00
## plugins/tabbed_chat_window.py
##
## Gajim Team:
## - Yann Le Boulanger <asterix@lagaule.org>
## - Vincent Hanquez <tab@snarc.org>
## - Nikos Kouremenos <kourem@gmail.com>
##
## Copyright (C) 2003-2005 Gajim Team
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
## by the Free Software Foundation; version 2 only.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
import gtk
import gtk . glade
import pango
import gobject
import time
2005-05-30 23:00:04 +02:00
import dialogs
2005-03-12 19:12:15 +01:00
2005-05-26 01:58:27 +02:00
try :
import gtkspell
except :
pass
2005-04-14 19:07:55 +02:00
from common import gajim
2005-03-12 19:12:15 +01:00
from common import i18n
_ = i18n . _
APP = i18n . APP
gtk . glade . bindtextdomain ( APP , i18n . DIR )
gtk . glade . textdomain ( APP )
2005-04-22 01:20:18 +02:00
GTKGUI_GLADE = ' gtkgui.glade '
2005-03-12 19:12:15 +01:00
2005-03-13 18:04:57 +01:00
class Chat :
""" Class for chat/groupchat windows """
2005-03-12 19:12:15 +01:00
def __init__ ( self , plugin , account , widget_name ) :
self . xml = gtk . glade . XML ( GTKGUI_GLADE , widget_name , APP )
2005-04-22 16:00:35 +02:00
self . window = self . xml . get_widget ( widget_name )
2005-06-07 23:28:21 +02:00
2005-04-22 16:00:35 +02:00
self . widget_name = widget_name
2005-03-12 19:12:15 +01:00
self . notebook = self . xml . get_widget ( ' chat_notebook ' )
self . notebook . remove_page ( 0 )
self . plugin = plugin
self . account = account
self . change_cursor = None
self . xmls = { }
self . tagIn = { }
self . tagOut = { }
self . tagStatus = { }
self . nb_unread = { }
self . last_message_time = { }
2005-06-03 23:52:36 +02:00
self . last_time_printout = { }
2005-03-12 19:12:15 +01:00
self . print_time_timeout_id = { }
2005-04-17 01:15:03 +02:00
self . names = { } # what is printed in the tab (eg. user.name)
2005-03-12 22:30:50 +01:00
self . childs = { }
2005-03-12 19:12:15 +01:00
2005-06-07 18:25:55 +02:00
#The following vars are used to keep history of user's messages
self . sent_history = { }
self . sent_history_pos = { }
self . typing_new = { }
self . orig_msg = { }
2005-03-12 19:12:15 +01:00
def update_tags ( self ) :
for jid in self . tagIn :
2005-04-22 02:02:42 +02:00
self . tagIn [ jid ] . set_property ( ' foreground ' ,
gajim . config . get ( ' inmsgcolor ' ) )
self . tagOut [ jid ] . set_property ( ' foreground ' ,
gajim . config . get ( ' outmsgcolor ' ) )
self . tagStatus [ jid ] . set_property ( ' foreground ' ,
gajim . config . get ( ' statusmsgcolor ' ) )
2005-03-12 19:12:15 +01:00
def update_print_time ( self ) :
2005-04-12 23:09:06 +02:00
if gajim . config . get ( ' print_time ' ) != ' sometimes ' :
2005-03-12 19:12:15 +01:00
list_jid = self . print_time_timeout_id . keys ( )
for jid in list_jid :
gobject . source_remove ( self . print_time_timeout_id [ jid ] )
del self . print_time_timeout_id [ jid ]
else :
for jid in self . xmls :
2005-04-22 02:02:42 +02:00
if self . print_time_timeout_id . has_key ( jid ) :
continue
self . print_time_timeout ( jid )
self . print_time_timeout_id [ jid ] = \
gobject . timeout_add ( 300000 ,
self . print_time_timeout ,
jid )
2005-03-12 19:12:15 +01:00
def show_title ( self ) :
""" redraw the window ' s title """
unread = 0
for jid in self . nb_unread :
unread + = self . nb_unread [ jid ]
start = " "
if unread > 1 :
2005-04-12 23:09:06 +02:00
start = ' [ ' + str ( unread ) + ' ] '
2005-03-12 19:12:15 +01:00
elif unread == 1 :
2005-04-12 23:09:06 +02:00
start = ' * '
2005-03-12 19:12:15 +01:00
chat = self . names [ jid ]
2005-04-22 02:02:42 +02:00
if len ( self . xmls ) > 1 : # if more than one tab in the same window
2005-03-16 21:48:56 +01:00
if self . widget_name == ' tabbed_chat_window ' :
chat = ' Chat '
elif self . widget_name == ' groupchat_window ' :
chat = ' Groupchat '
2005-04-22 02:02:42 +02:00
title = start + chat
2005-04-14 09:05:10 +02:00
if len ( gajim . connections ) > = 2 : # if we have 2 or more accounts
2005-05-21 17:19:58 +02:00
title = title + _ ( ' (account: ' ) + self . account + ' ) '
2005-04-22 02:02:42 +02:00
2005-03-16 02:27:37 +01:00
self . window . set_title ( title )
2005-03-12 19:12:15 +01:00
def redraw_tab ( self , jid ) :
""" redraw the label of the tab """
start = ' '
if self . nb_unread [ jid ] > 1 :
2005-04-12 23:09:06 +02:00
start = ' [ ' + str ( self . nb_unread [ jid ] ) + ' ] '
2005-03-12 19:12:15 +01:00
elif self . nb_unread [ jid ] == 1 :
2005-04-12 23:09:06 +02:00
start = ' * '
2005-05-03 18:37:59 +02:00
2005-03-12 22:30:50 +01:00
child = self . childs [ jid ]
2005-05-04 18:22:07 +02:00
if self . widget_name == ' tabbed_chat_window ' :
nickname = self . notebook . get_tab_label ( child ) . get_children ( ) [ 1 ]
elif self . widget_name == ' groupchat_window ' :
nickname = self . notebook . get_tab_label ( child ) . get_children ( ) [ 0 ]
2005-06-02 18:30:18 +02:00
#FIXME: when gtk2.4 is OOOOLD do it via glade2.10+
if gtk . pygtk_version > ( 2 , 6 , 0 ) and gtk . gtk_version > ( 2 , 6 , 0 ) :
2005-06-03 17:37:17 +02:00
nickname . set_max_width_chars ( 10 )
2005-06-02 18:30:18 +02:00
2005-05-03 18:37:59 +02:00
nickname . set_text ( start + self . names [ jid ] )
2005-03-12 19:12:15 +01:00
def on_window_destroy ( self , widget , kind ) : #kind is 'chats' or 'gc'
#clean self.plugin.windows[self.account][kind]
for jid in self . xmls :
2005-03-29 18:16:42 +02:00
if self . plugin . systray_enabled and self . nb_unread [ jid ] > 0 :
2005-03-21 23:06:34 +01:00
self . plugin . systray . remove_jid ( jid , self . account )
2005-03-12 19:12:15 +01:00
del self . plugin . windows [ self . account ] [ kind ] [ jid ]
if self . print_time_timeout_id . has_key ( jid ) :
gobject . source_remove ( self . print_time_timeout_id [ jid ] )
if self . plugin . windows [ self . account ] [ kind ] . has_key ( ' tabbed ' ) :
del self . plugin . windows [ self . account ] [ kind ] [ ' tabbed ' ]
def get_active_jid ( self ) :
2005-04-22 02:02:42 +02:00
notebook = self . notebook
active_child = notebook . get_nth_page ( notebook . get_current_page ( ) )
2005-03-12 19:12:15 +01:00
active_jid = ' '
for jid in self . xmls :
2005-03-12 22:30:50 +01:00
if self . childs [ jid ] == active_child :
2005-03-12 19:12:15 +01:00
active_jid = jid
break
return active_jid
def on_close_button_clicked ( self , button , jid ) :
2005-05-13 18:53:30 +02:00
""" When close button is pressed: close a tab """
2005-03-12 19:12:15 +01:00
self . remove_tab ( jid )
def on_chat_window_focus_in_event ( self , widget , event ) :
2005-05-26 01:58:27 +02:00
""" When window gets focus """
2005-03-12 19:12:15 +01:00
jid = self . get_active_jid ( )
2005-04-22 02:02:42 +02:00
textview = self . xmls [ jid ] . get_widget ( ' conversation_textview ' )
buffer = textview . get_buffer ( )
end_iter = buffer . get_end_iter ( )
end_rect = textview . get_iter_location ( end_iter )
visible_rect = textview . get_visible_rect ( )
2005-03-12 19:12:15 +01:00
if end_rect . y < = ( visible_rect . y + visible_rect . height ) :
#we are at the end
if self . nb_unread [ jid ] > 0 :
self . nb_unread [ jid ] = 0
self . redraw_tab ( jid )
self . show_title ( )
2005-03-29 18:16:42 +02:00
if self . plugin . systray_enabled :
self . plugin . systray . remove_jid ( jid , self . account )
2005-03-12 19:12:15 +01:00
def on_chat_notebook_switch_page ( self , notebook , page , page_num ) :
new_child = notebook . get_nth_page ( page_num )
new_jid = ' '
for jid in self . xmls :
2005-03-12 22:30:50 +01:00
if self . childs [ jid ] == new_child :
2005-03-12 19:12:15 +01:00
new_jid = jid
break
2005-04-22 02:02:42 +02:00
2005-05-13 18:53:30 +02:00
conversation_textview = self . xmls [ new_jid ] . get_widget (
' conversation_textview ' )
2005-03-12 19:12:15 +01:00
conversation_buffer = conversation_textview . get_buffer ( )
end_iter = conversation_buffer . get_end_iter ( )
end_rect = conversation_textview . get_iter_location ( end_iter )
visible_rect = conversation_textview . get_visible_rect ( )
if end_rect . y < = ( visible_rect . y + visible_rect . height ) :
#we are at the end
if self . nb_unread [ new_jid ] > 0 :
self . nb_unread [ new_jid ] = 0
self . redraw_tab ( new_jid )
self . show_title ( )
2005-03-29 18:16:42 +02:00
if self . plugin . systray_enabled :
self . plugin . systray . remove_jid ( new_jid , self . account )
2005-05-03 18:37:59 +02:00
conversation_textview . grab_focus ( )
2005-03-12 19:12:15 +01:00
2005-05-03 18:37:59 +02:00
def set_active_tab ( self , jid ) :
2005-05-04 18:40:41 +02:00
self . notebook . set_current_page ( self . notebook . page_num ( self . childs [ jid ] ) )
2005-03-12 19:12:15 +01:00
def remove_tab ( self , jid , kind ) : #kind is 'chats' or 'gc'
if len ( self . xmls ) == 1 :
self . window . destroy ( )
2005-04-22 02:02:42 +02:00
return
if self . nb_unread [ jid ] > 0 :
self . nb_unread [ jid ] = 0
2005-03-12 19:12:15 +01:00
self . show_title ( )
2005-04-22 02:02:42 +02:00
if self . plugin . systray_enabled :
self . plugin . systray . remove_jid ( jid , self . account )
if self . print_time_timeout_id . has_key ( jid ) :
gobject . source_remove ( self . print_time_timeout_id [ jid ] )
del self . print_time_timeout_id [ jid ]
2005-05-03 18:37:59 +02:00
self . notebook . remove_page ( self . notebook . page_num ( self . childs [ jid ] ) )
if len ( self . xmls ) == 2 :
# one that remains and one that we'll remove, 1 tab remains
self . notebook . set_show_tabs ( False )
2005-04-22 02:02:42 +02:00
del self . plugin . windows [ self . account ] [ kind ] [ jid ]
del self . nb_unread [ jid ]
del self . last_message_time [ jid ]
2005-06-03 23:52:36 +02:00
del self . last_time_printout [ jid ]
2005-04-22 02:02:42 +02:00
del self . xmls [ jid ]
del self . tagIn [ jid ]
del self . tagOut [ jid ]
del self . tagStatus [ jid ]
self . show_title ( )
2005-03-12 19:12:15 +01:00
def new_tab ( self , jid ) :
self . nb_unread [ jid ] = 0
self . last_message_time [ jid ] = 0
2005-06-03 23:52:36 +02:00
self . last_time_printout [ jid ] = float ( 0.0 )
2005-03-12 19:12:15 +01:00
2005-05-26 02:29:22 +02:00
if gajim . config . get ( ' use_speller ' ) and ' gtkspell ' in globals ( ) :
2005-05-26 01:58:27 +02:00
message_textview = self . xmls [ jid ] . get_widget ( ' message_textview ' )
2005-05-30 23:00:04 +02:00
try :
gtkspell . Spell ( message_textview )
except gobject . GError , msg :
2005-06-10 23:14:16 +02:00
dialogs . ErrorDialog ( str ( msg ) , _ ( ' If that is not your language for which you want to highlight misspelled words, then please set your $LANG as appropriate. Eg. for French do export LANG=fr_FR or export LANG=fr_FR.UTF-8 in ~/.bash_profile or to make it global in /etc/profile. \n \n Highlighting misspelled words feature will not be used ' ) ) . get_response ( )
2005-05-30 23:00:04 +02:00
gajim . config . set ( ' use_speller ' , False )
2005-05-26 01:58:27 +02:00
2005-05-13 18:53:30 +02:00
conversation_textview = self . xmls [ jid ] . get_widget (
' conversation_textview ' )
2005-03-12 19:12:15 +01:00
conversation_buffer = conversation_textview . get_buffer ( )
end_iter = conversation_buffer . get_end_iter ( )
2005-04-12 17:30:09 +02:00
conversation_buffer . create_mark ( ' end ' , end_iter , False )
2005-03-12 19:12:15 +01:00
self . tagIn [ jid ] = conversation_buffer . create_tag ( ' incoming ' )
2005-04-12 23:09:06 +02:00
color = gajim . config . get ( ' inmsgcolor ' )
2005-03-12 19:12:15 +01:00
self . tagIn [ jid ] . set_property ( ' foreground ' , color )
self . tagOut [ jid ] = conversation_buffer . create_tag ( ' outgoing ' )
2005-04-12 23:09:06 +02:00
color = gajim . config . get ( ' outmsgcolor ' )
2005-03-12 19:12:15 +01:00
self . tagOut [ jid ] . set_property ( ' foreground ' , color )
self . tagStatus [ jid ] = conversation_buffer . create_tag ( ' status ' )
2005-04-12 23:09:06 +02:00
color = gajim . config . get ( ' statusmsgcolor ' )
2005-03-12 19:12:15 +01:00
self . tagStatus [ jid ] . set_property ( ' foreground ' , color )
tag = conversation_buffer . create_tag ( ' time_sometimes ' )
tag . set_property ( ' foreground ' , ' #9e9e9e ' )
tag . set_property ( ' scale ' , pango . SCALE_SMALL )
tag . set_property ( ' justification ' , gtk . JUSTIFY_CENTER )
2005-06-02 21:38:22 +02:00
tag = conversation_buffer . create_tag ( ' small ' )
tag . set_property ( ' scale ' , pango . SCALE_SMALL )
2005-06-03 23:29:07 +02:00
tag = conversation_buffer . create_tag ( ' grey ' )
tag . set_property ( ' foreground ' , ' #9e9e9e ' )
2005-03-12 19:12:15 +01:00
tag = conversation_buffer . create_tag ( ' url ' )
tag . set_property ( ' foreground ' , ' #0000ff ' )
tag . set_property ( ' underline ' , pango . UNDERLINE_SINGLE )
tag . connect ( ' event ' , self . hyperlink_handler , ' url ' )
tag = conversation_buffer . create_tag ( ' mail ' )
tag . set_property ( ' foreground ' , ' #0000ff ' )
tag . set_property ( ' underline ' , pango . UNDERLINE_SINGLE )
tag . connect ( ' event ' , self . hyperlink_handler , ' mail ' )
tag = conversation_buffer . create_tag ( ' bold ' )
tag . set_property ( ' weight ' , pango . WEIGHT_BOLD )
tag = conversation_buffer . create_tag ( ' italic ' )
tag . set_property ( ' style ' , pango . STYLE_ITALIC )
tag = conversation_buffer . create_tag ( ' underline ' )
tag . set_property ( ' underline ' , pango . UNDERLINE_SINGLE )
self . xmls [ jid ] . signal_autoconnect ( self )
2005-05-03 18:37:59 +02:00
conversation_scrolledwindow = self . xmls [ jid ] . get_widget (
2005-05-13 18:53:30 +02:00
' conversation_scrolledwindow ' )
2005-05-03 18:37:59 +02:00
conversation_scrolledwindow . get_vadjustment ( ) . connect ( ' value-changed ' ,
2005-03-12 19:12:15 +01:00
self . on_conversation_vadjustment_value_changed )
2005-03-12 22:30:50 +01:00
child = self . childs [ jid ]
2005-05-04 18:22:07 +02:00
2005-03-12 19:12:15 +01:00
if len ( self . xmls ) > 1 :
self . notebook . set_show_tabs ( True )
2005-05-04 18:22:07 +02:00
if self . widget_name == ' tabbed_chat_window ' :
xm = gtk . glade . XML ( GTKGUI_GLADE , ' chat_tab_hbox ' , APP )
tab_hbox = xm . get_widget ( ' chat_tab_hbox ' )
2005-06-07 18:52:24 +02:00
# user = self.plugin.roster.contacts[self.account][jid][0]
user = self . users [ jid ]
2005-06-03 17:37:17 +02:00
gtklabel = gtk . Label ( user . name )
gtklabel . set_property ( ' xalign ' , 0 )
2005-05-04 18:22:07 +02:00
elif self . widget_name == ' groupchat_window ' :
xm = gtk . glade . XML ( GTKGUI_GLADE , ' groupchat_tab_hbox ' , APP )
tab_hbox = xm . get_widget ( ' groupchat_tab_hbox ' )
2005-06-03 17:37:17 +02:00
gtklabel = gtk . Label ( jid . split ( ' @ ' ) [ 0 ] )
gtklabel . set_property ( ' xalign ' , 0 )
2005-05-04 18:22:07 +02:00
xm . signal_connect ( ' on_close_button_clicked ' ,
2005-03-12 22:30:50 +01:00
self . on_close_button_clicked , jid )
2005-06-03 17:37:17 +02:00
self . notebook . append_page_menu ( child , tab_hbox , gtklabel )
2005-03-12 22:30:50 +01:00
2005-06-07 18:25:55 +02:00
#init new sent history for this conversation
self . sent_history [ jid ] = [ ]
self . sent_history_pos [ jid ] = 0
self . typing_new [ jid ] = True
self . orig_msg [ jid ] = ' '
2005-03-12 19:12:15 +01:00
self . show_title ( )
2005-03-31 17:03:07 +02:00
def on_conversation_textview_key_press_event ( self , widget , event ) :
2005-04-12 17:30:09 +02:00
""" Do not block these events and send them to the notebook """
2005-05-15 22:58:04 +02:00
if event . state & gtk . gdk . CONTROL_MASK :
2005-04-12 17:30:09 +02:00
if event . keyval == gtk . keysyms . Tab : # CTRL + TAB
2005-03-31 17:03:07 +02:00
self . notebook . emit ( ' key_press_event ' , event )
2005-05-15 22:58:04 +02:00
elif event . keyval == gtk . keysyms . ISO_Left_Tab : # CTRL + SHIFT + TAB
self . notebook . emit ( ' key_press_event ' , event )
2005-04-12 17:30:09 +02:00
elif event . keyval == gtk . keysyms . Page_Down : # CTRL + PAGE DOWN
self . notebook . emit ( ' key_press_event ' , event )
elif event . keyval == gtk . keysyms . Page_Up : # CTRL + PAGE UP
self . notebook . emit ( ' key_press_event ' , event )
2005-06-11 19:55:31 +02:00
elif event . keyval == gtk . keysyms . l or \
event . keyval == gtk . keysyms . L : # CTRL + L
conversation_textview . get_buffer ( ) . set_text ( ' ' )
2005-04-21 00:56:33 +02:00
elif event . keyval == gtk . keysyms . v : # CTRL + V
2005-04-21 18:41:22 +02:00
jid = self . get_active_jid ( )
message_textview = self . xmls [ jid ] . get_widget ( ' message_textview ' )
if not message_textview . is_focus ( ) :
message_textview . grab_focus ( )
message_textview . emit ( ' key_press_event ' , event )
2005-04-12 17:30:09 +02:00
2005-03-12 22:30:50 +01:00
def on_chat_notebook_key_press_event ( self , widget , event ) :
2005-03-12 19:12:15 +01:00
st = ' 1234567890 ' # zero is here cause humans count from 1, pc from 0 :P
jid = self . get_active_jid ( )
2005-04-21 18:41:22 +02:00
if event . keyval == gtk . keysyms . Escape : # ESCAPE
if self . widget_name == ' tabbed_chat_window ' :
2005-04-21 00:56:33 +02:00
self . remove_tab ( jid )
2005-04-12 17:30:09 +02:00
elif event . keyval == gtk . keysyms . F4 and \
2005-05-30 23:00:04 +02:00
( event . state & gtk . gdk . CONTROL_MASK ) : # CTRL + F4
2005-04-12 17:30:09 +02:00
self . remove_tab ( jid )
2005-04-22 02:02:42 +02:00
elif event . string and event . string in st and \
2005-05-30 23:00:04 +02:00
( event . state & gtk . gdk . MOD1_MASK ) : # alt + 1,2,3..
2005-03-12 19:12:15 +01:00
self . notebook . set_current_page ( st . index ( event . string ) )
2005-04-12 17:30:09 +02:00
elif event . keyval == gtk . keysyms . Page_Down :
if event . state & gtk . gdk . CONTROL_MASK : # CTRL + PAGE DOWN
2005-03-12 19:12:15 +01:00
current = self . notebook . get_current_page ( )
if current > 0 :
self . notebook . set_current_page ( current - 1 )
2005-04-12 17:30:09 +02:00
elif event . state & gtk . gdk . SHIFT_MASK : # SHIFT + PAGE DOWN
2005-03-12 19:12:15 +01:00
conversation_textview = self . xmls [ jid ] . \
get_widget ( ' conversation_textview ' )
rect = conversation_textview . get_visible_rect ( )
iter = conversation_textview . get_iter_at_location ( rect . x , \
rect . y + rect . height )
conversation_textview . scroll_to_iter ( iter , 0.1 , True , 0 , 0 )
2005-04-12 17:30:09 +02:00
elif event . keyval == gtk . keysyms . Page_Up :
if event . state & gtk . gdk . CONTROL_MASK : # CTRL + PAGE UP
2005-03-12 19:12:15 +01:00
current = self . notebook . get_current_page ( )
if current < ( self . notebook . get_n_pages ( ) - 1 ) :
2005-04-22 01:20:18 +02:00
self . notebook . set_current_page ( current + 1 )
2005-04-12 17:30:09 +02:00
elif event . state & gtk . gdk . SHIFT_MASK : # SHIFT + PAGE UP
2005-03-12 19:12:15 +01:00
conversation_textview = self . xmls [ jid ] . \
get_widget ( ' conversation_textview ' )
rect = conversation_textview . get_visible_rect ( )
iter = conversation_textview . get_iter_at_location ( rect . x , rect . y )
conversation_textview . scroll_to_iter ( iter , 0.1 , True , 0 , 1 )
2005-04-12 17:30:09 +02:00
# or event.keyval == gtk.keysyms.KP_Up
elif event . keyval == gtk . keysyms . Up :
if event . state & gtk . gdk . SHIFT_MASK : # SHIFT + UP
2005-04-22 02:02:42 +02:00
conversation_scrolledwindow = self . xml . get_widget ( ' conversation_scrolledwindow ' )
conversation_scrolledwindow . emit ( ' scroll-child ' ,
2005-04-12 17:30:09 +02:00
gtk . SCROLL_PAGE_BACKWARD , False )
2005-05-15 22:58:04 +02:00
elif event . keyval == gtk . keysyms . ISO_Left_Tab : # SHIFT + TAB
2005-05-30 23:00:04 +02:00
if event . state & gtk . gdk . CONTROL_MASK : # CTRL + SHIFT + TAB
2005-04-12 17:30:09 +02:00
current = self . notebook . get_current_page ( )
if current > 0 :
2005-04-22 02:02:42 +02:00
self . notebook . set_current_page ( current - 1 )
2005-04-12 17:30:09 +02:00
else :
self . notebook . set_current_page ( self . notebook . get_n_pages ( ) - 1 )
2005-05-15 22:58:04 +02:00
elif event . keyval == gtk . keysyms . Tab : # TAB
if event . state & gtk . gdk . CONTROL_MASK : # CTRL + TAB
2005-04-12 17:30:09 +02:00
current = self . notebook . get_current_page ( )
if current < ( self . notebook . get_n_pages ( ) - 1 ) :
2005-04-22 01:20:18 +02:00
self . notebook . set_current_page ( current + 1 )
2005-04-12 17:30:09 +02:00
else :
self . notebook . set_current_page ( 0 )
2005-06-11 19:55:31 +02:00
elif event . keyval == gtk . keysyms . l or \
event . keyval == gtk . keysyms . L :
if event . state & gtk . gdk . CONTROL_MASK : # CTRL + L
conversation_textview = self . xmls [ jid ] . \
get_widget ( ' conversation_textview ' )
conversation_textview . get_buffer ( ) . set_text ( ' ' )
2005-05-12 23:39:20 +02:00
elif event . keyval == gtk . keysyms . v :
if event . state & gtk . gdk . CONTROL_MASK : # CTRL + V
jid = self . get_active_jid ( )
message_textview = self . xmls [ jid ] . get_widget ( ' message_textview ' )
if not message_textview . is_focus ( ) :
message_textview . grab_focus ( )
message_textview . emit ( ' key_press_event ' , event )
2005-05-30 23:00:04 +02:00
elif event . state & gtk . gdk . CONTROL_MASK or \
( event . keyval == gtk . keysyms . Control_L ) or \
( event . keyval == gtk . keysyms . Control_R ) :
2005-04-22 02:02:42 +02:00
# 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
2005-04-21 18:41:22 +02:00
pass
2005-03-12 19:12:15 +01:00
else : # it's a normal key press make sure message_textview has focus
message_textview = self . xmls [ jid ] . get_widget ( ' message_textview ' )
if not message_textview . is_focus ( ) :
message_textview . grab_focus ( )
2005-03-16 19:35:53 +01:00
message_textview . emit ( ' key_press_event ' , event )
2005-03-12 19:12:15 +01:00
def on_conversation_vadjustment_value_changed ( self , widget ) :
jid = self . get_active_jid ( )
if not self . nb_unread [ jid ] :
return
2005-04-22 02:02:42 +02:00
textview = self . xmls [ jid ] . get_widget ( ' conversation_textview ' )
buffer = textview . get_buffer ( )
end_iter = buffer . get_end_iter ( )
end_rect = textview . get_iter_location ( end_iter )
visible_rect = textview . get_visible_rect ( )
2005-03-12 19:12:15 +01:00
if end_rect . y < = ( visible_rect . y + visible_rect . height ) and \
2005-04-22 02:02:42 +02:00
self . window . is_active ( ) :
2005-03-12 19:12:15 +01:00
#we are at the end
self . nb_unread [ jid ] = 0
self . redraw_tab ( jid )
self . show_title ( )
2005-03-29 18:16:42 +02:00
if self . plugin . systray_enabled :
self . plugin . systray . remove_jid ( jid , self . account )
2005-03-12 19:12:15 +01:00
def on_conversation_textview_motion_notify_event ( self , widget , event ) :
""" change the cursor to a hand when we are on a mail or an url """
x , y , spam = widget . window . get_pointer ( )
x , y = widget . window_to_buffer_coords ( gtk . TEXT_WINDOW_TEXT , x , y )
tags = widget . get_iter_at_location ( x , y ) . get_tags ( )
if self . change_cursor :
2005-05-13 18:53:30 +02:00
widget . get_window ( gtk . TEXT_WINDOW_TEXT ) . set_cursor (
2005-03-12 19:12:15 +01:00
gtk . gdk . Cursor ( gtk . gdk . XTERM ) )
self . change_cursor = None
2005-04-22 02:02:42 +02:00
tag_table = widget . get_buffer ( ) . get_tag_table ( )
2005-03-12 19:12:15 +01:00
for tag in tags :
2005-04-22 22:48:04 +02:00
if tag == tag_table . lookup ( ' url ' ) or tag == tag_table . lookup ( ' mail ' ) :
2005-05-13 18:53:30 +02:00
widget . get_window ( gtk . TEXT_WINDOW_TEXT ) . set_cursor (
2005-03-12 19:12:15 +01:00
gtk . gdk . Cursor ( gtk . gdk . HAND2 ) )
self . change_cursor = tag
return False
2005-05-11 21:40:37 +02:00
def on_clear ( self , widget , textview ) :
2005-05-13 20:03:10 +02:00
''' clear text in the given textview '''
2005-05-11 21:40:37 +02:00
buffer = textview . get_buffer ( )
start , end = buffer . get_bounds ( )
buffer . delete ( start , end )
def on_conversation_textview_populate_popup ( self , textview , menu ) :
2005-05-12 20:40:42 +02:00
item = gtk . MenuItem ( ) # seperator
menu . prepend ( item )
2005-05-13 21:58:03 +02:00
item = gtk . ImageMenuItem ( gtk . STOCK_CLEAR )
2005-05-12 20:40:42 +02:00
menu . prepend ( item )
2005-05-11 21:40:37 +02:00
item . connect ( ' activate ' , self . on_clear , textview )
menu . show_all ( )
2005-03-12 19:12:15 +01:00
def on_conversation_textview_button_press_event ( self , widget , event ) :
2005-04-22 02:02:42 +02:00
# Do not open the standard popup menu, so we block right button
# click on a taged text
if event . button != 3 :
return False
win = widget . get_window ( gtk . TEXT_WINDOW_TEXT )
x , y = widget . window_to_buffer_coords ( gtk . TEXT_WINDOW_TEXT , \
int ( event . x ) , int ( event . y ) )
iter = widget . get_iter_at_location ( x , y )
tags = iter . get_tags ( )
if not tags :
return False
for tag in tags :
tag_name = tag . get_property ( ' name ' )
if ' url ' in tag_name or ' mail ' in tag_name :
return True
2005-03-12 19:12:15 +01:00
def print_time_timeout ( self , jid ) :
if not jid in self . xmls . keys ( ) :
2005-06-03 23:52:36 +02:00
return False
2005-04-12 23:09:06 +02:00
if gajim . config . get ( ' print_time ' ) == ' sometimes ' :
2005-04-22 02:02:42 +02:00
textview = self . xmls [ jid ] . get_widget ( ' conversation_textview ' )
buffer = textview . get_buffer ( )
end_iter = buffer . get_end_iter ( )
2005-03-12 19:12:15 +01:00
tim = time . localtime ( )
tim_format = time . strftime ( ' % H: % M ' , tim )
2005-04-22 02:02:42 +02:00
buffer . insert_with_tags_by_name ( end_iter ,
2005-05-13 20:03:10 +02:00
' \n ' + tim_format ,
2005-04-22 02:02:42 +02:00
' time_sometimes ' )
2005-03-12 19:12:15 +01:00
#scroll to the end of the textview
2005-04-22 02:02:42 +02:00
end_rect = textview . get_iter_location ( end_iter )
visible_rect = textview . get_visible_rect ( )
2005-03-12 19:12:15 +01:00
if end_rect . y < = ( visible_rect . y + visible_rect . height ) :
#we are at the end
2005-04-25 15:18:12 +02:00
self . scroll_to_end ( textview )
2005-06-03 23:52:36 +02:00
return True # loop again
2005-03-12 19:12:15 +01:00
if self . print_time_timeout_id . has_key ( jid ) :
del self . print_time_timeout_id [ jid ]
2005-06-03 23:52:36 +02:00
return False
2005-03-12 19:12:15 +01:00
2005-05-26 01:58:27 +02:00
def on_open_link_activate ( self , widget , kind , text ) :
2005-03-12 19:12:15 +01:00
self . plugin . launch_browser_mailer ( kind , text )
2005-05-26 01:58:27 +02:00
def on_copy_link_activate ( self , widget , text ) :
2005-03-12 19:12:15 +01:00
clip = gtk . clipboard_get ( )
clip . set_text ( text )
def make_link_menu ( self , event , kind , text ) :
2005-05-26 01:58:27 +02:00
xml = gtk . glade . XML ( GTKGUI_GLADE , ' chat_context_menu ' , APP )
menu = xml . get_widget ( ' chat_context_menu ' )
childs = menu . get_children ( )
if kind == ' url ' :
childs [ 0 ] . connect ( ' activate ' , self . on_copy_link_activate , text )
childs [ 1 ] . connect ( ' activate ' , self . on_open_link_activate , kind , text )
childs [ 2 ] . hide ( ) # copy mail address
childs [ 3 ] . hide ( ) # open mail composer
else : # It's a mail
childs [ 2 ] . connect ( ' activate ' , self . on_copy_link_activate , text )
childs [ 3 ] . connect ( ' activate ' , self . on_open_link_activate , kind , text )
childs [ 0 ] . hide ( ) # copy link location
childs [ 1 ] . hide ( ) # open link in browser
2005-03-12 19:12:15 +01:00
menu . popup ( None , None , None , event . button , event . time )
menu . reposition ( )
def hyperlink_handler ( self , texttag , widget , event , iter , kind ) :
2005-03-14 18:04:46 +01:00
if event . type == gtk . gdk . BUTTON_PRESS :
2005-03-12 19:12:15 +01:00
begin_iter = iter . copy ( )
#we get the begining of the tag
while not begin_iter . begins_tag ( texttag ) :
begin_iter . backward_char ( )
end_iter = iter . copy ( )
#we get the end of the tag
while not end_iter . ends_tag ( texttag ) :
end_iter . forward_char ( )
word = begin_iter . get_text ( end_iter )
2005-04-12 17:30:09 +02:00
if event . button == 3 : # right click
2005-03-12 19:12:15 +01:00
self . make_link_menu ( event , kind , word )
else :
#we launch the correct application
self . plugin . launch_browser_mailer ( kind , word )
2005-03-16 18:22:20 +01:00
def print_with_tag_list ( self , buffer , text , iter , tag_list ) :
begin_mark = buffer . create_mark ( ' begin_tag ' , iter , True )
buffer . insert ( iter , text )
begin_tagged = buffer . get_iter_at_mark ( begin_mark )
for tag in tag_list :
buffer . apply_tag_by_name ( tag , begin_tagged , iter )
buffer . delete_mark ( begin_mark )
2005-06-02 21:38:22 +02:00
def detect_and_print_special_text ( self , otext , jid , other_tags ) :
2005-04-22 02:02:42 +02:00
textview = self . xmls [ jid ] . get_widget ( ' conversation_textview ' )
buffer = textview . get_buffer ( )
2005-03-12 19:12:15 +01:00
2005-03-13 18:04:57 +01:00
start = 0
end = 0
index = 0
# basic: links + mail + formatting is always checked (we like that)
2005-04-12 23:09:06 +02:00
if gajim . config . get ( ' useemoticons ' ) : # search for emoticons & urls
2005-03-13 18:04:57 +01:00
iterator = self . plugin . emot_and_basic_re . finditer ( otext )
else : # search for just urls + mail + formatting
iterator = self . plugin . basic_pattern_re . finditer ( otext )
for match in iterator :
start , end = match . span ( )
special_text = otext [ start : end ]
if start != 0 :
text_before_special_text = otext [ index : start ]
2005-04-22 02:02:42 +02:00
end_iter = buffer . get_end_iter ( )
2005-06-02 21:38:22 +02:00
self . print_with_tag_list ( buffer , text_before_special_text ,
end_iter , other_tags )
2005-03-13 18:04:57 +01:00
index = end # update index
2005-03-13 23:03:14 +01:00
#now print it
2005-04-22 02:02:42 +02:00
self . print_special_text ( special_text , other_tags ,
buffer )
2005-03-13 18:04:57 +01:00
2005-03-16 18:22:20 +01:00
return index
2005-03-13 23:03:14 +01:00
2005-04-22 02:02:42 +02:00
def print_special_text ( self , special_text , other_tags , buffer ) :
2005-03-16 18:22:20 +01:00
tags = [ ]
use_other_tags = True
2005-03-17 01:53:13 +01:00
possible_emot_ascii_caps = special_text . upper ( ) # emoticons keys are CAPS
2005-03-13 23:03:14 +01:00
if possible_emot_ascii_caps in self . plugin . emoticons . keys ( ) :
#it's an emoticon
emot_ascii = possible_emot_ascii_caps
2005-04-22 02:02:42 +02:00
end_iter = buffer . get_end_iter ( )
buffer . insert_pixbuf ( end_iter ,
self . plugin . emoticons [ emot_ascii ] )
2005-03-13 23:03:14 +01:00
elif special_text . startswith ( ' mailto: ' ) :
#it's a mail
2005-03-16 18:22:20 +01:00
tags . append ( ' mail ' )
use_other_tags = False
2005-03-13 23:03:14 +01:00
elif self . plugin . sth_at_sth_dot_sth_re . match ( special_text ) :
#it's a mail
2005-03-16 18:22:20 +01:00
tags . append ( ' mail ' )
use_other_tags = False
2005-03-14 02:02:59 +01:00
elif special_text . startswith ( ' * ' ) : # it's a bold text
2005-03-16 18:22:20 +01:00
tags . append ( ' bold ' )
2005-03-14 02:02:59 +01:00
if special_text [ 1 ] == ' / ' : # it's also italic
2005-03-16 18:22:20 +01:00
tags . append ( ' italic ' )
2005-03-14 02:02:59 +01:00
special_text = special_text [ 2 : - 2 ] # remove */ /*
elif special_text [ 1 ] == ' _ ' : # it's also underlined
2005-03-16 18:22:20 +01:00
tags . append ( ' underline ' )
2005-03-14 02:02:59 +01:00
special_text = special_text [ 2 : - 2 ] # remove *_ _*
else :
special_text = special_text [ 1 : - 1 ] # remove * *
elif special_text . startswith ( ' / ' ) : # it's an italic text
2005-03-16 18:22:20 +01:00
tags . append ( ' italic ' )
2005-03-14 02:02:59 +01:00
if special_text [ 1 ] == ' * ' : # it's also bold
2005-03-16 18:22:20 +01:00
tags . append ( ' bold ' )
2005-03-14 02:02:59 +01:00
special_text = special_text [ 2 : - 2 ] # remove /* */
elif special_text [ 1 ] == ' _ ' : # it's also underlined
2005-03-16 18:22:20 +01:00
tags . append ( ' underline ' )
2005-03-14 02:02:59 +01:00
special_text = special_text [ 2 : - 2 ] # remove /_ _/
else :
special_text = special_text [ 1 : - 1 ] # remove / /
elif special_text . startswith ( ' _ ' ) : # it's an underlined text
2005-03-16 18:22:20 +01:00
tags . append ( ' underline ' )
2005-03-14 02:02:59 +01:00
if special_text [ 1 ] == ' * ' : # it's also bold
2005-03-16 18:22:20 +01:00
tags . append ( ' bold ' )
2005-03-14 02:02:59 +01:00
special_text = special_text [ 2 : - 2 ] # remove _* *_
elif special_text [ 1 ] == ' / ' : # it's also italic
2005-03-16 18:22:20 +01:00
tags . append ( ' italic ' )
2005-03-14 02:02:59 +01:00
special_text = special_text [ 2 : - 2 ] # remove _/ /_
else :
special_text = special_text [ 1 : - 1 ] # remove _ _
2005-03-13 23:03:14 +01:00
else :
#it's a url
2005-03-16 18:22:20 +01:00
tags . append ( ' url ' )
use_other_tags = False
if len ( tags ) > 0 :
2005-04-22 02:02:42 +02:00
end_iter = buffer . get_end_iter ( )
2005-03-16 18:22:20 +01:00
all_tags = tags [ : ]
if use_other_tags :
all_tags + = other_tags
2005-04-22 02:02:42 +02:00
self . print_with_tag_list ( buffer , special_text ,
end_iter , all_tags )
2005-03-13 23:03:14 +01:00
2005-04-12 17:30:09 +02:00
def scroll_to_end ( self , textview ) :
2005-04-25 15:18:12 +02:00
parent = textview . get_parent ( )
2005-04-12 17:30:09 +02:00
buffer = textview . get_buffer ( )
textview . scroll_to_mark ( buffer . get_mark ( ' end ' ) , 0 , True , 0 , 1 )
2005-04-25 15:18:12 +02:00
adjustment = parent . get_hadjustment ( )
adjustment . set_value ( 0 )
2005-04-12 17:30:09 +02:00
return False
2005-06-03 23:29:07 +02:00
def print_empty_line ( self , jid ) :
textview = self . xmls [ jid ] . get_widget ( ' conversation_textview ' )
buffer = textview . get_buffer ( )
end_iter = buffer . get_end_iter ( )
buffer . insert ( end_iter , ' \n ' )
2005-04-22 02:02:42 +02:00
def print_conversation_line ( self , text , jid , kind , name , tim ,
2005-06-02 21:38:22 +02:00
other_tags_for_name = [ ] , other_tags_for_time = [ ] ,
other_tags_for_text = [ ] ) :
2005-04-22 02:02:42 +02:00
textview = self . xmls [ jid ] . get_widget ( ' conversation_textview ' )
buffer = textview . get_buffer ( )
2005-04-12 17:30:09 +02:00
at_the_end = False
2005-04-22 02:02:42 +02:00
end_iter = buffer . get_end_iter ( )
end_rect = textview . get_iter_location ( end_iter )
visible_rect = textview . get_visible_rect ( )
2005-04-12 17:30:09 +02:00
if end_rect . y < = ( visible_rect . y + visible_rect . height ) :
at_the_end = True
2005-03-16 18:22:20 +01:00
if not text :
text = ' '
2005-04-22 02:02:42 +02:00
if buffer . get_char_count ( ) > 0 :
buffer . insert ( end_iter , ' \n ' )
2005-04-12 23:09:06 +02:00
if gajim . config . get ( ' print_time ' ) == ' always ' :
2005-03-16 18:22:20 +01:00
if not tim :
tim = time . localtime ( )
2005-04-24 02:20:40 +02:00
before_str = gajim . config . get ( ' before_time ' )
after_str = gajim . config . get ( ' after_time ' )
2005-04-24 11:45:11 +02:00
format = before_str + ' % H: % M: % S ' + after_str
2005-04-02 21:52:00 +02:00
tim_format = time . strftime ( format , tim )
2005-06-02 21:38:22 +02:00
self . print_with_tag_list ( buffer , tim_format + ' ' , end_iter ,
other_tags_for_time )
2005-06-03 23:52:36 +02:00
elif gajim . config . get ( ' print_time ' ) == ' sometimes ' :
if ( time . time ( ) - self . last_time_printout [ jid ] ) > ( 5 * 60 ) :
self . last_time_printout [ jid ] = time . time ( )
end_iter = buffer . get_end_iter ( )
tim = time . localtime ( )
tim_format = time . strftime ( ' % H: % M ' , tim )
buffer . insert_with_tags_by_name ( end_iter ,
tim_format + ' \n ' ,
' time_sometimes ' )
#scroll to the end of the textview
end_rect = textview . get_iter_location ( end_iter )
visible_rect = textview . get_visible_rect ( )
2005-03-16 18:22:20 +01:00
2005-06-02 21:38:22 +02:00
text_tags = other_tags_for_text [ : ]
2005-03-16 18:22:20 +01:00
if kind == ' status ' :
2005-06-02 21:38:22 +02:00
text_tags . append ( kind )
2005-05-09 12:46:40 +02:00
elif text . startswith ( ' /me ' ) or text . startswith ( ' /me \n ' ) :
2005-03-16 18:22:20 +01:00
text = name + text [ 3 : ]
2005-06-02 21:38:22 +02:00
text_tags . append ( kind )
2005-03-16 18:22:20 +01:00
if kind == ' incoming ' :
self . last_message_time [ jid ] = time . time ( )
2005-06-02 21:38:22 +02:00
if name and len ( text_tags ) == len ( other_tags_for_text ) :
# not status nor /me
name_tags = other_tags_for_name [ : ] #create a new list
name_tags . append ( kind )
2005-04-24 02:54:10 +02:00
before_str = gajim . config . get ( ' before_nickname ' )
after_str = gajim . config . get ( ' after_nickname ' )
format = before_str + name + after_str + ' '
2005-06-02 21:38:22 +02:00
self . print_with_tag_list ( buffer , format , end_iter , name_tags )
2005-03-16 18:22:20 +01:00
# detect urls formatting and if the user has it on emoticons
2005-06-02 21:38:22 +02:00
index = self . detect_and_print_special_text ( text , jid , text_tags )
2005-03-16 18:22:20 +01:00
# add the rest of text located in the index and after
2005-04-22 02:02:42 +02:00
end_iter = buffer . get_end_iter ( )
2005-06-02 21:38:22 +02:00
self . print_with_tag_list ( buffer , text [ index : ] , end_iter , text_tags )
2005-03-16 18:22:20 +01:00
#scroll to the end of the textview
end = False
2005-04-12 17:30:09 +02:00
if at_the_end or ( kind == ' outgoing ' ) :
2005-03-16 18:22:20 +01:00
#we are at the end or we are sending something
end = True
2005-04-12 17:30:09 +02:00
# We scroll to the end after the scrollbar has appeared
2005-05-15 00:24:14 +02:00
gobject . idle_add ( self . scroll_to_end , textview )
2005-05-30 23:00:04 +02:00
if ( jid != self . get_active_jid ( ) or \
not self . window . is_active ( ) or \
not end ) and kind == ' incoming ' :
2005-03-16 18:22:20 +01:00
self . nb_unread [ jid ] + = 1
2005-03-29 18:16:42 +02:00
if self . plugin . systray_enabled :
self . plugin . systray . add_jid ( jid , self . account )
2005-03-16 18:22:20 +01:00
self . redraw_tab ( jid )
self . show_title ( )
2005-06-07 18:25:55 +02:00
def save_sent_message ( self , jid , message ) :
#save the message, so user can scroll though the list with key up/down
size = len ( self . sent_history [ jid ] )
#we don't want size of the buffer to grow indefinately
max_size = gajim . config . get ( ' key_up_lines ' )
if size > = max_size :
for i in range ( 0 , size - 1 ) :
self . sent_history [ jid ] [ i ] = self . sent_history [ jid ] [ i + 1 ]
self . sent_history [ jid ] [ max_size - 1 ] = message
else :
self . sent_history [ jid ] . append ( message )
self . sent_history_pos [ jid ] = size + 1
self . typing_new [ jid ] = True
self . orig_msg [ jid ] = ' '
def sent_messages_scroll ( self , jid , direction , conv_buf ) :
size = len ( self . sent_history [ jid ] )
if direction == ' up ' :
if self . sent_history_pos [ jid ] == 0 :
return
if self . typing_new [ jid ] :
#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 [ jid ] = conv_buf . get_text ( start_iter , end_iter , 0 )
self . typing_new [ jid ] = False
self . sent_history_pos [ jid ] = self . sent_history_pos [ jid ] - 1
conv_buf . set_text ( self . sent_history [ jid ] [ self . sent_history_pos [ jid ] ] )
elif direction == ' down ' :
if self . sent_history_pos [ jid ] > = size - 1 :
conv_buf . set_text ( self . orig_msg [ jid ] ) ;
self . typing_new [ jid ] = True
self . sent_history_pos [ jid ] = size
return
self . sent_history_pos [ jid ] = self . sent_history_pos [ jid ] + 1
conv_buf . set_text ( self . sent_history [ jid ] [ self . sent_history_pos [ jid ] ] )
2005-06-10 22:06:01 +02:00
def repaint_colored_widgets ( self ) :
""" Repaint widgets (banner) in the window/tab with theme color """
# get the bg color of the bar from the current theme colors
2005-06-10 22:13:37 +02:00
bgcolor = gajim . config . get ( ' accountbgcolor ' ) #FIXME: use uniq color
2005-06-10 22:06:01 +02:00
# iterate through tabs/windows and repaint
for jid in self . xmls :
2005-06-11 00:45:50 +02:00
self . xmls [ jid ] . get_widget ( ' banner_eventbox ' ) . modify_bg (
2005-06-10 22:13:37 +02:00
gtk . STATE_NORMAL , gtk . gdk . color_parse ( bgcolor ) )