Commit ebef428a authored by Yann Leboulanger's avatar Yann Leboulanger
Browse files

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

parent ba272a95
......@@ -107,7 +107,7 @@ class Connection:
'SUBSCRIBED': [], 'UNSUBSCRIBED': [], 'SUBSCRIBE': [], \
'AGENT_INFO': [], 'AGENT_INFO_ITEMS': [], 'AGENT_INFO_INFO': [], \
'QUIT': [], 'ACC_OK': [], 'MYVCARD': [], 'OS_INFO': [], 'VCARD': [], \
'GC_MSG': [], 'GC_SUBJECT': [], 'BAD_PASSPHRASE': [], \
'GC_MSG': [], 'GC_SUBJECT': [], 'GC_CONFIG': [], 'BAD_PASSPHRASE': [],\
'ROSTER_INFO': []}
self.name = name
self.connected = 0 # offline
......@@ -286,6 +286,7 @@ class Connection:
# END disconenctedCB
def _rosterSetCB(self, con, iq_obj):
gajim.log.debug('rosterSetCB')
for item in iq_obj.getQueryNode().getChildren():
jid = item.getAttr('jid')
name = item.getAttr('name')
......@@ -297,6 +298,7 @@ class Connection:
self.dispatch('ROSTER_INFO', (jid, name, sub, ask, groups))
def _BrowseResultCB(self, con, iq_obj):
gajim.log.debug('BrowseResultCB')
identities, features, items = [], [], []
q = iq_obj.getTag('service')
if not q:
......@@ -318,6 +320,7 @@ class Connection:
self.dispatch('AGENT_INFO', (jid, identities, features, items))
def _DiscoverItemsCB(self, con, iq_obj):
gajim.log.debug('DiscoverItemsCB')
qp = iq_obj.getQueryPayload()
items = []
if not qp:
......@@ -331,10 +334,12 @@ class Connection:
self.dispatch('AGENT_INFO_ITEMS', (jid, items))
def _DiscoverInfoErrorCB(self, con, iq_obj):
gajim.log.debug('DiscoverInfoErrorCB')
jid = str(iq_obj.getFrom())
con.browseAgents(jid)
def _DiscoverInfoCB(self, con, iq_obj):
gajim.log.debug('DiscoverInfoCB')
# According to JEP-0030:
# For identity: category, name is mandatory, type is optional.
# For feature: var is mandatory
......@@ -358,6 +363,7 @@ class Connection:
self.connection.discoverItems(jid)
def _VersionCB(self, con, iq_obj):
gajim.log.debug('VersionCB')
f = iq_obj.getFrom()
iq_obj.setFrom(iq_obj.getTo())
iq_obj.setTo(f)
......@@ -371,6 +377,7 @@ class Connection:
self.connection.send(iq_obj)
def _VersionResultCB(self, con, iq_obj):
gajim.log.debug('VersionResultCB')
client_info = ''
os_info = ''
qp = iq_obj.getTag('query')
......@@ -382,6 +389,70 @@ class Connection:
os_info += qp.getTag('os').getData()
jid = iq_obj.getFrom().getStripped()
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):
"""Connect and authentificate to the Jabber server"""
......@@ -427,6 +498,8 @@ class Connection:
common.jabber.NS_VERSION)
con.registerHandler('iq',self._VersionResultCB,'result', \
common.jabber.NS_VERSION)
con.registerHandler('iq',self._MucOwnerCB,'result', \
common.jabber.NS_P_MUC_OWNER)
try:
con.connect()
except:
......@@ -691,6 +764,7 @@ class Connection:
if not self.connection:
return
p = common.jabber.Presence(to = '%s@%s/%s' % (room, server, nick))
p.setX(common.jabber.NS_P_MUC)
self.connection.send(p)
def send_gc_message(self, jid, msg):
......@@ -709,6 +783,13 @@ class Connection:
msg_iq.setSubject(subject)
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):
if not self.connection:
return
......@@ -742,6 +823,47 @@ class Connection:
iq.setID(id)
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):
if USE_GPG:
self.gpg.passphrase = passphrase
......
......@@ -1087,7 +1087,7 @@ class Account_modification_window:
self.plugin.sleeper_state[name] = \
self.plugin.sleeper_state[self.account]
#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]:
self.plugin.windows[name][kind][j].account = name
#upgrade account in systray
......@@ -1167,7 +1167,8 @@ class Account_modification_window:
if save_password:
gajim.connections[name].password = password
#update variables
self.plugin.windows[name] = {'infos': {}, 'chats': {}, 'gc': {}}
self.plugin.windows[name] = {'infos': {}, 'chats': {}, 'gc': {}, \
'gc_config': {}}
self.plugin.queues[name] = {}
gajim.connections[name].connected = 0
self.plugin.roster.groups[name] = {}
......@@ -1904,6 +1905,126 @@ class Service_discovery_window:
self.browse(server_address)
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:
'''ask for removing from gajim only or from gajim and server too
and do removing of the account given'''
......
......@@ -374,7 +374,7 @@ class Interface:
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, 'proxyport', array[8])
self.windows[name] = {'infos': {}, 'chats': {}, 'gc': {}}
self.windows[name] = {'infos': {}, 'chats': {}, 'gc': {}, 'gc_config': {}}
self.queues[name] = {}
gajim.connections[name].connected = 0
self.nicks[name] = array[1]
......@@ -433,6 +433,13 @@ class Interface:
self.windows[account]['gc'][jid].print_conversation(\
'%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):
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('GC_MSG', self.handle_event_gc_msg)
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('ROSTER_INFO', self.handle_event_roster_info)
......@@ -637,7 +645,7 @@ class Interface:
self.nicks = {}
self.sleeper_state = {} #whether we pass auto away / xa or not
for a in gajim.connections:
self.windows[a] = {'infos': {}, 'chats': {}, 'gc': {}}
self.windows[a] = {'infos': {}, 'chats': {}, 'gc': {}, 'gc_config': {}}
self.queues[a] = {}
self.nicks[a] = gajim.config.get_per('accounts', a, 'name')
self.sleeper_state[a] = 0 #0:don't use sleeper for this account
......
......@@ -57,6 +57,8 @@ class Groupchat_window(chat.Chat):
self.on_chat_notebook_switch_page)
self.xml.signal_connect('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.on_groupchat_window_key_press_event)
......@@ -234,6 +236,10 @@ class Groupchat_window(chat.Chat):
subject = self.xml.get_widget('subject_entry').get_text()
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):
"""When a key is pressed:
if enter is pressed without the shit key, message (if not empty) is sent
......
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment