we now have groupchat configuration !! (and a Data Form Parser JEP 0004)

This commit is contained in:
Yann Leboulanger 2005-04-20 10:21:33 +00:00
parent ba272a9553
commit ebef428ae1
5 changed files with 455 additions and 655 deletions

View file

@ -107,7 +107,7 @@ class Connection:
'SUBSCRIBED': [], 'UNSUBSCRIBED': [], 'SUBSCRIBE': [], \ 'SUBSCRIBED': [], 'UNSUBSCRIBED': [], 'SUBSCRIBE': [], \
'AGENT_INFO': [], 'AGENT_INFO_ITEMS': [], 'AGENT_INFO_INFO': [], \ 'AGENT_INFO': [], 'AGENT_INFO_ITEMS': [], 'AGENT_INFO_INFO': [], \
'QUIT': [], 'ACC_OK': [], 'MYVCARD': [], 'OS_INFO': [], 'VCARD': [], \ 'QUIT': [], 'ACC_OK': [], 'MYVCARD': [], 'OS_INFO': [], 'VCARD': [], \
'GC_MSG': [], 'GC_SUBJECT': [], 'BAD_PASSPHRASE': [], \ 'GC_MSG': [], 'GC_SUBJECT': [], 'GC_CONFIG': [], 'BAD_PASSPHRASE': [],\
'ROSTER_INFO': []} 'ROSTER_INFO': []}
self.name = name self.name = name
self.connected = 0 # offline self.connected = 0 # offline
@ -286,6 +286,7 @@ class Connection:
# END disconenctedCB # END disconenctedCB
def _rosterSetCB(self, con, iq_obj): def _rosterSetCB(self, con, iq_obj):
gajim.log.debug('rosterSetCB')
for item in iq_obj.getQueryNode().getChildren(): for item in iq_obj.getQueryNode().getChildren():
jid = item.getAttr('jid') jid = item.getAttr('jid')
name = item.getAttr('name') name = item.getAttr('name')
@ -297,6 +298,7 @@ class Connection:
self.dispatch('ROSTER_INFO', (jid, name, sub, ask, groups)) self.dispatch('ROSTER_INFO', (jid, name, sub, ask, groups))
def _BrowseResultCB(self, con, iq_obj): def _BrowseResultCB(self, con, iq_obj):
gajim.log.debug('BrowseResultCB')
identities, features, items = [], [], [] identities, features, items = [], [], []
q = iq_obj.getTag('service') q = iq_obj.getTag('service')
if not q: if not q:
@ -318,6 +320,7 @@ class Connection:
self.dispatch('AGENT_INFO', (jid, identities, features, items)) self.dispatch('AGENT_INFO', (jid, identities, features, items))
def _DiscoverItemsCB(self, con, iq_obj): def _DiscoverItemsCB(self, con, iq_obj):
gajim.log.debug('DiscoverItemsCB')
qp = iq_obj.getQueryPayload() qp = iq_obj.getQueryPayload()
items = [] items = []
if not qp: if not qp:
@ -331,10 +334,12 @@ class Connection:
self.dispatch('AGENT_INFO_ITEMS', (jid, items)) self.dispatch('AGENT_INFO_ITEMS', (jid, items))
def _DiscoverInfoErrorCB(self, con, iq_obj): def _DiscoverInfoErrorCB(self, con, iq_obj):
gajim.log.debug('DiscoverInfoErrorCB')
jid = str(iq_obj.getFrom()) jid = str(iq_obj.getFrom())
con.browseAgents(jid) con.browseAgents(jid)
def _DiscoverInfoCB(self, con, iq_obj): def _DiscoverInfoCB(self, con, iq_obj):
gajim.log.debug('DiscoverInfoCB')
# According to JEP-0030: # According to JEP-0030:
# For identity: category, name is mandatory, type is optional. # For identity: category, name is mandatory, type is optional.
# For feature: var is mandatory # For feature: var is mandatory
@ -358,6 +363,7 @@ class Connection:
self.connection.discoverItems(jid) self.connection.discoverItems(jid)
def _VersionCB(self, con, iq_obj): def _VersionCB(self, con, iq_obj):
gajim.log.debug('VersionCB')
f = iq_obj.getFrom() f = iq_obj.getFrom()
iq_obj.setFrom(iq_obj.getTo()) iq_obj.setFrom(iq_obj.getTo())
iq_obj.setTo(f) iq_obj.setTo(f)
@ -371,6 +377,7 @@ class Connection:
self.connection.send(iq_obj) self.connection.send(iq_obj)
def _VersionResultCB(self, con, iq_obj): def _VersionResultCB(self, con, iq_obj):
gajim.log.debug('VersionResultCB')
client_info = '' client_info = ''
os_info = '' os_info = ''
qp = iq_obj.getTag('query') qp = iq_obj.getTag('query')
@ -383,6 +390,70 @@ class Connection:
jid = iq_obj.getFrom().getStripped() jid = iq_obj.getFrom().getStripped()
self.dispatch('OS_INFO', (jid, client_info, os_info)) self.dispatch('OS_INFO', (jid, client_info, os_info))
def _MucOwnerCB(self, con, iq_obj):
gajim.log.debug('MucOwnerCB')
qp = iq_obj.getQueryPayload()
node = None
for q in qp:
if q.getNamespace() == common.jabber.NS_XDATA:
node = q
if not node:
return
# Parse the form
dic = {}
tag = node.getTag('title')
if tag:
dic['title'] = tag.getData()
tag = node.getTag('instructions')
if tag:
dic['instructions'] = tag.getData()
i = 0
for child in node.getChildren():
if child.getName() != 'field':
continue
var = child.getAttr('var')
ctype = child.getAttr('type')
label = child.getAttr('label')
if not var and ctype != 'fixed': # We must have var if type != fixed
continue
dic[i] = {}
if var:
dic[i]['var'] = var
if ctype:
dic[i]['type'] = ctype
if label:
dic[i]['label'] = label
tags = child.getTags('value')
if len(tags):
dic[i]['values'] = []
for tag in tags:
data = tag.getData()
if ctype == 'boolean':
if data in ['yes', 'true', 'assent']:
data = True
else:
data = False
dic[i]['values'].append(data)
tag = child.getTag('desc')
if tag:
dic[i]['desc'] = tag.getData()
option_tags = child.getTags('option')
if len(option_tags):
dic[i]['options'] = {}
j = 0
for option_tag in option_tags:
dic[i]['options'][j] = {}
label = option_tag.getAttr('label')
if label:
dic[i]['options'][j]['label'] = label
tags = option_tag.getTags('value')
dic[i]['options'][j]['values'] = []
for tag in tags:
dic[i]['options'][j]['values'].append(tag.getData())
j += 1
i += 1
self.dispatch('GC_CONFIG', (str(iq_obj.getFrom()), dic))
def connect(self): def connect(self):
"""Connect and authentificate to the Jabber server""" """Connect and authentificate to the Jabber server"""
name = gajim.config.get_per('accounts', self.name, 'name') name = gajim.config.get_per('accounts', self.name, 'name')
@ -427,6 +498,8 @@ class Connection:
common.jabber.NS_VERSION) common.jabber.NS_VERSION)
con.registerHandler('iq',self._VersionResultCB,'result', \ con.registerHandler('iq',self._VersionResultCB,'result', \
common.jabber.NS_VERSION) common.jabber.NS_VERSION)
con.registerHandler('iq',self._MucOwnerCB,'result', \
common.jabber.NS_P_MUC_OWNER)
try: try:
con.connect() con.connect()
except: except:
@ -691,6 +764,7 @@ class Connection:
if not self.connection: if not self.connection:
return return
p = common.jabber.Presence(to = '%s@%s/%s' % (room, server, nick)) p = common.jabber.Presence(to = '%s@%s/%s' % (room, server, nick))
p.setX(common.jabber.NS_P_MUC)
self.connection.send(p) self.connection.send(p)
def send_gc_message(self, jid, msg): def send_gc_message(self, jid, msg):
@ -709,6 +783,13 @@ class Connection:
msg_iq.setSubject(subject) msg_iq.setSubject(subject)
self.connection.send(msg_iq) self.connection.send(msg_iq)
def request_gc_config(self, room_jid):
iq = common.jabber.Iq(type = 'get', to = room_jid)
iq.setQuery(common.jabber.NS_P_MUC_OWNER)
id = self.connection.getAnID()
iq.setID(id)
self.connection.send(iq)
def send_gc_status(self, nick, jid, show, status): def send_gc_status(self, nick, jid, show, status):
if not self.connection: if not self.connection:
return return
@ -742,6 +823,47 @@ class Connection:
iq.setID(id) iq.setID(id)
self.connection.send(iq) self.connection.send(iq)
def send_gc_config(self, room_jid, config):
iq = common.jabber.Iq(type = 'set', to = room_jid)
query = iq.setQuery(common.jabber.NS_P_MUC_OWNER)
x = query.insertTag('x', attrs = {'xmlns': common.jabber.NS_XDATA, \
'type': 'submit'})
if config.has_key('title'):
x.insertTag('title').insertData(config['title'])
if config.has_key('instructions'):
x.insertTag('instructions').insertData(config['instructions'])
i = 0
while config.has_key(i):
tag = x.insertTag('field')
if config[i].has_key('type'):
tag.putAttr('type', config[i]['type'])
if config[i].has_key('var'):
tag.putAttr('var', config[i]['var'])
if config[i].has_key('label'):
tag.putAttr('label', config[i]['label'])
if config[i].has_key('values'):
for val in config[i]['values']:
if val == False:
val = 'false'
elif val == True:
val = 'true'
tag.insertTag('value').insertData(val)
if config[i].has_key('desc'):
tag.insertTag('desc').insertData(config[i]['desc'])
if config[i].has_key('options'):
j = 0
while config[i]['options'].has_key(j):
opt_tag = tag.insertTag('option')
if config[i]['options'][j].has_key('label'):
opt_tag.putAttr('label', config[i]['options'][j]['label'])
for val in config[i]['options'][j]['values']:
opt_tag.insertTag('value').insertData(val)
j += 1
i += 1
id = self.connection.getAnID()
iq.setID(id)
self.connection.send(iq)
def gpg_passphrase(self, passphrase): def gpg_passphrase(self, passphrase):
if USE_GPG: if USE_GPG:
self.gpg.passphrase = passphrase self.gpg.passphrase = passphrase

