* ask only once at a time to change our nickname in a room in case of conflict

* add a checkbutton to use the entered nickname by default without asking anymore. Fixes #5141
This commit is contained in:
Yann Leboulanger 2009-07-17 09:53:15 +02:00
parent 425ae28713
commit 235c4d9ab8
5 changed files with 245 additions and 205 deletions

View File

@ -1,160 +1,113 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<?xml version="1.0"?>
<glade-interface>
<widget class="GtkDialog" id="input_dialog">
<property name="border_width">6</property>
<property name="title" translatable="yes"></property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<property name="focus_on_map">True</property>
<property name="urgency_hint">False</property>
<property name="has_separator">False</property>
<signal name="destroy" handler="on_input_dialog_destroy" last_modification_time="Sat, 18 Nov 2006 20:23:21 GMT"/>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox10">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">6</property>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area9">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<widget class="GtkButton" id="cancelbutton">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-cancel</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="response_id">-6</property>
</widget>
</child>
<child>
<widget class="GtkButton" id="okbutton">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="has_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-ok</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="response_id">-5</property>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox76">
<property name="border_width">6</property>
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">6</property>
<child>
<widget class="GtkHBox" id="hbox2960">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">12</property>
<child>
<widget class="GtkImage" id="image507">
<property name="visible">True</property>
<property name="stock">gtk-dialog-question</property>
<property name="icon_size">6</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label">
<property name="visible">True</property>
<property name="label" translatable="yes"></property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="input_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">True</property>
<property name="visibility">True</property>
<property name="max_length">0</property>
<property name="text" translatable="yes"></property>
<property name="has_frame">True</property>
<property name="activates_default">True</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
</child>
</widget>
<!-- interface-requires gtk+ 2.12 -->
<!-- interface-naming-policy toplevel-contextual -->
<widget class="GtkDialog" id="input_dialog">
<property name="border_width">6</property>
<property name="type_hint">dialog</property>
<property name="has_separator">False</property>
<signal name="delete_event" handler="on_input_dialog_delete_event"/>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox10">
<property name="visible">True</property>
<property name="spacing">6</property>
<child>
<widget class="GtkVBox" id="vbox">
<property name="visible">True</property>
<property name="border_width">6</property>
<property name="spacing">6</property>
<child>
<widget class="GtkHBox" id="hbox2960">
<property name="visible">True</property>
<property name="spacing">12</property>
<child>
<widget class="GtkImage" id="image507">
<property name="visible">True</property>
<property name="stock">gtk-dialog-question</property>
<property name="icon-size">6</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label">
<property name="visible">True</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="input_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="activates_default">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area9">
<property name="visible">True</property>
<property name="layout_style">end</property>
<child>
<widget class="GtkButton" id="cancelbutton">
<property name="label">gtk-cancel</property>
<property name="response_id">-6</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">False</property>
<property name="use_stock">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="okbutton">
<property name="label">gtk-ok</property>
<property name="response_id">-5</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="has_default">True</property>
<property name="receives_default">False</property>
<property name="use_stock">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

View File

@ -113,6 +113,7 @@ contacts = Contacts()
gc_connected = {} # tell if we are connected to the room or not {acct: {room_jid: True}}
gc_passwords = {} # list of the pass required to enter a room {room_jid: password}
automatic_rooms = {} # list of rooms that must be automaticaly configured and for which we have a list of invities {account: {room_jid: {'invities': []}}}
new_room_nick = None # if it's != None, use this nick instead of asking for a new nickname when there is a conflict.
groups = {} # list of groups
newly_added = {} # list of contacts that has just signed in

View File

@ -1580,6 +1580,7 @@ class CommonInputDialog:
self.dialog.set_title(title)
label.set_markup(label_str)
self.cancel_handler = cancel_handler
self.vbox = self.xml.get_widget('vbox')
self.ok_handler = ok_handler
okbutton = self.xml.get_widget('okbutton')
@ -1589,7 +1590,7 @@ class CommonInputDialog:
self.xml.signal_autoconnect(self)
self.dialog.show_all()
def on_input_dialog_destroy(self, widget):
def on_input_dialog_delete_event(self, widget, event):
if self.cancel_handler:
self.cancel_handler()
@ -1610,18 +1611,142 @@ class CommonInputDialog:
class InputDialog(CommonInputDialog):
'''Class for Input dialog'''
def __init__(self, title, label_str, input_str=None, is_modal=True,
ok_handler=None, cancel_handler=None):
ok_handler=None, cancel_handler=None):
self.xml = gtkgui_helpers.get_glade('input_dialog.glade')
CommonInputDialog.__init__(self, title, label_str, is_modal, ok_handler,
cancel_handler)
cancel_handler)
self.input_entry = self.xml.get_widget('input_entry')
if input_str:
self.set_entry(input_str)
def set_entry(self, value):
self.input_entry.set_text(value)
self.input_entry.select_region(0, -1) # select all
def get_text(self):
return self.input_entry.get_text().decode('utf-8')
class InputDialogCheck(InputDialog):
'''Class for Input dialog'''
def __init__(self, title, label_str, checktext='', input_str=None,
is_modal=True, ok_handler=None, cancel_handler=None):
self.xml = gtkgui_helpers.get_glade('input_dialog.glade')
InputDialog.__init__(self, title, label_str, input_str=input_str,
is_modal=is_modal, ok_handler=ok_handler,
cancel_handler=cancel_handler)
self.input_entry = self.xml.get_widget('input_entry')
if input_str:
self.input_entry.set_text(input_str)
self.input_entry.select_region(0, -1) # select all
self.checkbutton = gtk.CheckButton(checktext)
self.vbox.pack_start(self.checkbutton, expand=False, fill=True)
self.checkbutton.show()
def on_okbutton_clicked(self, widget):
user_input = self.get_text()
if user_input:
user_input = user_input.decode('utf-8')
self.cancel_handler = None
self.dialog.destroy()
if isinstance(self.ok_handler, tuple):
self.ok_handler[0](user_input, self.is_checked(), *self.ok_handler[1:])
else:
self.ok_handler(user_input, self.is_checked())
def get_text(self):
return self.input_entry.get_text().decode('utf-8')
def is_checked(self):
''' Get active state of the checkbutton '''
return self.checkbutton.get_active()
class ChangeNickDialog(InputDialogCheck):
'''Class for changing room nickname in case of conflict'''
def __init__(self, account, room_jid):
title = _('Unable to join group chat')
check_text = _('Always use this nickname when there is a conflict')
InputDialogCheck.__init__(self, title, '', checktext=check_text,
input_str='', is_modal=True, ok_handler=None, cancel_handler=None)
self.room_queue = [(account, room_jid)]
self.check_next()
def on_input_dialog_delete_event(self, widget, event):
self.on_cancelbutton_clicked(widget)
return True
def setup_dialog(self):
self.gc_control = gajim.interface.msg_win_mgr.get_gc_control(
self.room_jid, self.account)
if not self.gc_control and \
self.room_jid in gajim.interface.minimized_controls[self.account]:
self.gc_control = \
gajim.interface.minimized_controls[self.account][self.room_jid]
if not self.gc_control:
self.check_next()
return
label = self.xml.get_widget('label')
prompt = _('Your desired nickname in group chat %s is in use or '
'registered by another occupant.\nPlease specify another nickname '
'below:') % self.room_jid
label.set_markup(prompt)
self.set_entry(self.gc_control.nick + \
gajim.config.get('gc_proposed_nick_char'))
def check_next(self):
if len(self.room_queue) == 0:
self.cancel_handler = None
self.dialog.destroy()
del gajim.interface.instances['change_nick_dialog']
return
self.account, self.room_jid = self.room_queue.pop(0)
self.setup_dialog()
if gajim.new_room_nick is not None and not gajim.gc_connected[
self.account][self.room_jid] and self.gc_control.nick != \
gajim.new_room_nick:
self.dialog.hide()
self.on_ok(gajim.new_room_nick, True)
else:
self.dialog.show()
def on_okbutton_clicked(self, widget):
nick = self.get_text()
if nick:
nick = nick.decode('utf-8')
# send presence to room
try:
nick = helpers.parse_resource(nick)
except Exception:
# invalid char
dialogs.ErrorDialog(_('Invalid nickname'),
_('The nickname has not allowed characters.'))
return
self.on_ok(nick, self.is_checked())
def on_ok(self, nick, is_checked):
if is_checked:
gajim.new_room_nick = nick
gajim.connections[self.account].join_gc(nick, self.room_jid, None,
change_nick=True)
if gajim.gc_connected[self.account][self.room_jid]:
# We are changing nick, we will change self.nick when we receive
# presence that inform that it works
self.gc_control.new_nick = nick
else:
# We are connecting, we will not get a changed nick presence so
# change it NOW. We don't already have a nick so it's harmless
self.gc_control.nick = nick
self.check_next()
def on_cancelbutton_clicked(self, widget):
self.gc_control.new_nick = ''
self.check_next()
def add_room(self, account, room_jid):
if (account, room_jid) not in self.room_queue:
self.room_queue.append((account, room_jid))
class InputTextDialog(CommonInputDialog):
'''Class for multilines Input dialog (more place than InputDialog)'''
def __init__(self, title, label_str, input_str=None, is_modal=True,

View File

@ -506,16 +506,11 @@ class Interface:
def handle_event_ask_new_nick(self, account, data):
#('ASK_NEW_NICK', account, (room_jid,))
room_jid = data[0]
gc_control = self.msg_win_mgr.get_gc_control(room_jid, account)
if not gc_control and \
room_jid in self.minimized_controls[account]:
gc_control = self.minimized_controls[account][room_jid]
if gc_control: # user may close the window before we are here
title = _('Unable to join group chat')
prompt = _('Your desired nickname in group chat %s is in use or '
'registered by another occupant.\nPlease specify another nickname '
'below:') % room_jid
gc_control.show_change_nick_input_dialog(title, prompt)
if 'change_nick_dialog' in self.instances:
self.instances['change_nick_dialog'].add_room(account, room_jid)
else:
self.instances['change_nick_dialog'] = dialogs.ChangeNickDialog(
account, room_jid)
def handle_event_http_auth(self, account, data):
#('HTTP_AUTH', account, (method, url, transaction_id, iq_obj, msg))

View File

@ -181,7 +181,6 @@ class GroupchatControl(ChatControlBase):
self.is_continued=is_continued
self.is_anonymous = True
self.change_nick_dialog = None
self.actions_button = self.xml.get_widget('muc_window_actions_button')
id_ = self.actions_button.connect('clicked',
@ -1787,39 +1786,6 @@ class GroupchatControl(ChatControlBase):
else:
return 'visitor'
def show_change_nick_input_dialog(self, title, prompt):
'''asks user for new nick and on ok it sets it on room'''
if self.change_nick_dialog:
# A dialog is already opened
return
def on_ok(widget):
nick = self.change_nick_dialog.input_entry.get_text().decode('utf-8')
self.change_nick_dialog = None
try:
nick = helpers.parse_resource(nick)
except Exception:
# invalid char
dialogs.ErrorDialog(_('Invalid nickname'),
_('The nickname has not allowed characters.'))
return
gajim.connections[self.account].join_gc(nick, self.room_jid, None,
change_nick=True)
if gajim.gc_connected[self.account][self.room_jid]:
# We are changing nick, we will change self.nick when we receive
# presence that inform that it works
self.new_nick = nick
else:
# We are connecting, we will not get a changed nick presence so
# change it NOW. We don't already have a nick so it's harmless
self.nick = nick
def on_cancel():
self.change_nick_dialog = None
self.new_nick = ''
proposed_nick = self.nick + gajim.config.get('gc_proposed_nick_char')
self.change_nick_dialog = dialogs.InputDialog(title, prompt,
proposed_nick, is_modal=False, ok_handler=on_ok,
cancel_handler=on_cancel)
def minimizable(self):
if self.contact.jid in gajim.config.get_per('accounts', self.account,
'minimized_gc').split(' '):