diff --git a/data/glade/roster_window.glade b/data/glade/roster_window.glade
index 5e393ae45..16fb5bbb4 100644
--- a/data/glade/roster_window.glade
+++ b/data/glade/roster_window.glade
@@ -1,444 +1,338 @@
-
-
-
+
+
+
-
-
- 85
- 200
- Gajim
- GTK_WINDOW_TOPLEVEL
- GTK_WIN_POS_NONE
- False
- 200
- 400
- True
- False
- roster
- True
- False
- False
- GDK_WINDOW_TYPE_HINT_NORMAL
- GDK_GRAVITY_NORTH_WEST
- True
- False
-
-
-
-
-
-
-
-
- True
- False
- 0
-
-
-
-
- 0
- False
- False
-
-
-
-
-
- 2
- True
- True
- GTK_POLICY_NEVER
- GTK_POLICY_AUTOMATIC
- GTK_SHADOW_NONE
- GTK_CORNER_TOP_LEFT
-
-
-
- True
- True
- False
- False
- True
- True
- False
- False
- False
-
-
-
-
-
-
-
-
-
-
-
-
-
- 0
- True
- True
-
-
-
-
-
- True
- False
- True
-
-
-
- 0
- False
- True
-
-
-
-
-
-
+
+ 85
+ 200
+ Gajim
+ roster
+ 200
+ 400
+
+
+
+
+
+
+
+ True
+
+
+
+ False
+ False
+
+
+
+
+ True
+ True
+ 2
+ GTK_POLICY_NEVER
+ GTK_POLICY_AUTOMATIC
+
+
+ True
+ True
+ False
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ True
+
+
+
+ False
+ 2
+
+
+
+
+
diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py
index eaa6293c6..d1de9bdbc 100644
--- a/src/common/connection_handlers.py
+++ b/src/common/connection_handlers.py
@@ -46,6 +46,7 @@ VCARD_ARRIVED = 'vcard_arrived'
AGENT_REMOVED = 'agent_removed'
METACONTACTS_ARRIVED = 'metacontacts_arrived'
PRIVACY_ARRIVED = 'privacy_arrived'
+PEP_ACCESS_MODEL = 'pep_access_model'
HAS_IDLE = True
try:
import idle
@@ -1068,6 +1069,15 @@ class ConnectionVcard:
self.get_privacy_list('block')
# Ask metacontacts before roster
self.get_metacontacts()
+ elif self.awaiting_answers[id][0] == PEP_ACCESS_MODEL:
+ conf = iq_obj.getTag('pubsub').getTag('configure')
+ node = conf.getAttr('node')
+ form_tag = conf.getTag('x', namespace=common.xmpp.NS_DATA)
+ form = common.dataforms.ExtendForm(node=form_tag)
+ for field in form.iter_fields():
+ if field.var == 'pubsub#access_model':
+ self.dispatch('PEP_ACCESS_MODEL', (node, field.value))
+ break
del self.awaiting_answers[id]
diff --git a/src/common/pubsub.py b/src/common/pubsub.py
index c4ee908f7..acf3345dc 100644
--- a/src/common/pubsub.py
+++ b/src/common/pubsub.py
@@ -1,5 +1,7 @@
import xmpp
import gajim
+import dataforms
+import connection_handlers
class ConnectionPubSub:
def __init__(self):
@@ -92,3 +94,12 @@ class ConnectionPubSub:
cb(conn, stanza, *args, **kwargs)
except KeyError:
pass
+
+ def request_pb_configuration(self, jid, node):
+ query = xmpp.Iq('get', to=jid)
+ e = query.addChild('pubsub', namespace=xmpp.NS_PUBSUB_OWNER)
+ e = e.addChild('configure', {'node': node})
+ id = self.connection.getAnID()
+ query.setID(id)
+ self.awaiting_answers[id] = (connection_handlers.PEP_ACCESS_MODEL,)
+ self.connection.send(query)
diff --git a/src/common/xmpp/protocol.py b/src/common/xmpp/protocol.py
index 07bccf3da..ead233682 100644
--- a/src/common/xmpp/protocol.py
+++ b/src/common/xmpp/protocol.py
@@ -74,6 +74,7 @@ NS_PRIVACY ='jabber:iq:privacy'
NS_PRIVATE ='jabber:iq:private'
NS_PROFILE ='http://jabber.org/protocol/profile' # JEP-0154
NS_PUBSUB ='http://jabber.org/protocol/pubsub' # JEP-0060
+NS_PUBSUB_OWNER ='http://jabber.org/protocol/pubsub#owner' # JEP-0060
NS_REGISTER ='jabber:iq:register'
NS_ROSTER ='jabber:iq:roster'
NS_ROSTERX ='http://jabber.org/protocol/rosterx' # JEP-0144
diff --git a/src/config.py b/src/config.py
index e1bcfa062..1765e2ab7 100644
--- a/src/config.py
+++ b/src/config.py
@@ -3360,7 +3360,7 @@ class ZeroconfPropertiesWindow:
config['keyname'] = self.xml.get_widget('gpg_name_label').get_text().\
decode('utf-8')
- if config['keyname'] == '': #no key selected
+ if config['keyname'] == '': # no key selected
config['keyid'] = ''
config['savegpgpass'] = False
config['gpgpassword'] = ''
@@ -3430,3 +3430,65 @@ class ZeroconfPropertiesWindow:
st = widget.get_active()
w = self.xml.get_widget('gpg_password_entry')
w.set_sensitive(bool(st))
+
+class ManagePEPServicesWindow:
+ def __init__(self, account):
+ self.xml = gtkgui_helpers.get_glade('manage_pep_services_window.glade')
+ self.window = self.xml.get_widget('manage_pep_services_window')
+ self.window.set_transient_for(gajim.interface.roster.window)
+ self.xml.signal_autoconnect(self)
+ self.account = account
+
+ self.init_services()
+ self.window.show_all()
+
+ def on_manage_pep_services_window_destroy(self, widget):
+ '''close window'''
+ del gajim.interface.instances[self.account]['pep_services']
+
+ def cellrenderer_combo_edited(self, cellrenderer, path, new_text):
+ self.treestore[path][1] = new_text
+
+ def init_services(self):
+ treeview = self.xml.get_widget('services_treeview')
+ # service, access_model, group
+ self.treestore = gtk.ListStore(str, str, str)
+ treeview.set_model(self.treestore)
+
+ col = gtk.TreeViewColumn('Service')
+ treeview.append_column(col)
+
+ cellrenderer_text = gtk.CellRendererText()
+ col.pack_start(cellrenderer_text)
+ col.add_attribute(cellrenderer_text, 'text', 0)
+
+ col = gtk.TreeViewColumn('access model')
+ treeview.append_column(col)
+
+ model = gtk.ListStore(str)
+ model.append(['open'])
+ model.append(['presence'])
+ model.append(['roster'])
+ model.append(['whitelist'])
+ cellrenderer_combo = gtk.CellRendererCombo()
+ cellrenderer_combo.set_property('text-column', 0)
+ cellrenderer_combo.set_property('model', model)
+ cellrenderer_combo.set_property('has-entry', False)
+ cellrenderer_combo.set_property('editable', True)
+ cellrenderer_combo.connect('edited', self.cellrenderer_combo_edited)
+ col.pack_start(cellrenderer_combo)
+ col.add_attribute(cellrenderer_combo, 'text', 1)
+
+ our_jid = gajim.get_jid_from_account(self.account)
+ gajim.connections[self.account].discoverItems(our_jid)
+
+ def items_received(self, items):
+ our_jid = gajim.get_jid_from_account(self.account)
+ for item in items:
+ if 'jid' in item and item['jid'] == our_jid and 'node' in item:
+ # ask to have access model
+ gajim.connections[self.account].request_pb_configuration(
+ item['jid'], item['node'])
+
+ def new_service(self, node, model):
+ self.treestore.append([node, model, ''])
diff --git a/src/gajim.py b/src/gajim.py
index 15cb1b726..37970697d 100755
--- a/src/gajim.py
+++ b/src/gajim.py
@@ -934,6 +934,11 @@ class Interface:
def handle_event_agent_info_items(self, account, array):
#('AGENT_INFO_ITEMS', account, (agent, node, items))
+ our_jid = gajim.get_jid_from_account(account)
+ if gajim.interface.instances[account].has_key('pep_services') and \
+ array[0] == our_jid:
+ gajim.interface.instances[account]['pep_services'].items_received(
+ array[2])
try:
gajim.connections[account].services_cache.agent_items(array[0],
array[1], array[2])
@@ -1776,6 +1781,11 @@ class Interface:
_('You are already connected to this account with the same resource. Please type a new one'), input_str = gajim.connections[account].server_resource,
is_modal = False, ok_handler = on_ok)
+ def handle_event_pep_access_model(self, account, data):
+ # ('PEP_ACCESS_MODEL', account, (node, model))
+ if self.instances[account].has_key('pep_services'):
+ self.instances[account]['pep_services'].new_service(data[0], data[1])
+
def read_sleepy(self):
'''Check idle status and change that status if needed'''
if not self.sleeper.poll():
@@ -2102,6 +2112,7 @@ class Interface:
'SEARCH_FORM': self.handle_event_search_form,
'SEARCH_RESULT': self.handle_event_search_result,
'RESOURCE_CONFLICT': self.handle_event_resource_conflict,
+ 'PEP_ACCESS_MODEL': self.handle_event_pep_access_model,
}
gajim.handlers = self.handlers
diff --git a/src/roster_window.py b/src/roster_window.py
index fd62d3ef5..180315856 100644
--- a/src/roster_window.py
+++ b/src/roster_window.py
@@ -903,7 +903,8 @@ class RosterWindow:
add_new_contact_menuitem = self.xml.get_widget('add_new_contact_menuitem')
service_disco_menuitem = self.xml.get_widget('service_disco_menuitem')
advanced_menuitem = self.xml.get_widget('advanced_menuitem')
- profile_avatar_menuitem = self.xml.get_widget('profile_avatar_menuitem')
+ profile_avatar_menuitem = self.xml.get_widget('profile_avatar_menuitem')
+ pep_services_menuitem = self.xml.get_widget('pep_services_menuitem')
# destroy old advanced menus
for m in self.advanced_menus:
@@ -927,10 +928,10 @@ class RosterWindow:
self.new_chat_menuitem_handler_id)
self.new_chat_menuitem_handler_id = None
- if self.profile_avatar_menuitem_handler_id:
- profile_avatar_menuitem.handler_disconnect(
- self.profile_avatar_menuitem_handler_id)
- self.profile_avatar_menuitem_handler_id = None
+ if self.pep_services_menuitem_handler_id:
+ pep_services_menuitem.handler_disconnect(
+ self.pep_services_menuitem_handler_id)
+ self.pep_services_menuitem_handler_id = None
# remove the existing submenus
@@ -940,6 +941,7 @@ class RosterWindow:
new_chat_menuitem.remove_submenu()
advanced_menuitem.remove_submenu()
profile_avatar_menuitem.remove_submenu()
+ pep_services_menuitem.remove_submenu()
# remove the existing accelerator
if self.have_new_chat_accel:
@@ -1068,27 +1070,43 @@ class RosterWindow:
if len(connected_accounts_with_vcard) > 1:
# 2 or more accounts? make submenus
profile_avatar_sub_menu = gtk.Menu()
+ pep_services_sub_menu = gtk.Menu()
for account in connected_accounts_with_vcard:
# profile, avatar
- profile_avatar_item = gtk.MenuItem(_('of account %s') % account,
+ profile_avatar_item = gtk.MenuItem(_('of account %s') % account,
False)
profile_avatar_sub_menu.append(profile_avatar_item)
- profile_avatar_item.connect('activate',
+ profile_avatar_item.connect('activate',
self.on_profile_avatar_menuitem_activate, account)
+ # PEP services
+ pep_services_item = gtk.MenuItem(_('of account %s') % account,
+ False)
+ pep_services_sub_menu.append(pep_services_item)
+ pep_services_item.connect('activate',
+ self.on_pep_services_menuitem_activate, account)
profile_avatar_menuitem.set_submenu(profile_avatar_sub_menu)
profile_avatar_sub_menu.show_all()
+ pep_services_menuitem.set_submenu(pep_services_sub_menu)
+ pep_services_sub_menu.show_all()
elif len(connected_accounts_with_vcard) == 1: # user has only one account
account = connected_accounts_with_vcard[0]
# profile, avatar
if not self.profile_avatar_menuitem_handler_id:
self.profile_avatar_menuitem_handler_id = \
- profile_avatar_menuitem.connect('activate', self.\
- on_profile_avatar_menuitem_activate, account)
+ profile_avatar_menuitem.connect('activate',
+ self.on_profile_avatar_menuitem_activate, account)
+ # PEP services
+ if not self.pep_services_menuitem_handler_id:
+ self.pep_services_menuitem_handler_id = \
+ pep_services_menuitem.connect('activate',
+ self.on_pep_services_menuitem_activate, account)
if len(connected_accounts_with_vcard) == 0:
profile_avatar_menuitem.set_sensitive(False)
+ pep_services_menuitem.set_sensitive(False)
else:
profile_avatar_menuitem.set_sensitive(True)
+ pep_services_menuitem.set_sensitive(True)
newitem = gtk.ImageMenuItem(_('_Manage Bookmarks...'))
img = gtk.image_new_from_stock(gtk.STOCK_PREFERENCES,
@@ -3684,6 +3702,13 @@ class RosterWindow:
else:
gajim.interface.instances['preferences'] = config.PreferencesWindow()
+ def on_pep_services_menuitem_activate(self, widget, account):
+ if gajim.interface.instances[account].has_key('pep_services'):
+ gajim.interface.instances[account]['pep_services'].window.present()
+ else:
+ gajim.interface.instances[account]['pep_services'] = \
+ config.ManagePEPServicesWindow(account)
+
def on_add_new_contact(self, widget, account):
dialogs.AddNewContactWindow(account)
@@ -4840,6 +4865,7 @@ class RosterWindow:
self.service_disco_handler_id = False
self.new_chat_menuitem_handler_id = False
self.profile_avatar_menuitem_handler_id = False
+ self.pep_services_menuitem_handler_id = False
self.actions_menu_needs_rebuild = True
self.regroup = gajim.config.get('mergeaccounts')
if len(gajim.connections) < 2: # Do not merge accounts if only one exists