View file

@ -1087,7 +1087,7 @@ class Account_modification_window:
self.plugin.sleeper_state[name] = \ self.plugin.sleeper_state[name] = \
self.plugin.sleeper_state[self.account] self.plugin.sleeper_state[self.account]
#upgrade account variable in opened windows #upgrade account variable in opened windows
for kind in ['infos', 'chats', 'gc']: for kind in ['infos', 'chats', 'gc', 'gc_config']:
for j in self.plugin.windows[name][kind]: for j in self.plugin.windows[name][kind]:
self.plugin.windows[name][kind][j].account = name self.plugin.windows[name][kind][j].account = name
#upgrade account in systray #upgrade account in systray
@ -1167,7 +1167,8 @@ class Account_modification_window:
if save_password: if save_password:
gajim.connections[name].password = password gajim.connections[name].password = password
#update variables #update variables
self.plugin.windows[name] = {'infos': {}, 'chats': {}, 'gc': {}} self.plugin.windows[name] = {'infos': {}, 'chats': {}, 'gc': {}, \
'gc_config': {}}
self.plugin.queues[name] = {} self.plugin.queues[name] = {}
gajim.connections[name].connected = 0 gajim.connections[name].connected = 0
self.plugin.roster.groups[name] = {} self.plugin.roster.groups[name] = {}
@ -1904,6 +1905,126 @@ class Service_discovery_window:
self.browse(server_address) self.browse(server_address)
self.plugin.save_config() self.plugin.save_config()
class Groupchat_config_window:
'''Groupchat_config_window class'''
def __init__(self, plugin, account, room_jid, config):
self.plugin = plugin
self.account = account
self.room_jid = room_jid
self.config = config
self.xml = gtk.glade.XML(GTKGUI_GLADE, 'groupchat_config_window', APP)
self.window = self.xml.get_widget('groupchat_config_window')
self.config_table = self.xml.get_widget('config_table')
self.fill_table()
self.xml.signal_autoconnect(self)
def on_groupchat_config_window_destroy(self, widget):
del self.plugin.windows[self.account]['gc_config'][self.room_jid]
def on_cancel_button_clicked(self, widget):
self.window.destroy()
def on_apply_button_clicked(self, widget):
gajim.connections[self.account].send_gc_config(self.room_jid, self.config)
def on_checkbutton_toggled(self, widget, index):
self.config[index]['values'][0] = widget.get_active()
def on_combobox_changed(self, widget, index):
self.config[index]['values'][0] = self.config[index]['options'][ \
widget.get_active()]['values'][0]
def on_entry_changed(self, widget, index):
self.config[index]['values'][0] = widget.get_text()
def on_textbuffer_changed(self, widget, index):
begin, end = widget.get_bounds()
self.config[index]['values'][0] = widget.get_text(begin, end)
def fill_table(self):
if self.config.has_key('title'):
self.window.set_title(self.config['title'])
if self.config.has_key('instructions'):
self.xml.get_widget('instructions_label').set_text(\
self.config['instructions'])
i = 0
while self.config.has_key(i):
if not self.config[i].has_key('type'):
i += 1
continue
ctype = self.config[i]['type']
if ctype == 'hidden':
i += 1
continue
nbrows = self.config_table.get_property('n-rows')
self.config_table.resize(nbrows + 1, 2)
if self.config[i].has_key('label'):
label = gtk.Label(self.config[i]['label'])
label.set_alignment(0.0, 0.5)
self.config_table.attach(label, 0, 1, nbrows, nbrows + 1, gtk.FILL \
| gtk.SHRINK)
desc = None
if self.config[i].has_key('desc'):
desc = self.config[i]['desc']
max = 1
if ctype == 'boolean':
widget = gtk.CheckButton(desc, False)
widget.set_active(self.config[i]['values'][0])
widget.connect('toggled', self.on_checkbutton_toggled, i)
max = 2
elif ctype == 'fixed':
widget = gtk.Label('\n'.join(self.config[i]['values']))
widget.set_alignment(0.0, 0.5)
max = 4
elif ctype == 'jid-multi':
#TODO
widget = gtk.Label('')
elif ctype == 'jid-single':
#TODO
widget = gtk.Label('')
elif ctype == 'list-multi':
#TODO
widget = gtk.Label('')
elif ctype == 'list-single':
widget = gtk.combo_box_new_text()
widget.connect('changed', self.on_combobox_changed, i)
index = 0
j = 0
while self.config[i]['options'].has_key(j):
if self.config[i]['options'][j]['values'][0] == \
self.config[i]['values'][0]:
index = j
widget.append_text(self.config[i]['options'][j]['label'])
j += 1
widget.set_active(index)
max = 3
elif ctype == 'text-multi':
widget = gtk.TextView()
widget.get_buffer().connect('changed', self.on_textbuffer_changed, \
i)
widget.get_buffer().set_text('\n'.join(self.config[i]['values']))
max = 4
elif ctype == 'text-private':
widget = gtk.Entry()
widget.connect('changed', self.on_entry_changed, i)
widget.set_text(self.config[i]['values'][0])
widget.set_visibility(False)
max = 3
elif ctype == 'text-single':
widget = gtk.Entry()
widget.connect('changed', self.on_entry_changed, i)
widget.set_text(self.config[i]['values'][0])
max = 3
i += 1
if max < 4:
self.config_table.attach(widget, 1, max, nbrows, nbrows + 1, \
gtk.FILL | gtk.SHRINK)
widget = gtk.Label()
self.config_table.attach(widget, max, 4, nbrows, nbrows + 1)
else:
self.config_table.attach(widget, 1, max, nbrows, nbrows + 1)
self.config_table.show_all()
class Remove_account_window: class Remove_account_window:
'''ask for removing from gajim only or from gajim and server too '''ask for removing from gajim only or from gajim and server too
and do removing of the account given''' and do removing of the account given'''

