More groupchat goodness

This commit is contained in:
Travis Shirk 2006-01-06 06:59:55 +00:00
parent 58f2d03dd3
commit 2a5b0afc44
9 changed files with 510 additions and 165 deletions

View File

@ -281,18 +281,16 @@ class ChatControlBase(MessageControl):
def _process_command(self, message): def _process_command(self, message):
if not message: if not message:
return False return False
if message == '/clear': if message == '/clear':
self.conv_textview.clear() # clear conversation self.conv_textview.clear() # clear conversation
# FIXME: Need this function
self.clear(self.msg_textview) # clear message textview too self.clear(self.msg_textview) # clear message textview too
return True return True
elif message == '/compact': elif message == '/compact':
self.set_compact_view(not self.compact_view_current) self.set_compact_view(not self.compact_view_current)
# FIXME: Need this function
self.clear(self.msg_textview) self.clear(self.msg_textview)
return True return True
else: return False
return False
def send_message(self, message, keyID = '', type = 'chat', chatstate = None): def send_message(self, message, keyID = '', type = 'chat', chatstate = None):
'''Send the given message to the active tab''' '''Send the given message to the active tab'''
@ -308,19 +306,6 @@ class ChatControlBase(MessageControl):
# Clear msg input # Clear msg input
message_buffer = self.msg_textview.get_buffer() message_buffer = self.msg_textview.get_buffer()
message_buffer.set_text('') # clear message buffer (and tv of course) message_buffer.set_text('') # clear message buffer (and tv of course)
# FIXME GC ONLY
# if contact is None:
# # contact was from pm in MUC
# room, nick = gajim.get_room_and_nick_from_fjid(jid)
# gc_contact = gajim.contacts.get_gc_contact(self.account, room, nick)
# if not gc_contact:
# # contact left the room, or we left the room
# dialogs.ErrorDialog(_('Sending private message failed'),
# #in second %s code replaces with nickname
# _('You are no longer in room "%s" or "%s" has left.') % \
# (room, nick)).get_response()
# return
def save_sent_message(self, message): def save_sent_message(self, message):
#save the message, so user can scroll though the list with key up/down #save the message, so user can scroll though the list with key up/down
@ -433,13 +418,6 @@ class ChatControlBase(MessageControl):
def update_tags(self): def update_tags(self):
self.conv_textview.update_tags() self.conv_textview.update_tags()
def set_compact_view(self, state):
'''Toggle compact view. state is bool'''
MessageControl.set_compact_view(self, state)
# make the last message visible, when changing to "full view"
if not state:
gobject.idle_add(self.conv_textview.scroll_to_end_iter)
def clear(self, tv): def clear(self, tv):
buffer = tv.get_buffer() buffer = tv.get_buffer()
start, end = buffer.get_bounds() start, end = buffer.get_bounds()
@ -559,10 +537,10 @@ class ChatControlBase(MessageControl):
if not self.nb_unread: if not self.nb_unread:
return return
jid = self.contact.jid jid = self.contact.jid
if self.conv_textview.at_the_end() and self.window.is_active(): if self.conv_textview.at_the_end() and self.parent_win.window.is_active():
#we are at the end #we are at the end
self.nb_unread = self.get_specific_unread() self.nb_unread = self.get_specific_unread()
self.parent_win.redraw_tab(jid) self.parent_win.redraw_tab(self.contact)
self.parent_win.show_title() self.parent_win.show_title()
if gajim.interface.systray_enabled: if gajim.interface.systray_enabled:
gajim.interface.systray.remove_jid(jid, self.account, gajim.interface.systray.remove_jid(jid, self.account,
@ -600,6 +578,55 @@ class ChatControlBase(MessageControl):
color.blue = int((color.blue * p) + (mask * (1 - p))) color.blue = int((color.blue * p) + (mask * (1 - p)))
return color return color
def remove_possible_switch_to_menuitems(self, menu):
''' remove duplicate 'Switch to' if they exist and return clean menu'''
childs = menu.get_children()
contact = self.parent_win.get_active_contact()
jid = contact.jid
if _('not in the roster') in contact.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)
if self.type_id == message_control.TYPE_GC:
start_removing_from = 7 # # this is from the seperator and after
else:
start_removing_from = 6 # this is from the seperator and after
for child in childs[start_removing_from:]:
menu.remove(child)
return menu
def set_compact_view(self, state):
'''Toggle compact view. state is bool'''
MessageControl.set_compact_view(self, state)
# make the last message visible, when changing to "full view"
if not state:
gobject.idle_add(self.conv_textview.scroll_to_end_iter)
if self.type_id == message_control.TYPE_GC:
widgets = [
self.xml.get_widget('banner_eventbox'),
self.xml.get_widget('gc_actions_hbox'),
self.xml.get_widget('list_scrolledwindow'),
]
else:
widgets = [
self.xml.get_widget('banner_eventbox'),
self.xml.get_widget('actions_hbox'),
]
for widget in widgets:
if state:
widget.set_no_show_all(True)
widget.hide()
else:
widget.set_no_show_all(False)
widget.show_all()
################################################################################ ################################################################################
class ChatControl(ChatControlBase): class ChatControl(ChatControlBase):
'''A control for standard 1-1 chat''' '''A control for standard 1-1 chat'''
@ -1004,28 +1031,6 @@ class ChatControl(ChatControlBase):
return tab_img return tab_img
def remove_possible_switch_to_menuitems(self, menu):
''' remove duplicate 'Switch to' if they exist and return clean menu'''
childs = menu.get_children()
contact = self.parent_win.get_active_contact()
jid = contact.jid
if _('not in the roster') in contact.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)
start_removing_from = 6 # this is from the seperator and after
# FIXME: GC only
# elif :
# start_removing_from = 7 # # this is from the seperator and after
for child in childs[start_removing_from:]:
menu.remove(child)
return menu
def prepare_context_menu(self): def prepare_context_menu(self):
'''sets compact view menuitem active state '''sets compact view menuitem active state
sets active and sensitivity state for toggle_gpg_menuitem sets active and sensitivity state for toggle_gpg_menuitem
@ -1051,28 +1056,6 @@ class ChatControl(ChatControlBase):
return menu return menu
def set_compact_view(self, state):
'''Toggle compact view. state is bool'''
ChatControlBase.set_compact_view(self, state)
widgets = [
self.xml.get_widget('banner_eventbox'),
self.xml.get_widget('actions_hbox'),
]
# FIXME GC only
# 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'),
# ]
for widget in widgets:
if state:
widget.set_no_show_all(True)
widget.hide()
else:
widget.set_no_show_all(False)
widget.show_all()
def send_chatstate(self, state, contact = None): def send_chatstate(self, state, contact = None):
''' sends OUR chatstate as STANDLONE chat state message (eg. no body) ''' sends OUR chatstate as STANDLONE chat state message (eg. no body)
to contact only if new chatstate is different from the previous one to contact only if new chatstate is different from the previous one
@ -1292,9 +1275,8 @@ class ChatControl(ChatControlBase):
# Is it a pm ? # Is it a pm ?
is_pm = False is_pm = False
room_jid, nick = gajim.get_room_and_nick_from_fjid(jid) room_jid, nick = gajim.get_room_and_nick_from_fjid(jid)
# FIXME: Accessing gc's, here? control = gajim.interface.msg_win_mgr.get_control(room_jid)
gcs = gajim.interface.instances[self.account]['gc'] if control.type_id == message_control.TYPE_GC:
if gcs.has_key(room_jid):
is_pm = True is_pm = True
events_to_keep = [] events_to_keep = []
for event in l: for event in l:
@ -1309,16 +1291,16 @@ class ChatControl(ChatControlBase):
else: else:
kind = 'print_queue' kind = 'print_queue'
self.print_conversation(data[0], kind, tim = data[3], self.print_conversation(data[0], kind, tim = data[3],
encrypted = data[4], subject = data[1]) encrypted = data[4], subject = data[1])
# remove from gc nb_unread if it's pm or from roster # remove from gc nb_unread if it's pm or from roster
if is_pm: if is_pm:
gcs[room_jid].nb_unread[room_jid] -= 1 control.nb_unread -= 1
else: else:
gajim.interface.roster.nb_unread -= 1 gajim.interface.roster.nb_unread -= 1
if is_pm: if is_pm:
gcs[room_jid].show_title() control.parent_win.show_title()
else: else:
gajim.interface.roster.show_title() gajim.interface.roster.show_title()
# Keep only non-messages events # Keep only non-messages events
@ -1327,12 +1309,10 @@ class ChatControl(ChatControlBase):
else: else:
del gajim.awaiting_events[self.account][jid] del gajim.awaiting_events[self.account][jid]
typ = 'chat' # Is it a normal chat or a pm ? typ = 'chat' # Is it a normal chat or a pm ?
# # reset to status image in gc if it is a pm # reset to status image in gc if it is a pm
# # FIXME: New data structure if is_pm:
# gcs = gajim.interface.instances[self.account]['gc'] control.draw_widgets()
# if gcs.has_key(room_jid): typ = 'pm'
# gcs[room_jid].draw_all_roster()
# typ = 'pm'
gajim.interface.roster.draw_contact(jid, self.account) gajim.interface.roster.draw_contact(jid, self.account)
if gajim.interface.systray_enabled: if gajim.interface.systray_enabled:
@ -1344,7 +1324,7 @@ class ChatControl(ChatControlBase):
gajim.interface.roster.really_remove_contact(self.contact, gajim.interface.roster.really_remove_contact(self.contact,
self.account) self.account)
elif typ == 'pm': elif typ == 'pm':
gcs[room_jid].remove_contact(room_jid, nick) control.remove_contact(nick)
def show_bigger_avatar(self, small_avatar): def show_bigger_avatar(self, small_avatar):
'''resizes the avatar, if needed, so it has at max half the screen size '''resizes the avatar, if needed, so it has at max half the screen size

