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-06-13 16:46:08 +02:00
import history_window
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 = { }
2005-06-21 00:22:54 +02:00
self . tagIn = { } # holds tag for nick that talks to us
self . tagOut = { } # holds tag for our nick
2005-06-17 17:31:21 +02:00
self . tagStatus = { } # holds status messages
2005-03-12 19:12:15 +01:00
self . nb_unread = { }
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-06-21 00:22:54 +02:00
self . childs = { } # holds the contents for every tab (VBox)
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-06-30 15:31:31 +02:00
# we check that on opening new windows
self . always_compact_view = gajim . config . get ( ' always_compact_view ' )
2005-06-07 18:25:55 +02:00
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 ' :
2005-08-03 01:03:21 +02:00
chat = _ ( ' Chat ' )
2005-03-16 21:48:56 +01:00
elif self . widget_name == ' groupchat_window ' :
2005-08-03 01:03:21 +02:00
chat = _ ( ' Group Chat ' )
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-08-03 01:03:21 +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-07-22 22:06:16 +02:00
2005-03-12 22:30:50 +01:00
child = self . childs [ jid ]
2005-08-04 11:42:34 +02:00
hb = self . notebook . get_tab_label ( child ) . get_children ( ) [ 0 ]
2005-05-04 18:22:07 +02:00
if self . widget_name == ' tabbed_chat_window ' :
2005-08-04 11:42:34 +02:00
nickname = hb . get_children ( ) [ 1 ]
2005-05-04 18:22:07 +02:00
elif self . widget_name == ' groupchat_window ' :
2005-08-04 11:42:34 +02:00
nickname = hb . get_children ( ) [ 0 ]
2005-05-04 18:22:07 +02:00
2005-06-02 18:30:18 +02:00
#FIXME: when gtk2.4 is OOOOLD do it via glade2.10+
2005-06-18 17:29:05 +02:00
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
2005-07-22 22:06:16 +02:00
2005-03-12 19:12:15 +01:00
def on_window_destroy ( self , widget , kind ) : #kind is 'chats' or 'gc'
2005-07-22 01:41:13 +02:00
''' clean self.plugin.windows[self.account][kind] '''
2005-03-12 19:12:15 +01:00
for jid in self . xmls :
2005-07-19 19:08:01 +02:00
windows = self . plugin . windows [ self . account ] [ kind ]
if kind == ' chats ' :
# send 'gone' chatstate to every tabbed chat tab
windows [ jid ] . send_chatstate ( ' gone ' )
2005-07-19 23:40:08 +02:00
gobject . source_remove ( self . possible_paused_timeout_id [ jid ] )
gobject . source_remove ( self . possible_inactive_timeout_id [ jid ] )
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-07-19 19:08:01 +02:00
del windows [ jid ]
2005-03-12 19:12:15 +01:00
if self . print_time_timeout_id . has_key ( jid ) :
gobject . source_remove ( self . print_time_timeout_id [ jid ] )
2005-07-19 19:08:01 +02:00
if windows . has_key ( ' tabbed ' ) :
del windows [ ' tabbed ' ]
2005-03-12 19:12:15 +01:00
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 )
2005-08-04 16:30:41 +02:00
def on_history_menuitem_clicked ( self , widget = None , jid = None ) :
""" When history menuitem is pressed: call history window """
if jid is None :
jid = self . get_active_jid ( )
2005-06-13 16:46:08 +02:00
if self . plugin . windows [ ' logs ' ] . has_key ( jid ) :
self . plugin . windows [ ' logs ' ] [ jid ] . window . present ( )
else :
2005-08-04 16:57:36 +02:00
self . plugin . windows [ ' logs ' ] [ jid ] = history_window . HistoryWindow (
self . plugin , jid , self . account )
2005-06-13 16:46:08 +02:00
2005-03-12 19:12:15 +01:00
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-08-03 17:42:44 +02:00
2005-06-30 15:31:31 +02:00
def on_compact_view_menuitem_activate ( self , widget ) :
isactive = widget . get_active ( )
self . set_compact_view ( isactive )
2005-08-04 16:57:36 +02:00
def on_actions_button_clicked ( self , widget ) :
''' popup action menu '''
menu = self . prepare_context_menu ( )
menu . popup ( None , None , None , 1 , 0 )
menu . show_all ( )
2005-06-30 15:31:31 +02:00
def remove_possible_switch_to_menuitems ( self , menu ) :
''' remove duplicate ' Switch to ' if they exist and return clean menu '''
childs = menu . get_children ( )
2005-08-04 14:46:31 +02:00
if self . widget_name == ' tabbed_chat_window ' :
jid = self . get_active_jid ( )
c = gajim . get_first_contact_instance_from_jid ( self . account , jid )
if _ ( ' not in the roster ' ) in c . groups : # for add_to_roster_menuitem
childs [ 5 ] . show ( )
childs [ 5 ] . set_no_show_all ( False )
else :
childs [ 5 ] . hide ( )
childs [ 5 ] . set_no_show_all ( True )
2005-08-05 16:15:31 +02:00
for child in childs [ 6 : ] : # start looping after Add to roster
2005-08-04 14:46:31 +02:00
grandchilds = child . get_children ( )
# check because seperator menuitem doesn't have childs
if len ( grandchilds ) :
accel_label = grandchilds [ 0 ]
if accel_label . get_text ( ) . startswith ( _ ( ' Switch to ' ) ) :
menu . remove ( child )
else : # remove the seperator
menu . remove ( child )
2005-06-30 15:31:31 +02:00
return menu
2005-08-04 16:57:36 +02:00
def prepare_context_menu ( self ) :
''' sets compact view menuitem active state
sets active and sensitivity state for toggle_gpg_menuitem
and remove possible ' Switch to ' menuitems '''
if self . widget_name == ' groupchat_window ' :
menu = self . gc_popup_menu
childs = menu . get_children ( )
# compact_view_menuitem
childs [ 5 ] . set_active ( self . compact_view_current_state )
elif self . widget_name == ' tabbed_chat_window ' :
menu = self . tabbed_chat_popup_menu
childs = menu . get_children ( )
# check if gpg capabitlies or else make gpg toggle insensitive
jid = self . get_active_jid ( )
gpg_btn = self . xmls [ jid ] . get_widget ( ' gpg_togglebutton ' )
isactive = gpg_btn . get_active ( )
issensitive = gpg_btn . get_property ( ' sensitive ' )
childs [ 3 ] . set_active ( isactive )
childs [ 3 ] . set_property ( ' sensitive ' , issensitive )
# compact_view_menuitem
childs [ 4 ] . set_active ( self . compact_view_current_state )
menu = self . remove_possible_switch_to_menuitems ( menu )
return menu
2005-06-22 21:39:19 +02:00
def on_chat_window_button_press_event ( self , widget , event ) :
''' If right-clicked, show popup '''
if event . button == 3 : # right click
2005-08-04 16:57:36 +02:00
menu = self . prepare_context_menu ( )
2005-06-22 21:39:19 +02:00
# common menuitems (tab switches)
if len ( self . xmls ) > 1 : # if there is more than one tab
2005-06-30 15:31:31 +02:00
menu . append ( gtk . MenuItem ( ) ) # seperator
2005-06-22 21:39:19 +02:00
for jid in self . xmls :
if jid != self . get_active_jid ( ) :
2005-07-01 17:15:35 +02:00
item = gtk . ImageMenuItem ( _ ( ' Switch to %s ' ) % self . names [ jid ] )
img = gtk . image_new_from_stock ( gtk . STOCK_JUMP_TO ,
2005-06-30 15:31:31 +02:00
gtk . ICON_SIZE_MENU )
2005-07-01 17:15:35 +02:00
item . set_image ( img )
2005-07-08 02:53:50 +02:00
item . connect ( ' activate ' , lambda obj , jid : self . set_active_tab (
2005-06-22 21:39:19 +02:00
jid ) , jid )
menu . append ( item )
# show the menu
menu . popup ( None , None , None , event . button , event . time )
menu . show_all ( )
2005-03-12 19:12:15 +01:00
def on_chat_notebook_switch_page ( self , notebook , page , page_num ) :
2005-07-22 20:10:28 +02:00
# get the index of the page and then the page that we're leaving
old_no = notebook . get_current_page ( )
old_child = notebook . get_nth_page ( old_no )
2005-03-12 19:12:15 +01:00
new_child = notebook . get_nth_page ( page_num )
2005-07-22 20:10:28 +02:00
old_jid = ' '
2005-03-12 19:12:15 +01:00
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
2005-07-22 20:10:28 +02:00
elif self . childs [ jid ] == old_child :
old_jid = jid
if old_jid != ' ' and new_jid != ' ' : # we found both jids
break # so stop looping
if self . widget_name == ' tabbed_chat_window ' :
# send chatstate inactive to the one we're leaving
# and active to the one we visit
2005-07-22 22:06:16 +02:00
if old_jid != ' ' :
self . send_chatstate ( ' inactive ' , old_jid )
2005-07-22 20:10:28 +02:00
self . send_chatstate ( ' active ' , new_jid )
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'
2005-07-22 01:41:13 +02:00
if len ( self . xmls ) == 1 : # only one tab so destroy window
# we check and possibly save positions here, because Ctrl+W, Escape
# etc.. call remove_tab so similar code in delete_event callbacks
# is not enough
if gajim . config . get ( ' saveposition ' ) :
if kind == ' chats ' :
x , y = self . window . get_position ( )
gajim . config . set ( ' chat-x-position ' , x )
gajim . config . set ( ' chat-y-position ' , y )
width , height = self . window . get_size ( )
gajim . config . set ( ' chat-width ' , width )
gajim . config . set ( ' chat-height ' , height )
elif kind == ' gc ' :
gajim . config . set ( ' gc-hpaned-position ' , self . hpaned_position )
x , y = self . window . get_position ( )
gajim . config . set ( ' gc-x-position ' , x )
gajim . config . set ( ' gc-y-position ' , y )
width , height = self . window . get_size ( )
gajim . config . set ( ' gc-width ' , width )
gajim . config . set ( ' gc-height ' , height )
2005-03-12 19:12:15 +01:00
self . window . destroy ( )
2005-08-03 13:36:00 +02:00
else :
if self . nb_unread [ jid ] > 0 :
self . nb_unread [ jid ] = 0
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 ]
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-03-12 19:12:15 +01:00
self . show_title ( )
2005-05-03 18:37:59 +02:00
2005-08-03 21:42:26 +02:00
if self . plugin . windows [ self . account ] [ kind ] . has_key ( jid ) :
del self . plugin . windows [ self . account ] [ kind ] [ jid ]
2005-04-22 02:02:42 +02:00
del self . nb_unread [ jid ]
2005-07-03 17:27:41 +02:00
del gajim . last_message_time [ self . account ] [ 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 ]
2005-08-03 13:36:00 +02:00
del self . childs [ jid ]
2005-04-22 02:02:42 +02:00
del self . tagIn [ jid ]
del self . tagOut [ jid ]
del self . tagStatus [ jid ]
2005-07-25 22:58:19 +02:00
def bring_scroll_to_end ( self , textview , diff_y = 0 ) :
''' scrolls to the end of textview if end is not visible '''
buffer = textview . get_buffer ( )
buffer . begin_user_action ( )
at_the_end = False
end_iter = buffer . get_end_iter ( )
end_rect = textview . get_iter_location ( end_iter )
visible_rect = textview . get_visible_rect ( )
# scroll only if expected end is not visible
if end_rect . y > = ( visible_rect . y + visible_rect . height + diff_y ) :
gobject . idle_add ( self . scroll_to_end_iter , textview )
def scroll_to_end_iter ( self , textview ) :
buffer = textview . get_buffer ( )
end_iter = buffer . get_end_iter ( )
textview . scroll_to_iter ( end_iter , 0 , False , 1 , 1 )
return False
2005-07-26 16:58:42 +02:00
def size_request ( self , message_textview , requisition , xml_top ) :
2005-07-25 16:27:48 +02:00
''' When message_textview changes its size. If the new height
will enlarge the window , enable the scrollbar automatic policy '''
2005-07-26 01:52:22 +02:00
if message_textview . window is None :
return
2005-07-26 16:58:42 +02:00
message_scrolledwindow = xml_top . get_widget ( ' message_scrolledwindow ' )
2005-07-25 16:27:48 +02:00
conversation_scrolledwindow = \
xml_top . get_widget ( ' conversation_scrolledwindow ' )
2005-07-25 22:58:19 +02:00
conversation_textview = \
xml_top . get_widget ( ' conversation_textview ' )
2005-07-26 01:52:22 +02:00
min_height = conversation_scrolledwindow . get_property ( ' height-request ' )
conversation_height = conversation_textview . window . get_size ( ) [ 1 ]
message_height = message_textview . window . get_size ( ) [ 1 ]
2005-07-26 16:58:42 +02:00
# new tab is not exposed yet
if conversation_height < 2 :
return
if conversation_height < min_height :
min_height = conversation_height
2005-07-26 01:52:22 +02:00
diff_y = message_height - requisition . height
2005-07-25 22:58:19 +02:00
if diff_y is not 0 :
2005-07-26 01:52:22 +02:00
if conversation_height + diff_y < min_height :
2005-07-26 16:58:42 +02:00
message_scrolledwindow . set_property ( ' vscrollbar-policy ' ,
gtk . POLICY_AUTOMATIC )
message_scrolledwindow . set_property ( ' hscrollbar-policy ' ,
gtk . POLICY_AUTOMATIC )
2005-07-26 01:52:22 +02:00
message_scrolledwindow . set_property ( ' height-request ' , message_height + \
conversation_height - min_height )
2005-07-25 22:58:19 +02:00
self . bring_scroll_to_end ( message_textview )
else :
2005-07-26 16:58:42 +02:00
message_scrolledwindow . set_property ( ' vscrollbar-policy ' ,
gtk . POLICY_NEVER )
message_scrolledwindow . set_property ( ' hscrollbar-policy ' ,
gtk . POLICY_NEVER )
2005-07-25 22:58:19 +02:00
message_scrolledwindow . set_property ( ' height-request ' , - 1 )
2005-07-26 16:58:42 +02:00
self . bring_scroll_to_end ( conversation_textview , diff_y - 18 )
2005-07-25 16:27:48 +02:00
return True
2005-08-04 11:42:34 +02:00
def on_tab_eventbox_button_press_event ( self , widget , event , child ) :
if event . button == 3 :
n = self . notebook . page_num ( child )
self . notebook . set_current_page ( n )
2005-03-12 19:12:15 +01:00
def new_tab ( self , jid ) :
2005-07-01 19:55:41 +02:00
#FIXME: text formating buttons will be hidden in 0.8 release
for w in [ ' bold_togglebutton ' , ' italic_togglebutton ' , ' underline_togglebutton ' ] :
self . xmls [ jid ] . get_widget ( w ) . set_no_show_all ( True )
2005-06-30 15:31:31 +02:00
self . set_compact_view ( self . always_compact_view )
2005-03-12 19:12:15 +01:00
self . nb_unread [ jid ] = 0
2005-07-03 17:27:41 +02:00
gajim . last_message_time [ self . account ] [ 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 )
2005-06-16 21:14:07 +02:00
tag = conversation_buffer . create_tag ( ' marked ' )
color = gajim . config . get ( ' markedmsgcolor ' )
tag . set_property ( ' foreground ' , color )
tag . set_property ( ' weight ' , pango . WEIGHT_BOLD )
2005-03-12 19:12:15 +01:00
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-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 ' :
2005-08-04 11:42:34 +02:00
xm = gtk . glade . XML ( GTKGUI_GLADE , ' chats_eventbox ' , APP )
tab_hbox = xm . get_widget ( ' chats_eventbox ' )
2005-05-04 18:22:07 +02:00
elif self . widget_name == ' groupchat_window ' :
2005-08-04 11:42:34 +02:00
xm = gtk . glade . XML ( GTKGUI_GLADE , ' gc_eventbox ' , APP )
tab_hbox = xm . get_widget ( ' gc_eventbox ' )
child = self . childs [ jid ]
2005-06-23 17:23:24 +02:00
xm . signal_connect ( ' on_close_button_clicked ' ,
self . on_close_button_clicked , jid )
2005-08-04 11:42:34 +02:00
xm . signal_connect ( ' on_tab_eventbox_button_press_event ' ,
self . on_tab_eventbox_button_press_event , child )
2005-06-03 17:37:17 +02:00
2005-06-23 23:16:10 +02:00
self . notebook . append_page ( child , tab_hbox )
2005-07-26 16:58:42 +02:00
message_textview = self . xmls [ jid ] . get_widget ( ' message_textview ' )
2005-07-25 16:27:48 +02:00
message_textview . connect ( ' size-request ' , self . size_request ,
2005-07-26 16:58:42 +02:00
self . xmls [ jid ] )
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 \
2005-06-30 15:31:31 +02:00
event . keyval == gtk . keysyms . L : # CTRL + L
message_textview = self . xmls [ jid ] . get_widget ( ' message_textview ' )
2005-06-11 19:55:31 +02:00
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-07-18 17:35:15 +02:00
elif event . keyval == gtk . keysyms . w and \
( event . state & gtk . gdk . CONTROL_MASK ) : # CTRL + W
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-06-22 23:58:45 +02:00
elif event . keyval == gtk . keysyms . c and \
2005-06-30 15:31:31 +02:00
( event . state & gtk . gdk . MOD1_MASK ) : # alt + C toggles compact view
self . set_compact_view ( not self . compact_view_current_state )
2005-04-12 17:30:09 +02:00
elif event . keyval == gtk . keysyms . Page_Down :
2005-06-27 10:37:02 +02:00
if 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 :
2005-06-27 10:37:02 +02:00
if 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-06-27 02:07:20 +02:00
self . notebook . prev_page ( )
else : # traverse for ever (eg. don't stop at first tab)
2005-04-12 17:30:09 +02:00
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-06-27 02:07:20 +02:00
self . notebook . next_page ( )
else : # traverse for ever (eg. don't stop at last tab)
2005-04-12 17:30:09 +02:00
self . notebook . set_current_page ( 0 )
2005-06-30 21:47:08 +02:00
elif ( event . keyval == gtk . keysyms . l or event . keyval == gtk . keysyms . L ) \
and event . state & gtk . gdk . CONTROL_MASK : # CTRL + L
conversation_textview = self . xmls [ jid ] . \
get_widget ( ' conversation_textview ' )
conversation_textview . get_buffer ( ) . set_text ( ' ' )
elif event . keyval == gtk . keysyms . v and 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 ) :
2005-07-19 22:17:28 +02:00
''' change the cursor to a hand when we are over a mail or an url '''
jid = self . get_active_jid ( )
2005-03-12 19:12:15 +01:00
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 )
2005-06-25 03:23:21 +02:00
def visit_url_from_menuitem ( self , widget , link ) :
''' basically it filters out the widget instance '''
self . plugin . launch_browser_mailer ( ' url ' , link )
2005-05-11 21:40:37 +02:00
def on_conversation_textview_populate_popup ( self , textview , menu ) :
2005-06-25 03:23:21 +02:00
''' we override the default context menu and we prepend Clear
and if we have sth selected we show a submenu with actions on the phrase
( see on_conversation_textview_button_press_event ) '''
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 )
2005-06-25 03:23:21 +02:00
if self . selected_phrase :
2005-06-25 10:12:59 +02:00
s = self . selected_phrase
2005-06-25 11:46:04 +02:00
if len ( s ) > 25 : #FIXME: do me with pango ellipseEND when gtk24 is OLD
2005-06-25 10:12:59 +02:00
s = s [ : 21 ] + ' ... '
item = gtk . MenuItem ( _ ( ' Actions for " %s " ' ) % s )
2005-06-25 03:23:21 +02:00
menu . prepend ( item )
submenu = gtk . Menu ( )
item . set_submenu ( submenu )
2005-06-30 15:31:31 +02:00
2005-07-17 21:45:32 +02:00
always_use_en = gajim . config . get ( ' always_english_wikipedia ' )
if always_use_en :
2005-08-05 16:55:42 +02:00
link = ' http://en.wikipedia.org/wiki/Special:Search?search= %s ' \
% self . selected_phrase
2005-07-17 21:45:32 +02:00
else :
2005-08-05 16:55:42 +02:00
link = ' http:// %s .wikipedia.org/wiki/Special:Search?search= %s ' \
2005-08-05 17:42:55 +02:00
% ( gajim . LANG , self . selected_phrase )
2005-07-18 18:40:12 +02:00
item = gtk . MenuItem ( _ ( ' Read _Wikipedia Article ' ) )
2005-06-25 03:23:21 +02:00
item . connect ( ' activate ' , self . visit_url_from_menuitem , link )
submenu . append ( item )
2005-07-18 18:40:12 +02:00
item = gtk . MenuItem ( _ ( ' Look it up in _Dictionary ' ) )
2005-08-05 17:42:55 +02:00
dict_link = gajim . config . get ( ' dictionary_url ' )
if dict_link == ' WIKTIONARY ' :
# special link (yeah undocumented but default)
always_use_en = gajim . config . get ( ' always_english_wiktionary ' )
if always_use_en :
link = ' http://en.wiktionary.org/wiki/Special:Search?search= %s ' \
% self . selected_phrase
else :
link = ' http:// %s .wiktionary.org/wiki/Special:Search?search= %s ' \
% ( gajim . LANG , self . selected_phrase )
item . connect ( ' activate ' , self . visit_url_from_menuitem , link )
else :
if dict_link . find ( ' %s ' ) == - 1 :
# we must have %s in the url if not WIKTIONARY
item = gtk . MenuItem ( _ ( ' Dictionary url is not WIKTIONARY or is missing an " %s " ' ) )
item . set_property ( ' sensitive ' , False )
else :
link = dict_link % self . selected_phrase
item . connect ( ' activate ' , self . visit_url_from_menuitem , link )
2005-06-25 03:23:21 +02:00
submenu . append ( item )
2005-08-05 17:42:55 +02:00
search_link = gajim . config . get ( ' search_engine ' )
if search_link . find ( ' %s ' ) == - 1 : # we must have %s in the url
item = gtk . MenuItem ( _ ( ' Web Search URL is missing an " %s " ' ) )
item . set_property ( ' sensitive ' , False )
else :
item = gtk . MenuItem ( _ ( ' Web _Search for it ' ) )
link = search_link % self . selected_phrase
item . connect ( ' activate ' , self . visit_url_from_menuitem , link )
2005-06-25 03:23:21 +02:00
submenu . append ( item )
2005-05-11 21:40:37 +02:00
menu . show_all ( )
2005-03-12 19:12:15 +01:00
def on_conversation_textview_button_press_event ( self , widget , event ) :
2005-06-25 03:23:21 +02:00
# If we clicked on a taged text do NOT open the standard popup menu
# if normal text check if we have sth selected
2005-04-22 02:02:42 +02:00
2005-06-25 03:23:21 +02:00
self . selected_phrase = ' '
if event . button != 3 : # if not right click
2005-04-22 02:02:42 +02:00
return False
win = widget . get_window ( gtk . TEXT_WINDOW_TEXT )
2005-06-25 03:23:21 +02:00
x , y = widget . window_to_buffer_coords ( gtk . TEXT_WINDOW_TEXT ,
2005-04-22 02:02:42 +02:00
int ( event . x ) , int ( event . y ) )
iter = widget . get_iter_at_location ( x , y )
tags = iter . get_tags ( )
2005-06-25 11:46:04 +02:00
if tags : # we clicked on sth special (it can be status message too)
2005-06-25 03:23:21 +02:00
for tag in tags :
tag_name = tag . get_property ( ' name ' )
if ' url ' in tag_name or ' mail ' in tag_name :
return True # we block normal context menu
2005-06-25 11:46:04 +02:00
2005-06-25 10:12:59 +02:00
# we check if sth was selected and if it was we assign
# selected_phrase variable
# so on_conversation_textview_populate_popup can use it
buffer = widget . get_buffer ( )
return_val = buffer . get_selection_bounds ( )
if return_val : # if sth was selected when we right-clicked
# get the selected text
start_sel , finish_sel = return_val [ 0 ] , return_val [ 1 ]
self . selected_phrase = buffer . get_text ( start_sel , finish_sel )
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 )
2005-06-30 18:45:14 +02:00
def on_start_chat_activate ( self , widget , jid ) :
self . plugin . roster . new_chat_from_jid ( self . account , jid )
def on_join_group_chat_menuitem_activate ( self , widget , jid ) :
2005-07-01 00:22:03 +02:00
room , server = jid . split ( ' @ ' )
2005-06-30 18:45:14 +02:00
if self . plugin . windows [ self . account ] . has_key ( ' join_gc ' ) :
instance = self . plugin . windows [ self . account ] [ ' join_gc ' ]
instance . xml . get_widget ( ' server_entry ' ) . set_text ( server )
instance . xml . get_widget ( ' room_entry ' ) . set_text ( room )
self . plugin . windows [ self . account ] [ ' join_gc ' ] . window . present ( )
else :
try :
self . plugin . windows [ self . account ] [ ' join_gc ' ] = \
dialogs . JoinGroupchatWindow ( self . plugin , self . account , server , room )
except RuntimeError :
pass
def on_add_to_roster_activate ( self , widget , jid ) :
dialogs . AddNewContactWindow ( self . plugin , self . account , jid )
2005-03-12 19:12:15 +01:00
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
2005-06-30 18:45:14 +02:00
childs [ 4 ] . hide ( ) # jid section seperator
childs [ 5 ] . hide ( ) # start chat
2005-07-01 12:34:19 +02:00
childs [ 6 ] . hide ( ) # join group chat
childs [ 7 ] . hide ( ) # add to roster
2005-06-30 18:45:14 +02:00
else : # It's a mail or a JID
2005-05-26 01:58:27 +02:00
childs [ 2 ] . connect ( ' activate ' , self . on_copy_link_activate , text )
childs [ 3 ] . connect ( ' activate ' , self . on_open_link_activate , kind , text )
2005-06-30 18:45:14 +02:00
childs [ 5 ] . connect ( ' activate ' , self . on_start_chat_activate , text )
childs [ 6 ] . connect ( ' activate ' ,
self . on_join_group_chat_menuitem_activate , text )
2005-07-05 01:16:50 +02:00
allow_add = False
2005-07-18 23:08:31 +02:00
if gajim . contacts [ self . account ] . has_key ( text ) :
c = gajim . contacts [ self . account ] [ text ] [ 0 ]
2005-07-07 19:33:15 +02:00
if _ ( ' not in the roster ' ) in c . groups :
2005-07-05 01:16:50 +02:00
allow_add = True
else : # he's not at all in the account contacts
allow_add = True
if allow_add :
childs [ 7 ] . connect ( ' activate ' , self . on_add_to_roster_activate , text )
childs [ 7 ] . show ( ) # show add to roster menuitem
else :
childs [ 7 ] . hide ( ) # hide add to roster menuitem
2005-07-02 20:32:22 +02:00
2005-05-26 01:58:27 +02:00
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 )
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-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-23 23:35:54 +02:00
buffer . insert_with_tags_by_name ( end_iter ,
text_before_special_text , * 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-06-18 17:57:06 +02:00
self . print_special_text ( special_text , other_tags , textview )
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-06-18 17:57:06 +02:00
def print_special_text ( self , special_text , other_tags , textview ) :
2005-03-16 18:22:20 +01:00
tags = [ ]
use_other_tags = True
2005-06-18 17:57:06 +02:00
buffer = textview . get_buffer ( )
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 ( )
2005-06-18 17:57:06 +02:00
anchor = buffer . create_child_anchor ( end_iter )
2005-06-19 15:12:50 +02:00
img = gtk . Image ( )
img . set_from_file ( self . plugin . emoticons [ emot_ascii ] )
img . show ( )
2005-06-25 03:23:21 +02:00
#add with possible animation
2005-06-19 15:12:50 +02:00
textview . add_child_at_anchor ( img , anchor )
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-06-23 23:35:54 +02:00
buffer . insert_with_tags_by_name ( end_iter , special_text , * 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 = [ ] ,
2005-07-05 23:35:37 +02:00
other_tags_for_text = [ ] , count_as_new = True , subject = None ) :
2005-07-08 02:53:50 +02:00
''' ' prints ' chat ' type messages '''
2005-04-22 02:02:42 +02:00
textview = self . xmls [ jid ] . get_widget ( ' conversation_textview ' )
buffer = textview . get_buffer ( )
2005-06-23 23:35:54 +02:00
buffer . begin_user_action ( )
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-07-17 21:45:32 +02:00
# FIXME: who gives us text that is not a string?
2005-03-16 18:22:20 +01:00
if not text :
text = ' '
2005-07-17 21:45:32 +02:00
2005-04-22 02:02:42 +02:00
if buffer . get_char_count ( ) > 0 :
buffer . insert ( end_iter , ' \n ' )
2005-07-22 12:29:54 +02:00
update_time = True
if kind == ' incoming_queue ' :
kind = ' incoming '
update_time = False
2005-07-17 21:45:32 +02:00
# print the time stamp
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-23 23:35:54 +02:00
buffer . insert_with_tags_by_name ( end_iter , tim_format + ' ' ,
* other_tags_for_time )
2005-06-03 23:52:36 +02:00
elif gajim . config . get ( ' print_time ' ) == ' sometimes ' :
2005-07-24 22:29:32 +02:00
every_foo_seconds = 60 * gajim . config . get (
' print_ichat_every_foo_minutes ' )
seconds_passed = time . time ( ) - self . last_time_printout [ jid ]
if seconds_passed > every_foo_seconds :
2005-06-03 23:52:36 +02:00
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-06-17 17:31:21 +02: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
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-23 23:35:54 +02:00
buffer . insert_with_tags_by_name ( end_iter , format , * 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
2005-07-08 02:53:50 +02:00
if subject : # if we have subject, show it too!
subject = _ ( ' Subject: %s \n ' ) % subject
end_iter = buffer . get_end_iter ( )
buffer . insert ( end_iter , subject )
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-23 23:35:54 +02:00
buffer . insert_with_tags_by_name ( end_iter , text [ index : ] , * text_tags )
2005-03-16 18:22:20 +01:00
#scroll to the end of the textview
end = False
2005-06-17 17:31:21 +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-06-23 23:35:54 +02:00
buffer . end_user_action ( )
2005-07-01 20:29:23 +02:00
if not count_as_new :
return
2005-07-22 12:29:54 +02:00
if kind == ' incoming ' and update_time :
2005-07-03 17:27:41 +02:00
gajim . last_message_time [ self . account ] [ jid ] = time . time ( )
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-06-19 15:12:50 +02:00
if self . widget_name == ' groupchat_window ' :
# Do not notify us for gc messages that are not for us
if text . find ( self . nicks [ jid ] ) == - 1 :
2005-06-19 13:20:06 +02:00
return
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 )
2005-07-23 18:08:33 +02:00
self . sent_history_pos [ jid ] = size + 1
2005-06-07 18:25:55 +02:00
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
2005-06-14 00:11:09 +02:00
def paint_banner ( self , jid ) :
theme = gajim . config . get ( ' roster_theme ' )
bgcolor = gajim . config . get_per ( ' themes ' , theme , ' bannerbgcolor ' )
textcolor = gajim . config . get_per ( ' themes ' , theme , ' bannertextcolor ' )
2005-06-30 15:31:31 +02:00
# the backgrounds are colored by using an eventbox by
# setting the bg color of the eventbox and the fg of the name_label
2005-06-14 00:11:09 +02:00
self . xmls [ jid ] . get_widget ( ' banner_eventbox ' ) . modify_bg (
gtk . STATE_NORMAL , gtk . gdk . color_parse ( bgcolor ) )
banner_name_label = self . xmls [ jid ] . get_widget ( ' banner_name_label ' )
banner_name_label . modify_fg ( gtk . STATE_NORMAL ,
gtk . gdk . color_parse ( textcolor ) )
2005-06-10 22:06:01 +02:00
def repaint_colored_widgets ( self ) :
""" Repaint widgets (banner) in the window/tab with theme color """
# iterate through tabs/windows and repaint
for jid in self . xmls :
2005-06-14 00:11:09 +02:00
self . paint_banner ( jid )
2005-06-22 23:58:45 +02:00
2005-06-30 15:31:31 +02:00
def set_compact_view ( self , state ) :
2005-08-04 16:57:36 +02:00
''' Toggle compact view. state is bool '''
2005-06-30 15:31:31 +02:00
self . compact_view_current_state = state
2005-06-22 23:58:45 +02:00
for jid in self . xmls :
2005-06-30 15:31:31 +02:00
if self . widget_name == ' tabbed_chat_window ' :
widgets = [
self . xmls [ jid ] . get_widget ( ' banner_eventbox ' ) ,
self . xmls [ jid ] . get_widget ( ' actions_hbox ' ) ,
]
elif self . widget_name == ' groupchat_window ' :
widgets = [ self . xmls [ jid ] . get_widget ( ' banner_eventbox ' ) ,
self . xmls [ jid ] . get_widget ( ' gc_actions_hbox ' ) ,
self . xmls [ jid ] . get_widget ( ' list_scrolledwindow ' ) ,
]
2005-06-22 23:58:45 +02:00
for widget in widgets :
if state :
widget . set_no_show_all ( True )
widget . hide ( )
else :
widget . set_no_show_all ( False )
2005-06-23 10:15:13 +02:00
widget . show_all ( )
2005-07-29 20:10:23 +02:00
# make the last message visible, when changing to "full view"
if not state :
conversation_textview = \
self . xmls [ jid ] . get_widget ( ' conversation_textview ' )
gobject . idle_add ( self . scroll_to_end_iter , conversation_textview )