View file

@ -374,7 +374,7 @@ class Interface:
gajim.config.set_per('accounts', name, 'use_proxy', array[6]) gajim.config.set_per('accounts', name, 'use_proxy', array[6])
gajim.config.set_per('accounts', name, 'proxyhost', array[7]) gajim.config.set_per('accounts', name, 'proxyhost', array[7])
gajim.config.set_per('accounts', name, 'proxyport', array[8]) gajim.config.set_per('accounts', name, 'proxyport', array[8])
self.windows[name] = {'infos': {}, 'chats': {}, 'gc': {}} self.windows[name] = {'infos': {}, 'chats': {}, 'gc': {}, 'gc_config': {}}
self.queues[name] = {} self.queues[name] = {}
gajim.connections[name].connected = 0 gajim.connections[name].connected = 0
self.nicks[name] = array[1] self.nicks[name] = array[1]
@ -433,6 +433,13 @@ class Interface:
self.windows[account]['gc'][jid].print_conversation(\ self.windows[account]['gc'][jid].print_conversation(\
'%s has set the subject to %s' % (jids[1], array[1]), jid) '%s has set the subject to %s' % (jids[1], array[1]), jid)
def handle_event_gc_config(self, account, array):
#('GC_CONFIG', account, (jid, config)) config is a dict
jid = array[0].split('/')[0]
if not self.windows[account]['gc_config'].has_key(jid):
self.windows[account]['gc_config'][jid] = \
config.Groupchat_config_window(self, account, jid, array[1])
def handle_event_bad_passphrase(self, account, array): def handle_event_bad_passphrase(self, account, array):
dialogs.Warning_dialog(_('Your GPG passphrase is wrong, so you are connected without your GPG key.')) dialogs.Warning_dialog(_('Your GPG passphrase is wrong, so you are connected without your GPG key.'))
@ -612,6 +619,7 @@ class Interface:
conn.register_handler('OS_INFO', self.handle_event_os_info) conn.register_handler('OS_INFO', self.handle_event_os_info)
conn.register_handler('GC_MSG', self.handle_event_gc_msg) conn.register_handler('GC_MSG', self.handle_event_gc_msg)
conn.register_handler('GC_SUBJECT', self.handle_event_gc_subject) conn.register_handler('GC_SUBJECT', self.handle_event_gc_subject)
conn.register_handler('GC_CONFIG', self.handle_event_gc_config)
conn.register_handler('BAD_PASSPHRASE', self.handle_event_bad_passphrase) conn.register_handler('BAD_PASSPHRASE', self.handle_event_bad_passphrase)
conn.register_handler('ROSTER_INFO', self.handle_event_roster_info) conn.register_handler('ROSTER_INFO', self.handle_event_roster_info)
@ -637,7 +645,7 @@ class Interface:
self.nicks = {} self.nicks = {}
self.sleeper_state = {} #whether we pass auto away / xa or not self.sleeper_state = {} #whether we pass auto away / xa or not
for a in gajim.connections: for a in gajim.connections:
self.windows[a] = {'infos': {}, 'chats': {}, 'gc': {}} self.windows[a] = {'infos': {}, 'chats': {}, 'gc': {}, 'gc_config': {}}
self.queues[a] = {} self.queues[a] = {}
self.nicks[a] = gajim.config.get_per('accounts', a, 'name') self.nicks[a] = gajim.config.get_per('accounts', a, 'name')
self.sleeper_state[a] = 0 #0:don't use sleeper for this account self.sleeper_state[a] = 0 #0:don't use sleeper for this account