View File

@ -145,8 +145,7 @@ def get_real_jid_from_fjid(account, fjid):
if not nick: # It's not a fake_jid, it is a real jid if not nick: # It's not a fake_jid, it is a real jid
return fjid # we return the real jid return fjid # we return the real jid
real_jid = fjid real_jid = fjid
gcs = interface.instances[account]['gc'] if interface.msg_win_mgr.get_control(room_jid):
if gcs.has_key(room_jid):
# It's a pm, so if we have real jid it's in contact.jid # It's a pm, so if we have real jid it's in contact.jid
gc_contact = contacts.get_gc_contact(account, room_jid, nick) gc_contact = contacts.get_gc_contact(account, room_jid, nick)
if not gc_contact: if not gc_contact:

View File

@ -36,6 +36,7 @@ import gtkgui_helpers
import dialogs import dialogs
import vcard import vcard
import cell_renderer_image import cell_renderer_image
import message_control
try: try:
import gtkspell import gtkspell

View File

@ -35,6 +35,8 @@ import pygtk
import message_control import message_control
from chat_control import ChatControlBase
from common import exceptions from common import exceptions
from common import i18n from common import i18n
i18n.init() i18n.init()
@ -176,10 +178,9 @@ class Interface:
title = data[1] title = data[1]
prompt = data[2] prompt = data[2]
proposed_nick = data[3] proposed_nick = data[3]
w = self.instances[account]['gc'] gc_control = gajim.interface.msg_win_mgr.get_control(room_jid)
if w.has_key(room_jid): # user may close the window before we are here if gc_control: # user may close the window before we are here
w[room_jid].show_change_nick_input_dialog(title, prompt, proposed_nick, gc_control.show_change_nick_input_dialog(title, prompt, proposed_nick)
room_jid)
def handle_event_http_auth(self, account, data): def handle_event_http_auth(self, account, data):
#('HTTP_AUTH', account, (method, url, transaction_id, iq_obj)) #('HTTP_AUTH', account, (method, url, transaction_id, iq_obj))
@ -219,9 +220,9 @@ class Interface:
(jid_from, file_props)) (jid_from, file_props))
conn.disconnect_transfer(file_props) conn.disconnect_transfer(file_props)
return return
if jid_from in self.instances[account]['gc']: ctl = gajim.interface.msg_win_mgr.get_control(jid_from)
self.instances[account]['gc'][jid_from].print_conversation( if ctl and ctl.type_id == message_control.TYPE_GC:
'Error %s: %s' % (array[2], array[1]), jid_from) ctl.print_conversation('Error %s: %s' % (array[2], array[1]))
def handle_event_con_type(self, account, con_type): def handle_event_con_type(self, account, con_type):
# ('CON_TYPE', account, con_type) which can be 'ssl', 'tls', 'tcp' # ('CON_TYPE', account, con_type) which can be 'ssl', 'tls', 'tcp'
@ -240,8 +241,9 @@ class Interface:
if not gajim.gc_connected.has_key(account): if not gajim.gc_connected.has_key(account):
return return
for room_jid in gajim.gc_connected[account]: for room_jid in gajim.gc_connected[account]:
if self.instances[account]['gc'].has_key(room_jid): gc_control = gajim.interface.msg_win_mgr.get_control(room_jid)
self.instances[account]['gc'][room_jid].got_disconnected(room_jid) if gc_control:
gc_control.got_disconnected()
else: else:
gobject.timeout_add(30000, self.allow_notif, account) gobject.timeout_add(30000, self.allow_notif, account)
model[self.roster.status_message_menuitem_iter][3] = True # sensitivity for this menuitem model[self.roster.status_message_menuitem_iter][3] = True # sensitivity for this menuitem
@ -476,34 +478,33 @@ class Interface:
fjid = array[0] fjid = array[0]
jids = fjid.split('/', 1) jids = fjid.split('/', 1)
jid = jids[0] jid = jids[0]
gcs = self.instances[account]['gc'] gcs = gajim.interface.msg_win_mgr.get_controls(message_window.TYPE_GC)
if jid in gcs: for gc_control in gcs:
if len(jids) > 1: # it's a pm if jid == gc_control.contact.jid:
nick = jids[1] if len(jids) > 1: # it's a pm
if not gajim.interface.msg_win_mgr.has_window(fjid): nick = jids[1]
gc = gcs[jid] if not gajim.interface.msg_win_mgr.get_control(fjid):
tv = gc.list_treeview[jid] tv = gc_control.list_treeview
model = tv.get_model() model = tv.get_model()
i = gc.get_contact_iter(jid, nick) i = gc_control.get_contact_iter(nick)
if i: if i:
show = model[i][3] show = model[i][3]
else: else:
show = 'offline' show = 'offline'
gc_c = gajim.contacts.create_gc_contact(room_jid = jid, gc_c = gajim.contacts.create_gc_contact(room_jid = jid,
name = nick, show = show) name = nick, show = show)
c = gajim.contacts.contact_from_gc_contct(c) c = gajim.contacts.contact_from_gc_contct(c)
self.roster.new_chat(c, account) self.roster.new_chat(c, account, private_chat = True)
ctl = gajim.interface.msg_win_mgr.get_control(fjid) ctl = gajim.interface.msg_win_mgr.get_control(fjid)
ctl.print_conversation('Error %s: %s' % (array[1], array[2]), ctl.print_conversation('Error %s: %s' % (array[1], array[2]),
'status') 'status')
return
gc_control.print_conversation('Error %s: %s' % (array[1], array[2]))
if gc_control.parent_win.get_active_jid() == jid:
gc_control.set_subject(gc_control.subject)
return return
# FIXME
gcs[jid].print_conversation('Error %s: %s' % \
(array[1], array[2]), jid)
if gcs[jid].get_active_jid() == jid:
gcs[jid].set_subject(jid,
gcs[jid].subjects[jid])
return
if jid.find('@') <= 0: if jid.find('@') <= 0:
jid = jid.replace('@', '') jid = jid.replace('@', '')
self.roster.on_message(jid, _('error while sending') + \ self.roster.on_message(jid, _('error while sending') + \
@ -723,12 +724,12 @@ class Interface:
#('GC_SUBJECT', account, (jid, subject)) #('GC_SUBJECT', account, (jid, subject))
jids = array[0].split('/', 1) jids = array[0].split('/', 1)
jid = jids[0] jid = jids[0]
if not self.instances[account]['gc'].has_key(jid): gc_control = gajim.interface.msg_win_mgr.get_control(jid)
if not gc_control:
return return
self.instances[account]['gc'][jid].set_subject(jid, array[1]) gc_control.set_subject(array[1])
if len(jids) > 1: if len(jids) > 1:
self.instances[account]['gc'][jid].print_conversation( gc_control.print_conversation('%s has set the subject to %s' % (jids[1], array[1]))
'%s has set the subject to %s' % (jids[1], array[1]), jid)
def handle_event_gc_config(self, account, array): def handle_event_gc_config(self, account, array):
#('GC_CONFIG', account, (jid, config)) config is a dict #('GC_CONFIG', account, (jid, config)) config is a dict
@ -953,14 +954,12 @@ class Interface:
def handle_event_signed_in(self, account, empty): def handle_event_signed_in(self, account, empty):
'''SIGNED_IN event is emitted when we sign in, so handle it''' '''SIGNED_IN event is emitted when we sign in, so handle it'''
# join already open groupchats # join already open groupchats
for room_jid in self.instances[account]['gc']: for gc_control in gajim.interface.msg_win_mgr.get_controls(message_control.TYPE_GC):
if room_jid == 'tabbed': room_jid = gc_control.contact.jid
continue
if gajim.gc_connected[account][room_jid]: if gajim.gc_connected[account][room_jid]:
continue continue
room, server = gajim.get_room_name_and_server_from_room_jid( room, server = gajim.get_room_name_and_server_from_room_jid(room_jid)
room_jid) nick = gc_control.nick
nick = self.instances[account]['gc'][room_jid].nicks[room_jid]
password = '' password = ''
if gajim.gc_passwords.has_key(room_jid): if gajim.gc_passwords.has_key(room_jid):
password = gajim.gc_passwords[room_jid] password = gajim.gc_passwords[room_jid]
@ -1242,17 +1241,16 @@ class Interface:
def handle_event(self, account, jid, typ): def handle_event(self, account, jid, typ):
w = None w = None
if typ == 'gc': if typ == message_control.TYPE_GC:
if wins['gc'].has_key(jid): w = gajim.interface.msg_win_mgr.get_window(jid)
w = wins['gc'][jid] elif typ == message_control.TYPE_CHAT:
elif typ == 'chat':
if gajim.interface.msg_win_mgr.has_window(jid): if gajim.interface.msg_win_mgr.has_window(jid):
w = gajim.interface.msg_win_mgr.get_window(jid) w = gajim.interface.msg_win_mgr.get_window(jid)
else: else:
contact = gajim.contacts.get_first_contact_from_jid(account, jid) contact = gajim.contacts.get_first_contact_from_jid(account, jid)
self.roster.new_chat(contact, account) self.roster.new_chat(contact, account)
w = gajim.interface.msg_win_mgr.get_window(jid) w = gajim.interface.msg_win_mgr.get_window(jid)
elif typ == 'pm': elif typ == message_control.TYPE_PM:
if gajim.interface.msg_win_mgr.has_window(jid): if gajim.interface.msg_win_mgr.has_window(jid):
w = gajim.interface.msg_win_mgr.get_window(jid) w = gajim.interface.msg_win_mgr.get_window(jid)
else: else:
@ -1266,7 +1264,7 @@ class Interface:
gc_contact = gajim.contacts.create_gc_contact(room_jid = room_jid, gc_contact = gajim.contacts.create_gc_contact(room_jid = room_jid,
name = nick, show = show) name = nick, show = show)
c = gajim.contacts.contact_from_gc_contct(gc_contact) c = gajim.contacts.contact_from_gc_contct(gc_contact)
self.roster.new_chat(c, account) self.roster.new_chat(c, account, private_chat = True)
w = gajim.interface.msg_win_mgr.get_window(jid) w = gajim.interface.msg_win_mgr.get_window(jid)
elif typ in ('normal', 'file-request', 'file-request-error', elif typ in ('normal', 'file-request', 'file-request-error',
'file-send-error', 'file-error', 'file-stopped', 'file-completed'): 'file-send-error', 'file-error', 'file-stopped', 'file-completed'):
@ -1278,8 +1276,11 @@ class Interface:
w.set_active_tab(jid) w.set_active_tab(jid)
w.window.present() w.window.present()
w.window.window.focus() w.window.window.focus()
tv = w.conversation_textviews[jid] ctl = w.get_control(jid)
tv.scroll_to_end() # Using isinstance here because we want to catch all derived types
if isinstance(ctl, ChatControlBase):
tv = ctl.conv_textview
tv.scroll_to_end()
def __init__(self): def __init__(self):
gajim.interface = self gajim.interface = self

View File

@ -63,6 +63,28 @@ class PrivateChatControl(ChatControl):
self.TYPE_ID = 'pm' self.TYPE_ID = 'pm'
self.display_name = _('Private chat') self.display_name = _('Private chat')
def send_message(self, message):
'''call this function to send our message'''
if not message:
return
# We need to make sure that we can still send through the room and that the
# recipient did not go away
contact = gajim.contacts.get_first_contact_from_jid(self.account, self.contact.jid)
if contact is None:
# contact was from pm in MUC
room, nick = gajim.get_room_and_nick_from_fjid(self.contact.jid)
gc_contact = gajim.contacts.get_gc_contact(self.account, room, nick)
if not gc_contact:
dialogs.ErrorDialog(
_('Sending private message failed'),
#in second %s code replaces with nickname
_('You are no longer in room "%s" or "%s" has left.') % \
(room, nick)).get_response()
return
ChatControl.send_message(self, message)
class GroupchatControl(ChatControlBase): class GroupchatControl(ChatControlBase):
TYPE_ID = message_control.TYPE_GC TYPE_ID = message_control.TYPE_GC
@ -255,7 +277,7 @@ class GroupchatControl(ChatControlBase):
menu = self.gc_popup_menu menu = self.gc_popup_menu
childs = menu.get_children() childs = menu.get_children()
# compact_view_menuitem # compact_view_menuitem
childs[5].set_active(self.compact_view_current_state) childs[5].set_active(self.compact_view_current)
menu = self.remove_possible_switch_to_menuitems(menu) menu = self.remove_possible_switch_to_menuitems(menu)
return menu return menu
@ -303,7 +325,8 @@ class GroupchatControl(ChatControlBase):
else: else:
gc_c = gajim.contacts.get_gc_contact(self.account, self.room_jid, nick) gc_c = gajim.contacts.get_gc_contact(self.account, self.room_jid, nick)
c = gajim.contacts.contact_from_gc_contact(gc_c) c = gajim.contacts.contact_from_gc_contact(gc_c)
gajim.interface.roster.new_chat(c, self.account) print "creating PM chat"
gajim.interface.roster.new_chat(c, self.account, private_chat = True)
# Scroll to line # Scroll to line
self.list_treeview.expand_row(path[0:1], False) self.list_treeview.expand_row(path[0:1], False)
self.list_treeview.scroll_to_cell(path) self.list_treeview.scroll_to_cell(path)
@ -536,9 +559,32 @@ class GroupchatControl(ChatControlBase):
print "draw_roster" print "draw_roster"
for nick in gajim.contacts.get_nick_list(self.account, self.room_jid): for nick in gajim.contacts.get_nick_list(self.account, self.room_jid):
gc_contact = gajim.contacts.get_gc_contact(self.account, self.room_jid, nick) gc_contact = gajim.contacts.get_gc_contact(self.account, self.room_jid, nick)
self.add_contact_to_roster(self.room_jid, nick, gc_contact.show, self.add_contact_to_roster(nick, gc_contact.show, gc_contact.role,
gc_contact.role, gc_contact.affiliation, gc_contact.status, gc_contact.affiliation, gc_contact.status,
gc_contact.jid) gc_contact.jid)
def on_send_pm(self, widget=None, model=None, iter=None, nick=None, msg=None):
'''opens a chat window and msg is not None sends private message to a
contact in a room'''
if nick is None:
nick = model[iter][C_NICK].decode('utf-8')
fjid = gajim.construct_fjid(self.room_jid, nick) # 'fake' jid
chat_win = gajim.interface.msg_win_mgr.get_window(fjid)
if not chat_win:
gc_c = gajim.contacts.get_gc_contact(self.account, self.room_jid, nick)
c = gajim.contacts.contact_from_gc_contact(gc_c)
print "creating PM chat"
gajim.interface.roster.new_chat(c, self.account, private_chat = True)
chat_win = gajim.interface.msg_win_mgr.get_window(fjid)
chat_control = chat_win.get_control(fjid)
#make active here in case we need to send a message
chat_win.set_active_tab(fjid)
if msg:
chat_control.send_message(msg)
chat_win.window.present()
def draw_contact(self, nick, selected=False, focus=False): def draw_contact(self, nick, selected=False, focus=False):
iter = self.get_contact_iter(nick) iter = self.get_contact_iter(nick)
@ -708,3 +754,308 @@ class GroupchatControl(ChatControlBase):
if model.iter_n_children(parent_iter) == 0: if model.iter_n_children(parent_iter) == 0:
model.remove(parent_iter) model.remove(parent_iter)
def _process_command(self, message):
if message[0] != '/':
return False
# Handle common commands
if ChatControlBase._process_command(self, message):
return True
message = message[1:]
message_array = message.split(' ', 1)
command = message_array.pop(0).lower()
if message_array == ['']:
message_array = []
if command == 'nick':
# example: /nick foo
if len(message_array):
nick = message_array[0]
gajim.connections[self.account].change_gc_nick(self.room_jid, nick)
self.clear(self.msg_textview)
else:
self.get_command_help(command)
return True
elif command == 'query' or command == 'chat':
# Open a chat window to the specified nick
# example: /query foo
if len(message_array):
nick = message_array.pop(0)
nicks = gajim.contacts.get_nick_list(self.account, self.room_jid)
if nick in nicks:
self.on_send_pm(nick = nick)
self.clear(self.msg_textview)
else:
self.print_conversation(_('Nickname not found: %s') % nick)
else:
self.get_command_help(command)
return True
elif command == 'msg':
# Send a message to a nick. Also opens a private message window.
# example: /msg foo Hey, what's up?
if len(message_array):
message_array = message_array[0].split()
nick = message_array.pop(0)
room_nicks = gajim.contacts.get_nick_list(self.account, self.room_jid)
if nick in room_nicks:
privmsg = ' '.join(message_array)
self.on_send_pm(nick=nick, msg=privmsg)
self.clear(self.msg_textview)
else:
self.print_conversation(_('Nickname not found: %s') % nick)
else:
self.get_command_help(command)
return True
elif command == 'topic':
# display or change the room topic
# example: /topic : print topic
# /topic foo : change topic to foo
if len(message_array):
new_topic = message_array.pop(0)
gajim.connections[self.account].send_gc_subject(self.room_jid,
new_topic)
else:
self.print_conversation(self.subject)
self.clear(self.msg_textview)
return True
elif command == 'invite':
# invite a user to a room for a reason
# example: /invite user@example.com reason
if len(message_array):
message_array = message_array[0].split()
invitee = message_array.pop(0)
if invitee.find('@') >= 0:
reason = ' '.join(message_array)
gajim.connections[self.account].send_invite(self.room_jid,
invitee, reason)
s = _('Invited %(contact_jid)s to %(room_jid)s.') % {
'contact_jid': invitee,
'room_jid': self.room_jid}
self.print_conversation(s)
self.clear(self.msg_textview)
else:
#%s is something the user wrote but it is not a jid so we inform
s = _('%s does not appear to be a valid JID') % invitee
self.print_conversation(s)
else:
self.get_command_help(command)
return True
elif command == 'join':
# example: /join room@conference.example.com/nick
if len(message_array):
message_array = message_array[0]
if message_array.find('@') >= 0:
room, servernick = message_array.split('@')
if servernick.find('/') >= 0:
server, nick = servernick.split('/', 1)
else:
server = servernick
nick = ''
#join_gc window is needed in order to provide for password entry.
if gajim.interface.instances[self.account].has_key('join_gc'):
gajim.interface.instances[self.account]['join_gc'].\
window.present()
else:
try:
gajim.interface.instances[self.account]['join_gc'] =\
dialogs.JoinGroupchatWindow(self.account,
server = server, room = room, nick = nick)
except RuntimeError:
pass
self.clear(self.msg_textview)
else:
#%s is something the user wrote but it is not a jid so we inform
s = _('%s does not appear to be a valid JID') % message_array
self.print_conversation(s)
else:
self.get_command_help(command)
return True
elif command == 'leave' or command == 'part' or command == 'close':
# Leave the room and close the tab or window
# FIXME: Sometimes this doesn't actually leave the room. Why?
reason = 'offline'
if len(message_array):
reason = message_array.pop(0)
self.remove_tab(reason)
return True
elif command == 'ban':
if len(message_array):
message_array = message_array[0].split()
nick = message_array.pop(0)
room_nicks = gajim.contacts.get_nick_list(self.account, self.room_jid)
reason = ' '.join(message_array)
if nick in room_nicks:
ban_jid = gajim.construct_fjid(self.room_jid, nick)
gajim.connections[self.account].gc_set_affiliation(self.room_jid,
ban_jid, 'outcast', reason)
self.clear(self.msg_textview)
elif nick.find('@') >= 0:
gajim.connections[self.account].gc_set_affiliation(self.room_jid,
nick, 'outcast', reason)
self.clear(self.msg_textview)
else:
self.print_conversation(_('Nickname not found: %s') % nick)
else:
self.get_command_help(command)
return True
elif command == 'kick':
if len(message_array):
message_array = message_array[0].split()
nick = message_array.pop(0)
room_nicks = gajim.contacts.get_nick_list(self.account, self.room_jid)
reason = ' '.join(message_array)
if nick in room_nicks:
gajim.connections[self.account].gc_set_role(self.room_jid, nick,
'none', reason)
self.clear(self.msg_textview)
else:
self.print_conversation(_('Nickname not found: %s') % nick)
else:
self.get_command_help(command)
return True
elif command == 'help':
if len(message_array):
subcommand = message_array.pop(0)
self.get_command_help(subcommand)
else:
self.get_command_help(command)
self.clear(self.msg_textview)
return True
elif command == 'say':
if len(message_array):
gajim.connections[self.account].send_gc_message(self.room_jid,
message[4:])
self.clear(self.msg_textview)
else:
self.get_command_help(command)
return True
else:
self.print_conversation(_('No such command: /%s (if you want to send this, '
'prefix it with /say)') % command)
return True
return False
def send_message(self, message):
'''call this function to send our message'''
if not message:
return
if message != '' or message != '\n':
self.save_sent_message(message)
if not self._process_command(message):
# Send the message
gajim.connections[self.account].send_gc_message(self.room_jid, message)
self.msg_textview.get_buffer().set_text('')
self.msg_textview.grab_focus()
def get_command_help(self, command):
if command == 'help':
self.print_conversation(_('Commands: %s') % self.muc_cmds)
elif command == 'ban':
s = _('Usage: /%s <nickname|JID> [reason], bans the JID from the room.'
' The nickname of an occupant may be substituted, but not if it contains "@".'
' If the JID is currently in the room, he/she/it will also be kicked.'
' Does NOT support spaces in nickname.') % command
self.print_conversation(s)
elif command == 'chat' or command == 'query':
self.print_conversation(_('Usage: /%s <nickname>, opens a private chat '
'window to the specified occupant.') % command)
elif command == 'clear':
self.print_conversation(_('Usage: /%s, clears the text window.') % command)
elif command == 'close' or command == 'leave' or command == 'part':
self.print_conversation(_('Usage: /%s [reason], closes the current window '
'or tab, displaying reason if specified.') % command)
elif command == 'compact':
self.print_conversation(_('Usage: /%s, sets the groupchat window to compact '
'mode.') % command)
elif command == 'invite':
self.print_conversation(_('Usage: /%s <JID> [reason], invites JID to the '
'current room, optionally providing a reason.') % command)
elif command == 'join':
self.print_conversation(_('Usage: /%s <room>@<server>[/nickname], offers to '
'join room@server optionally using specified '
'nickname.') % command)
elif command == 'kick':
self.print_conversation(_('Usage: /%s <nickname> [reason], removes the occupant '
'specified by nickname from the room and optionally '
'displays a reason. Does NOT support spaces in '
'nickname.') % command)
elif command == 'me':
self.print_conversation(_('Usage: /%s <action>, sends action to the current '
'room. Use third person. (e.g. /%s explodes.)') %\
(command, command))
elif command == 'msg':
s = _('Usage: /%s <nickname> [message], opens a private message window and '
'sends message to the occupant specified by nickname.') % command
self.print_conversation(s)
elif command == 'nick':
s = _('Usage: /%s <nickname>, changes your nickname in current room.') % command
self.print_conversation(s)
elif command == 'topic':
self.print_conversation(_('Usage: /%s [topic], displays or updates the current '
'room topic.') % command)
elif command == 'say':
self.print_conversation(_('Usage: /%s <message>, sends a message without '
'looking for other commands.') % command)
else:
self.print_conversation(_('No help info for /%s') % command)
def get_role(self, nick):
gc_contact = gajim.contacts.get_gc_contact(self.account, self.room_jid, nick)
if gc_contact:
return gc_contact.role
else:
return 'visitor'
def show_change_nick_input_dialog(self, title, prompt, proposed_nick = None):
'''asks user for new nick and on ok it sets it on room'''
instance = dialogs.InputDialog(title, prompt, proposed_nick)
response = instance.get_response()
if response == gtk.RESPONSE_OK:
nick = instance.input_entry.get_text().decode('utf-8')
self.nick = nick
gajim.connections[self.account].change_gc_nick(self.room_jid, nick)
def shutdown(self):
gajim.connections[self.account].send_gc_status(self.nick, self.room_jid,
show='offline', status=reason)
# They can already be removed by the destroy function
if self.room_jid in gajim.contacts.get_gc_list(self.account):
gajim.contacts.remove_room(self.account, self.room_jid)
del gajim.gc_connected[self.account][self.room_jid]
def allow_shutdown(self):
# FIXME:
# whether to ask for comfirmation before closing muc
if gajim.config.get('confirm_close_muc'):
names = []
if not room_jid:
for r_jid in self.xmls:
if gajim.gc_connected[self.account][r_jid]:
names.append(gajim.get_nick_from_jid(r_jid))
else:
names = [room_jid]
rooms_no = len(names)
if rooms_no >= 2: # if we are in many rooms
pritext = _('Are you sure you want to leave rooms "%s"?') % ', '.join(names)
sectext = _('If you close this window, you will be disconnected from these rooms.')
elif rooms_no == 1: # just in one room
pritext = _('Are you sure you want to leave room "%s"?') % names[0]
sectext = _('If you close this window, you will be disconnected from this room.')
if rooms_no > 0:
dialog = dialogs.ConfirmationDialogCheck(pritext, sectext,
_('Do _not ask me again'))
if dialog.is_checked():
gajim.config.set('confirm_close_muc', False)
dialog.destroy()
if dialog.get_response() != gtk.RESPONSE_OK:
return False
return True

View File

@ -19054,7 +19054,7 @@ Maybe I'll refactor later</property>
<property name="show_tabs">True</property> <property name="show_tabs">True</property>
<property name="show_border">True</property> <property name="show_border">True</property>
<property name="tab_pos">GTK_POS_TOP</property> <property name="tab_pos">GTK_POS_TOP</property>
<property name="scrollable">False</property> <property name="scrollable">True</property>
<property name="enable_popup">False</property> <property name="enable_popup">False</property>
<child> <child>
@ -19875,7 +19875,7 @@ topic</property>
</child> </child>
<child> <child>
<widget class="GtkScrolledWindow" id="scrolledwindow48"> <widget class="GtkScrolledWindow" id="list_scrolledwindow">
<property name="width_request">100</property> <property name="width_request">100</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="hscrollbar_policy">GTK_POLICY_NEVER</property> <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
@ -20108,7 +20108,7 @@ topic</property>
<property name="right_padding">0</property> <property name="right_padding">0</property>
<child> <child>
<widget class="GtkHBox" id="hbox3015"> <widget class="GtkHBox" id="gc_actions_hbox">
<property name="visible">True</property> <property name="visible">True</property>
<property name="homogeneous">False</property> <property name="homogeneous">False</property>
<property name="spacing">2</property> <property name="spacing">2</property>

View File

@ -558,12 +558,19 @@ class MessageWindowMgr:
return win return win
def get_control(self, jid): def get_control(self, jid):
'''Amonst all windows, return the MessageControl for jid''' '''Amongst all windows, return the MessageControl for jid'''
win = self.get_window(jid) win = self.get_window(jid)
if win: if win:
return win.get_control(jid) return win.get_control(jid)
return None return None
def get_controls(self, type):
ctls = []
for c in self.controls():
if c.type_id == type:
ctls.append(c)
return ctls
def windows(self): def windows(self):
for w in self._windows.values(): for w in self._windows.values():
yield w yield w

View File

@ -1529,11 +1529,9 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
passphrase) passphrase)
gajim.connections[account].gpg_passphrase(passphrase) gajim.connections[account].gpg_passphrase(passphrase)
for room_jid in gajim.interface.instances[account]['gc']: for gc_control in gajim.interface.msg_win_mgr.get_controls(message_control.TYPE_GC):
if room_jid != 'tabbed': gajim.connections[account].send_gc_status(gc_control.nick, gc_control.room_jid,
nick = gajim.interface.instances[account]['gc'][room_jid].nicks[room_jid] status, txt)
gajim.connections[account].send_gc_status(nick, room_jid, status,
txt)
gajim.connections[account].change_status(status, txt, sync, auto) gajim.connections[account].change_status(status, txt, sync, auto)
if status == 'online' and gajim.interface.sleeper.getState() != \ if status == 'online' and gajim.interface.sleeper.getState() != \
common.sleepy.STATE_UNKNOWN: common.sleepy.STATE_UNKNOWN:
@ -1672,14 +1670,24 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
self.update_status_combobox() self.update_status_combobox()
self.make_menu() self.make_menu()
def new_chat(self, contact, account): def new_chat(self, contact, account, private_chat = False):
# Get target window, create a control, and associate it with the window # Get target window, create a control, and associate it with the window
if not private_chat:
type = message_control.TYPE_CHAT
else:
type = message_control.TYPE_PM
mw = gajim.interface.msg_win_mgr.get_window(contact.jid) mw = gajim.interface.msg_win_mgr.get_window(contact.jid)
if not mw: if not mw:
mw = gajim.interface.msg_win_mgr.create_window(contact, account, mw = gajim.interface.msg_win_mgr.create_window(contact, account, type)
ChatControl.TYPE_ID)
chat_control = ChatControl(mw, contact, account) if not private_chat:
chat_control = ChatControl(mw, contact, account)
else:
chat_control = PrivateChatControl(mw, contact, account)
mw.new_tab(chat_control) mw.new_tab(chat_control)
if gajim.awaiting_events[account].has_key(contact.jid): if gajim.awaiting_events[account].has_key(contact.jid):
# We call this here to avoid race conditions with widget validation # We call this here to avoid race conditions with widget validation
chat_control.read_queue() chat_control.read_queue()

View File

@ -250,15 +250,13 @@ class NotificationAreaTooltip(BaseTooltip, StatusTable):
else: else:
unread_pm += ctl.nb_unread unread_pm += ctl.nb_unread
# FIXME
# we count unread gc/pm messages # we count unread gc/pm messages
gc_wins = gajim.interface.instances[acct]['gc'] chat_t = message_control.TYPE_GC
for jid in gc_wins: for gc_control in gajim.interface.msg_win_mgr.get_controls(chat_t):
if jid != 'tabbed': pm_msgs = gc_control.get_specific_unread()
pm_msgs = gc_wins[jid].get_specific_unread(jid) unread_gc += gc_control.nb_unread
unread_gc += gc_wins[jid].nb_unread[jid] unread_gc -= pm_msgs
unread_gc -= pm_msgs unread_pm += pm_msgs
unread_pm += pm_msgs
if unread_chat or unread_single_chat or unread_gc or unread_pm: if unread_chat or unread_single_chat or unread_gc or unread_pm:
text = '' text = ''