diff --git a/gajim/common/connection.py b/gajim/common/connection.py
index 42528cabb..3df254e84 100644
--- a/gajim/common/connection.py
+++ b/gajim/common/connection.py
@@ -792,11 +792,6 @@ class Connection(CommonConnection, ConnectionHandlers):
None, dialog_name='invalid-answer',
kwargs={'name': data[0], 'error': data[3]}))
return
- is_form = data[2]
- conf = data[1]
- app.nec.push_incoming_event(RegisterAgentInfoReceivedEvent(
- None, conn=self, agent=data[0], config=conf,
- is_form=is_form))
def _select_next_host(self, hosts):
"""
diff --git a/gajim/common/connection_handlers.py b/gajim/common/connection_handlers.py
index 941139488..58b1b231d 100644
--- a/gajim/common/connection_handlers.py
+++ b/gajim/common/connection_handlers.py
@@ -54,61 +54,6 @@ log = logging.getLogger('gajim.c.connection_handlers')
# kind of events we can wait for an answer
AGENT_REMOVED = 'agent_removed'
-
-class ConnectionDisco:
-
- def request_register_agent_info(self, agent):
- if not self.connection or self.connected < 2:
- return None
- iq = nbxmpp.Iq('get', nbxmpp.NS_REGISTER, to=agent)
- id_ = self.connection.getAnID()
- iq.setID(id_)
- # Wait the answer during 30 secondes
- self.awaiting_timeouts[app.idlequeue.current_time() + 30] = (id_,
- _('Registration information for transport %s has not arrived in '
- 'time') % agent)
- self.connection.SendAndCallForResponse(iq, self._ReceivedRegInfo,
- {'agent': agent})
-
- def _agent_registered_cb(self, con, resp, agent):
- if resp.getType() == 'result':
- app.nec.push_incoming_event(InformationEvent(
- None, dialog_name='agent-register-success', args=agent))
- self.get_module('Presence').subscribe(agent, auto_auth=True)
- self.agent_registrations[agent]['roster_push'] = True
- if self.agent_registrations[agent]['sub_received']:
- p = nbxmpp.Presence(agent, 'subscribed')
- p = self.add_sha(p)
- self.connection.send(p)
- if resp.getType() == 'error':
- app.nec.push_incoming_event(InformationEvent(
- None, dialog_name='agent-register-error',
- kwargs={'agent': agent,
- 'error': resp.getError(),
- 'error_msg': resp.getErrorMsg()}))
-
- def register_agent(self, agent, info, is_form=False):
- if not self.connection or self.connected < 2:
- return
- if is_form:
- iq = nbxmpp.Iq('set', nbxmpp.NS_REGISTER, to=agent)
- query = iq.setQuery()
- info.setAttr('type', 'submit')
- query.addChild(node=info)
- self.connection.SendAndCallForResponse(iq,
- self._agent_registered_cb, {'agent': agent})
- else:
- # fixed: blocking
- nbxmpp.features_nb.register(self.connection, agent, info,
- self._agent_registered_cb, {'agent': agent})
- self.agent_registrations[agent] = {'roster_push': False,
- 'sub_received': False}
-
- def _ReceivedRegInfo(self, con, resp, agent):
- nbxmpp.features_nb._ReceivedRegInfo(con, resp, agent)
- self._IqCB(con, resp)
-
-
# basic connection handlers used here and in zeroconf
class ConnectionHandlersBase:
def __init__(self):
@@ -443,7 +388,7 @@ class ConnectionHandlersBase:
return sess
-class ConnectionHandlers(ConnectionSocks5Bytestream, ConnectionDisco,
+class ConnectionHandlers(ConnectionSocks5Bytestream,
ConnectionHandlersBase,
ConnectionJingle, ConnectionIBBytestream):
def __init__(self):
diff --git a/gajim/common/connection_handlers_events.py b/gajim/common/connection_handlers_events.py
index 6c72a05c3..9acd6ecdb 100644
--- a/gajim/common/connection_handlers_events.py
+++ b/gajim/common/connection_handlers_events.py
@@ -868,10 +868,6 @@ class SignedInEvent(nec.NetworkIncomingEvent):
name = 'signed-in'
base_network_events = []
-class RegisterAgentInfoReceivedEvent(nec.NetworkIncomingEvent):
- name = 'register-agent-info-received'
- base_network_events = []
-
class FileRequestReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
name = 'file-request-received'
base_network_events = []
diff --git a/gajim/common/modules/register.py b/gajim/common/modules/register.py
index 6f52b57c5..e6586c9b5 100644
--- a/gajim/common/modules/register.py
+++ b/gajim/common/modules/register.py
@@ -31,6 +31,8 @@ class Register:
self.handlers = []
+ self.agent_registrations = {}
+
def change_password(self, password, success_cb, error_cb):
if not app.account_is_connected(self._account):
return
@@ -52,11 +54,87 @@ class Register:
if not nbxmpp.isResultNode(stanza):
error = stanza.getErrorMsg()
log.info('Error: %s', error)
- error_cb()(error)
+ if error_cb() is not None:
+ error_cb()(error)
else:
log.info('Password changed')
+ if success_cb() is not None:
+ success_cb()()
+
+ def register_agent(self, agent, form, is_form, success_cb, error_cb):
+ if not app.account_is_connected(self._account):
+ return
+
+ weak_success_cb = weakref.WeakMethod(success_cb)
+ weak_error_cb = weakref.WeakMethod(error_cb)
+
+ iq = nbxmpp.Iq('set', nbxmpp.NS_REGISTER, to=agent)
+ if is_form:
+ query = iq.setQuery()
+ form.setAttr('type', 'submit')
+ query.addChild(node=form)
+ else:
+ for field in form.keys():
+ iq.setTag('query').setTagData(field, form[field])
+
+ self._con.connection.SendAndCallForResponse(
+ iq, self._register_agent_response, {'agent': agent,
+ 'success_cb': weak_success_cb,
+ 'error_cb': weak_error_cb})
+
+ self.agent_registrations[agent] = {'roster_push': False,
+ 'sub_received': False}
+
+ def _register_agent_response(self, con, stanza, agent,
+ success_cb, error_cb):
+ if not nbxmpp.isResultNode(stanza):
+ error = stanza.getErrorMsg()
+ log.info('Error: %s', error)
+ if error_cb() is not None:
+ error_cb()(error)
+ return
+
+ self._con.get_module('Presence').subscribe(agent, auto_auth=True)
+
+ self.agent_registrations[agent]['roster_push'] = True
+ if self.agent_registrations[agent]['sub_received']:
+ self._con.get_module('Presence').subscribed(agent)
+
+ if success_cb() is not None:
success_cb()()
+ def get_register_form(self, jid, success_cb, error_cb):
+ if not app.account_is_connected(self._account):
+ return
+
+ weak_success_cb = weakref.WeakMethod(success_cb)
+ weak_error_cb = weakref.WeakMethod(error_cb)
+
+ iq = nbxmpp.Iq('get', nbxmpp.NS_REGISTER, to=jid)
+ self._con.connection.SendAndCallForResponse(
+ iq, self._register_info_response, {'success_cb': weak_success_cb,
+ 'error_cb': weak_error_cb})
+
+ def _register_info_response(self, con, stanza, success_cb, error_cb):
+ if not nbxmpp.isResultNode(stanza):
+ error = stanza.getErrorMsg()
+ log.info('Error: %s', error)
+ if error_cb() is not None:
+ error_cb()(error)
+ else:
+ log.info('Register form received')
+ form = stanza.getQuery().getTag('x', namespace=nbxmpp.NS_DATA)
+ is_form = form is not None
+ if not is_form:
+ form = {}
+ for field in stanza.getQueryPayload():
+ if not isinstance(field, nbxmpp.Node):
+ continue
+ form[field.getName()] = field.getData()
+
+ if success_cb() is not None:
+ success_cb()(form, is_form)
+
def get_instance(*args, **kwargs):
return Register(*args, **kwargs), 'Register'
diff --git a/gajim/config.py b/gajim/config.py
index 301812e54..e4928b4d8 100644
--- a/gajim/config.py
+++ b/gajim/config.py
@@ -1486,57 +1486,6 @@ class FakeDataForm(Gtk.Table, object):
self.infos[name] = self.entries[name].get_text()
return self.infos
-class ServiceRegistrationWindow:
- """
- Class for Service registration window. Window that appears when we want to
- subscribe to a service if is_form we use dataforms_widget else we use
- service_registarion_window
- """
- def __init__(self, service, infos, account, is_form):
- self.service = service
- self.account = account
- self.is_form = is_form
- self.xml = gtkgui_helpers.get_gtk_builder('service_registration_window.ui')
- self.window = self.xml.get_object('service_registration_window')
- self.window.set_transient_for(app.interface.roster.window)
- if self.is_form:
- dataform = dataforms.ExtendForm(node = infos)
- self.data_form_widget = dataforms_widget.DataFormWidget(dataform)
- if self.data_form_widget.title:
- self.window.set_title('%s - Gajim' % self.data_form_widget.title)
- grid = self.xml.get_object('grid')
- grid.attach(self.data_form_widget, 0, 0, 2, 1)
- else:
- if 'registered' in infos:
- self.window.set_title(_('Edit %s') % service)
- else:
- self.window.set_title(_('Register to %s') % service)
- self.data_form_widget = FakeDataForm(infos)
- grid = self.xml.get_object('grid')
- grid.attach(self.data_form_widget, 0, 0, 2, 1)
-
- self.xml.connect_signals(self)
- self.window.show_all()
-
- def on_cancel_button_clicked(self, widget):
- self.window.destroy()
-
- def on_ok_button_clicked(self, widget):
- # send registration info to the core
- if self.is_form:
- form = self.data_form_widget.data_form
- app.connections[self.account].register_agent(self.service,
- form, True) # True is for is_form
- else:
- infos = self.data_form_widget.get_infos()
- if 'instructions' in infos:
- del infos['instructions']
- if 'registered' in infos:
- del infos['registered']
- app.connections[self.account].register_agent(self.service, infos)
-
- self.window.destroy()
-
class GroupchatConfigWindow:
def __init__(self, account, room_jid, form=None):
diff --git a/gajim/data/gui/service_registration_window.ui b/gajim/data/gui/service_registration_window.ui
deleted file mode 100644
index a7ff3e995..000000000
--- a/gajim/data/gui/service_registration_window.ui
+++ /dev/null
@@ -1,96 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/gajim/disco.py b/gajim/disco.py
index af0a96c0a..4fe38e86f 100644
--- a/gajim/disco.py
+++ b/gajim/disco.py
@@ -59,6 +59,7 @@ from gajim import groups
from gajim import adhoc_commands
from gajim import search_window
from gajim import gui_menu_builder
+from gajim.gtk import ServiceRegistration
from gajim.common import app
import nbxmpp
@@ -1355,8 +1356,8 @@ class ToplevelAgentBrowser(AgentBrowser):
return
jid = model[iter_][0]
if jid:
- app.connections[self.account].request_register_agent_info(jid)
- self.window.destroy(chain = True)
+ ServiceRegistration(self.account, jid)
+ self.window.destroy(chain=True)
def on_join_button_clicked(self, widget):
"""
diff --git a/gajim/gtk/__init__.py b/gajim/gtk/__init__.py
index e21fc3645..c62ff0cc3 100644
--- a/gajim/gtk/__init__.py
+++ b/gajim/gtk/__init__.py
@@ -66,3 +66,4 @@ from gajim.gtk.bookmarks import ManageBookmarksWindow
from gajim.gtk.profile import ProfileWindow
from gajim.gtk.features import FeaturesDialog
from gajim.gtk.account_wizard import AccountCreationWizard
+from gajim.gtk.service_registration import ServiceRegistration
diff --git a/gajim/gtk/add_contact.py b/gajim/gtk/add_contact.py
index f094f07e7..6609cbf6f 100644
--- a/gajim/gtk/add_contact.py
+++ b/gajim/gtk/add_contact.py
@@ -209,7 +209,8 @@ class AddNewContactWindow(Gtk.ApplicationWindow):
model = self.protocol_jid_combobox.get_model()
row = self.protocol_jid_combobox.get_active()
jid = model[row][0]
- app.connections[self.account].request_register_agent_info(jid)
+ from gajim.gtk import ServiceRegistration
+ ServiceRegistration(self.account, jid)
def _on_key_press(self, widget, event):
if event.keyval == Gdk.KEY_Escape:
diff --git a/gajim/gtk/dialogs.py b/gajim/gtk/dialogs.py
index ea3feb5bc..62b693ae6 100644
--- a/gajim/gtk/dialogs.py
+++ b/gajim/gtk/dialogs.py
@@ -13,10 +13,10 @@
# along with Gajim. If not, see .
from gi.repository import Gtk
-from gi.repository import Gdk
from gajim.common import app
from gajim.common import helpers
+from gajim.common.modules import dataforms
from gajim.gtk.util import get_builder
from gajim.gtk.util import load_icon
diff --git a/gajim/gtk/service_registration.py b/gajim/gtk/service_registration.py
new file mode 100644
index 000000000..6db36b628
--- /dev/null
+++ b/gajim/gtk/service_registration.py
@@ -0,0 +1,198 @@
+# This file is part of Gajim.
+#
+# Gajim is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published
+# by the Free Software Foundation; version 3 only.
+#
+# Gajim is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Gajim. If not, see .
+
+import logging
+from enum import IntEnum
+
+from gi.repository import Gtk
+
+from gajim.common import app
+from gajim.common.modules import dataforms
+
+log = logging.getLogger('gajim.gtk.registration')
+
+
+class Page(IntEnum):
+ REQUEST = 0
+ FORM = 1
+ SENDING = 2
+ SUCCESS = 3
+ ERROR = 4
+
+
+class ServiceRegistration(Gtk.Assistant):
+ def __init__(self, account, agent):
+ Gtk.Assistant.__init__(self)
+
+ self._con = app.connections[account]
+ self._agent = agent
+ self._account = account
+ self._data_form_widget = None
+ self._is_form = None
+
+ self.set_application(app.app)
+ self.set_resizable(True)
+ self.set_position(Gtk.WindowPosition.CENTER)
+
+ self.set_default_size(500, 300)
+ self.get_style_context().add_class('dialog-margin')
+
+ request = RequestPage()
+ self.append_page(request)
+ self.set_page_type(request, Gtk.AssistantPageType.INTRO)
+
+ form = FormPage()
+ self.append_page(form)
+ self.set_page_type(form, Gtk.AssistantPageType.INTRO)
+ self.set_page_complete(form, True)
+
+ sending = SendingPage()
+ self.append_page(sending)
+ self.set_page_type(sending, Gtk.AssistantPageType.PROGRESS)
+
+ success = SuccessfulPage()
+ self.append_page(success)
+ self.set_page_type(success, Gtk.AssistantPageType.SUMMARY)
+ self.set_page_complete(success, True)
+
+ error = ErrorPage()
+ self.append_page(error)
+ self.set_page_type(error, Gtk.AssistantPageType.SUMMARY)
+ self.set_page_complete(error, True)
+
+ self.connect('prepare', self._on_page_change)
+ self.connect('cancel', self._on_cancel)
+ self.connect('close', self._on_cancel)
+
+ self.show_all()
+
+ def _on_page_change(self, assistant, page):
+ if self.get_current_page() == Page.REQUEST:
+ self._con.get_module('Register').get_register_form(
+ self._agent, self._on_get_success, self._on_error)
+ elif self.get_current_page() == Page.SENDING:
+ self._register()
+ self.commit()
+ pass
+
+ def _on_get_success(self, form, is_form):
+ log.info('Show Form page')
+ self._is_form = is_form
+ if is_form:
+ from gajim import dataforms_widget
+ dataform = dataforms.ExtendForm(node=form)
+ self._data_form_widget = dataforms_widget.DataFormWidget(dataform)
+ if self._data_form_widget.title:
+ self.set_title('%s - Gajim' % self._data_form_widget.title)
+ else:
+ if 'registered' in form:
+ self.set_title(_('Edit %s') % self._agent)
+ else:
+ self.set_title(_('Register to %s') % self._agent)
+ from gajim import config
+ self._data_form_widget = config.FakeDataForm(form)
+
+ page = self.get_nth_page(Page.FORM)
+ page.pack_start(self._data_form_widget, True, True, 0)
+ self._data_form_widget.show()
+ self.set_current_page(Page.FORM)
+
+ def _on_error(self, error_text):
+ log.info('Show Error page')
+ page = self.get_nth_page(Page.ERROR)
+ page.set_text(error_text)
+ self.set_current_page(Page.ERROR)
+
+ def _on_cancel(self, widget):
+ self.destroy()
+
+ def _register(self):
+ log.info('Show Sending page')
+ if self._is_form:
+ form = self._data_form_widget.data_form
+ else:
+ form = self._data_form_widget.get_infos()
+ if 'instructions' in form:
+ del form['instructions']
+ if 'registered' in form:
+ del form['registered']
+
+ self._con.get_module('Register').register_agent(
+ self._agent,
+ form,
+ self._is_form,
+ self._on_register_success,
+ self._on_error)
+
+ def _on_register_success(self):
+ log.info('Show Success page')
+ self.set_current_page(Page.SUCCESS)
+
+
+class RequestPage(Gtk.Box):
+ def __init__(self):
+ super().__init__(orientation=Gtk.Orientation.VERTICAL)
+ self.set_spacing(18)
+ spinner = Gtk.Spinner()
+ self.pack_start(spinner, True, True, 0)
+ spinner.start()
+
+
+class SendingPage(RequestPage):
+ def __init__(self):
+ super().__init__()
+
+
+class FormPage(Gtk.Box):
+ def __init__(self):
+ super().__init__(orientation=Gtk.Orientation.VERTICAL)
+
+
+class SuccessfulPage(Gtk.Box):
+ def __init__(self):
+ super().__init__(orientation=Gtk.Orientation.VERTICAL)
+ self.set_spacing(12)
+ self.set_homogeneous(True)
+
+ icon = Gtk.Image.new_from_icon_name('object-select-symbolic',
+ Gtk.IconSize.DIALOG)
+ icon.get_style_context().add_class('success-color')
+ icon.set_valign(Gtk.Align.END)
+ label = Gtk.Label(label=_('Registration successful'))
+ label.get_style_context().add_class('bold16')
+ label.set_valign(Gtk.Align.START)
+
+ self.add(icon)
+ self.add(label)
+
+
+class ErrorPage(Gtk.Box):
+ def __init__(self):
+ super().__init__(orientation=Gtk.Orientation.VERTICAL)
+ self.set_spacing(12)
+ self.set_homogeneous(True)
+
+ icon = Gtk.Image.new_from_icon_name('dialog-error-symbolic',
+ Gtk.IconSize.DIALOG)
+ icon.get_style_context().add_class('error-color')
+ icon.set_valign(Gtk.Align.END)
+ self._label = Gtk.Label()
+ self._label.get_style_context().add_class('bold16')
+ self._label.set_valign(Gtk.Align.START)
+
+ self.add(icon)
+ self.add(self._label)
+
+ def set_text(self, text):
+ self._label.set_text(text)
diff --git a/gajim/gui_interface.py b/gajim/gui_interface.py
index d24bae907..f86bebbab 100644
--- a/gajim/gui_interface.py
+++ b/gajim/gui_interface.py
@@ -580,17 +580,6 @@ class Interface:
'unsubscribed', 'gajim-unsubscribed',
event_type, obj.jid)
- @staticmethod
- def handle_event_register_agent_info(obj):
- # ('REGISTER_AGENT_INFO', account, (agent, infos, is_form))
- # info in a dataform if is_form is True
- if obj.is_form or 'instructions' in obj.config:
- config.ServiceRegistrationWindow(obj.agent, obj.config,
- obj.conn.name, obj.is_form)
- else:
- ErrorDialog(_('Contact with "%s" cannot be established') % \
- obj.agent, _('Check your connection or try again later.'))
-
def handle_event_gc_config(self, obj):
#('GC_CONFIG', account, (jid, form_node)) config is a dict
account = obj.conn.name
@@ -1565,7 +1554,6 @@ class Interface:
'password-required': [self.handle_event_password_required],
'plain-connection': [self.handle_event_plain_connection],
'presence-received': [self.handle_event_presence],
- 'register-agent-info-received': [self.handle_event_register_agent_info],
'roster-info': [self.handle_event_roster_info],
'roster-item-exchange-received': \
[self.handle_event_roster_item_exchange],
diff --git a/gajim/roster_window.py b/gajim/roster_window.py
index f53c9a1b7..928110cbd 100644
--- a/gajim/roster_window.py
+++ b/gajim/roster_window.py
@@ -71,6 +71,7 @@ from gajim.gtk import AddNewContactWindow
from gajim.gtk import ManagePEPServicesWindow
from gajim.gtk import ManageBookmarksWindow
from gajim.gtk import AccountCreationWizard
+from gajim.gtk import ServiceRegistration
from gajim.common.const import AvatarSize
@@ -2790,7 +2791,7 @@ class RosterWindow:
"""
When we want to modify the agent registration
"""
- app.connections[account].request_register_agent_info(contact.jid)
+ ServiceRegistration(account, contact.jid)
def on_remove_agent(self, widget, list_):
"""