View file

@ -57,6 +57,8 @@ class Groupchat_window(chat.Chat):
self.on_chat_notebook_switch_page) self.on_chat_notebook_switch_page)
self.xml.signal_connect('on_set_button_clicked', \ self.xml.signal_connect('on_set_button_clicked', \
self.on_set_button_clicked) self.on_set_button_clicked)
self.xml.signal_connect('on_configure_button_clicked', \
self.on_configure_button_clicked)
self.xml.signal_connect('on_groupchat_window_key_press_event', \ self.xml.signal_connect('on_groupchat_window_key_press_event', \
self.on_groupchat_window_key_press_event) self.on_groupchat_window_key_press_event)
@ -234,6 +236,10 @@ class Groupchat_window(chat.Chat):
subject = self.xml.get_widget('subject_entry').get_text() subject = self.xml.get_widget('subject_entry').get_text()
gajim.connections[self.account].send_gc_subject(room_jid, subject) gajim.connections[self.account].send_gc_subject(room_jid, subject)
def on_configure_button_clicked(self, widget):
room_jid = self.get_active_jid()
gajim.connections[self.account].request_gc_config(room_jid)
def on_message_textview_key_press_event(self, widget, event): def on_message_textview_key_press_event(self, widget, event):
"""When a key is pressed: """When a key is pressed:
if enter is pressed without the shit key, message (if not empty) is sent if enter is pressed without the shit key, message (if not empty) is sent

File diff suppressed because it is too large Load diff