| ... |
... |
@@ -12,218 +12,192 @@ |
|
12
|
12
|
# You should have received a copy of the GNU General Public License
|
|
13
|
13
|
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
|
14
|
14
|
|
|
|
15
|
+from __future__ import annotations
|
|
|
16
|
+
|
|
|
17
|
+from typing import Any
|
|
|
18
|
+from typing import Literal
|
|
|
19
|
+from typing import Optional
|
|
|
20
|
+from typing import overload
|
|
|
21
|
+
|
|
15
|
22
|
import logging
|
|
16
|
|
-from enum import IntEnum
|
|
17
|
23
|
|
|
18
|
24
|
from gi.repository import Gtk
|
|
19
|
25
|
|
|
20
|
26
|
from nbxmpp.errors import StanzaError
|
|
21
|
27
|
from nbxmpp.errors import MalformedStanzaError
|
|
22
|
28
|
from nbxmpp.errors import RegisterStanzaError
|
|
|
29
|
+from nbxmpp.protocol import JID
|
|
|
30
|
+from nbxmpp.task import Task
|
|
23
|
31
|
|
|
24
|
32
|
from gajim.common import app
|
|
25
|
33
|
from gajim.common.i18n import _
|
|
26
|
34
|
|
|
|
35
|
+from .assistant import Assistant
|
|
|
36
|
+from .assistant import ErrorPage
|
|
|
37
|
+from .assistant import Page
|
|
|
38
|
+from .assistant import ProgressPage
|
|
|
39
|
+from .assistant import SuccessPage
|
|
27
|
40
|
from .dataform import DataFormWidget
|
|
28
|
41
|
|
|
29
|
|
-log = logging.getLogger('gajim.gui.registration')
|
|
|
42
|
+log = logging.getLogger('gajim.gui.service_registration')
|
|
30
|
43
|
|
|
31
|
44
|
|
|
32
|
|
-class Page(IntEnum):
|
|
33
|
|
- REQUEST = 0
|
|
34
|
|
- FORM = 1
|
|
35
|
|
- SENDING = 2
|
|
36
|
|
- SUCCESS = 3
|
|
37
|
|
- ERROR = 4
|
|
|
45
|
+class ServiceRegistration(Assistant):
|
|
|
46
|
+ def __init__(self, account: str, address: JID) -> None:
|
|
|
47
|
+ Assistant.__init__(self, width= 600, height=400)
|
|
|
48
|
+ self.account = account
|
|
38
|
49
|
|
|
|
50
|
+ self._client = app.get_client(account)
|
|
|
51
|
+ self._service = address
|
|
39
|
52
|
|
|
40
|
|
-class ServiceRegistration(Gtk.Assistant):
|
|
41
|
|
- def __init__(self, account, address):
|
|
42
|
|
- Gtk.Assistant.__init__(self)
|
|
43
|
|
- self.account = account
|
|
|
53
|
+ self.add_button('register', _('Register'), 'suggested-action')
|
|
|
54
|
+ self.add_button('close', _('Close'))
|
|
|
55
|
+ self.add_button('back', _('Back'))
|
|
44
|
56
|
|
|
45
|
|
- self._con = app.connections[account]
|
|
46
|
|
- self._agent = address
|
|
47
|
|
- self._data_form_widget = None
|
|
|
57
|
+ self.set_button_visible_func(self._visible_func)
|
|
48
|
58
|
|
|
49
|
|
- self.set_application(app.app)
|
|
50
|
|
- self.set_resizable(True)
|
|
51
|
|
- self.set_position(Gtk.WindowPosition.CENTER)
|
|
|
59
|
+ self.add_pages({
|
|
|
60
|
+ 'form': Form(),
|
|
|
61
|
+ })
|
|
52
|
62
|
|
|
53
|
|
- self.set_default_size(600, 400)
|
|
54
|
|
- self.get_style_context().add_class('dialog-margin')
|
|
|
63
|
+ self.add_default_page('error')
|
|
|
64
|
+ self.add_default_page('progress')
|
|
|
65
|
+ self.add_default_page('success')
|
|
55
|
66
|
|
|
56
|
|
- self._add_page(RequestPage())
|
|
57
|
|
- self._add_page(FormPage())
|
|
58
|
|
- self._add_page(SendingPage())
|
|
59
|
|
- self._add_page(SuccessfulPage())
|
|
60
|
|
- self._add_page(ErrorPage())
|
|
|
67
|
+ self.get_page('error').set_title(_('Registration failed'))
|
|
|
68
|
+ self.get_page('error').set_heading(_('Registration failed'))
|
|
61
|
69
|
|
|
62
|
|
- self.connect('prepare', self._on_page_change)
|
|
63
|
|
- self.connect('cancel', self._on_cancel)
|
|
64
|
|
- self.connect('close', self._on_cancel)
|
|
|
70
|
+ self.connect('button-clicked', self._on_button_clicked)
|
|
65
|
71
|
|
|
66
|
|
- self._remove_sidebar()
|
|
67
|
72
|
self.show_all()
|
|
68
|
73
|
|
|
69
|
|
- def _add_page(self, page):
|
|
70
|
|
- self.append_page(page)
|
|
71
|
|
- self.set_page_type(page, page.type_)
|
|
72
|
|
- self.set_page_title(page, page.title)
|
|
73
|
|
- self.set_page_complete(page, page.complete)
|
|
74
|
|
-
|
|
75
|
|
- def _remove_sidebar(self):
|
|
76
|
|
- main_box = self.get_children()[0]
|
|
77
|
|
- sidebar = main_box.get_children()[0]
|
|
78
|
|
- main_box.remove(sidebar)
|
|
79
|
|
-
|
|
80
|
|
- def _on_page_change(self, _assistant, _page):
|
|
81
|
|
- if self.get_current_page() == Page.REQUEST:
|
|
82
|
|
- self._con.get_module('Register').request_register_form(
|
|
83
|
|
- self._agent, callback=self._on_register_form)
|
|
84
|
|
- elif self.get_current_page() == Page.SENDING:
|
|
|
74
|
+ self._request_form()
|
|
|
75
|
+
|
|
|
76
|
+ @overload
|
|
|
77
|
+ def get_page(self, name: Literal['form']) -> Form: ...
|
|
|
78
|
+ @overload
|
|
|
79
|
+ def get_page(self, name: Literal['success']) -> SuccessPage: ...
|
|
|
80
|
+ @overload
|
|
|
81
|
+ def get_page(self, name: Literal['error']) -> ErrorPage: ...
|
|
|
82
|
+ @overload
|
|
|
83
|
+ def get_page(self, name: Literal['progress']) -> ProgressPage: ...
|
|
|
84
|
+
|
|
|
85
|
+ def get_page(self, name: str) -> Page:
|
|
|
86
|
+ return self._pages[name]
|
|
|
87
|
+
|
|
|
88
|
+ @staticmethod
|
|
|
89
|
+ def _visible_func(_assistant: Assistant, page_name: str) -> list[str]:
|
|
|
90
|
+ if page_name == 'form':
|
|
|
91
|
+ return ['close', 'register']
|
|
|
92
|
+
|
|
|
93
|
+ if page_name == 'progress':
|
|
|
94
|
+ return []
|
|
|
95
|
+
|
|
|
96
|
+ if page_name == 'success':
|
|
|
97
|
+ return ['close']
|
|
|
98
|
+
|
|
|
99
|
+ if page_name == 'error':
|
|
|
100
|
+ return ['back', 'close']
|
|
|
101
|
+ raise ValueError(f'page {page_name} unknown')
|
|
|
102
|
+
|
|
|
103
|
+ def _on_button_clicked(self, _page: Gtk.Widget, button_name: str) -> None:
|
|
|
104
|
+ if button_name == 'register':
|
|
85
|
105
|
self._register()
|
|
86
|
|
- self.commit()
|
|
87
|
106
|
|
|
88
|
|
- def _on_register_form(self, task):
|
|
|
107
|
+ if button_name == 'back':
|
|
|
108
|
+ self.show_page('form', Gtk.StackTransitionType.SLIDE_RIGHT)
|
|
|
109
|
+
|
|
|
110
|
+ if button_name == 'close':
|
|
|
111
|
+ self.destroy()
|
|
|
112
|
+
|
|
|
113
|
+ def _request_form(self) -> None:
|
|
|
114
|
+ self.get_page('progress').set_title(_('Requesting Register Form'))
|
|
|
115
|
+ self.get_page('progress').set_text(
|
|
|
116
|
+ _('Requesting register form from server…'))
|
|
|
117
|
+ self.show_page('progress')
|
|
|
118
|
+
|
|
|
119
|
+ self._client.get_module('Register').request_register_form(
|
|
|
120
|
+ self._service, callback=self._on_register_form)
|
|
|
121
|
+
|
|
|
122
|
+ def _on_register_form(self, task: Task) -> None:
|
|
89
|
123
|
try:
|
|
90
|
124
|
result = task.finish()
|
|
91
|
125
|
except (StanzaError, MalformedStanzaError) as error:
|
|
92
|
|
- self.get_nth_page(Page.ERROR).set_text(error.get_text())
|
|
93
|
|
- self.set_current_page(Page.ERROR)
|
|
|
126
|
+ self.get_page('error').set_text(error.get_text())
|
|
|
127
|
+ self.show_page('error')
|
|
94
|
128
|
return
|
|
95
|
129
|
|
|
96
|
130
|
form = result.form
|
|
97
|
131
|
if result.form is None:
|
|
98
|
132
|
form = result.fields_form
|
|
99
|
133
|
|
|
100
|
|
- self._data_form_widget = DataFormWidget(form)
|
|
101
|
|
- self._data_form_widget.connect('is-valid', self._on_is_valid)
|
|
102
|
|
- self._data_form_widget.validate()
|
|
103
|
|
- self.get_nth_page(Page.FORM).set_form(self._data_form_widget)
|
|
104
|
|
- self.set_current_page(Page.FORM)
|
|
|
134
|
+ self.get_page('form').add_form(form)
|
|
|
135
|
+ self.show_page('form')
|
|
105
|
136
|
|
|
106
|
|
- def _on_is_valid(self, _widget, is_valid):
|
|
107
|
|
- self.set_page_complete(self.get_nth_page(Page.FORM), is_valid)
|
|
|
137
|
+ def _register(self) -> None:
|
|
|
138
|
+ self.get_page('progress').set_title(_('Registering…'))
|
|
|
139
|
+ self.get_page('progress').set_text(_('Registering…'))
|
|
|
140
|
+ self.show_page('progress')
|
|
108
|
141
|
|
|
109
|
|
- def _on_cancel(self, _widget):
|
|
110
|
|
- self.destroy()
|
|
111
|
|
-
|
|
112
|
|
- def _register(self):
|
|
113
|
|
- form = self._data_form_widget.get_submit_form()
|
|
114
|
|
- self._con.get_module('Register').submit_register_form(
|
|
|
142
|
+ form = self.get_page('form').get_submit_form()
|
|
|
143
|
+ self._client.get_module('Register').submit_register_form(
|
|
115
|
144
|
form,
|
|
116
|
|
- self._agent,
|
|
|
145
|
+ self._service,
|
|
117
|
146
|
callback=self._on_register_result)
|
|
118
|
147
|
|
|
119
|
|
- def _on_register_result(self, task):
|
|
|
148
|
+ def _on_register_result(self, task: Task) -> None:
|
|
120
|
149
|
try:
|
|
121
|
150
|
task.finish()
|
|
122
|
151
|
except (StanzaError,
|
|
123
|
152
|
MalformedStanzaError,
|
|
124
|
153
|
RegisterStanzaError) as error:
|
|
125
|
|
- self.get_nth_page(Page.ERROR).set_text(error.get_text())
|
|
126
|
|
- self.set_current_page(Page.ERROR)
|
|
|
154
|
+ self.get_page('error').set_text(error.get_text())
|
|
|
155
|
+ self.show_page('error')
|
|
127
|
156
|
return
|
|
128
|
157
|
|
|
129
|
|
- self.set_current_page(Page.SUCCESS)
|
|
130
|
|
-
|
|
131
|
|
-
|
|
132
|
|
-class RequestPage(Gtk.Box):
|
|
133
|
|
-
|
|
134
|
|
- type_ = Gtk.AssistantPageType.INTRO
|
|
135
|
|
- title = _('Register')
|
|
136
|
|
- complete = False
|
|
137
|
|
-
|
|
138
|
|
- def __init__(self):
|
|
139
|
|
- super().__init__(orientation=Gtk.Orientation.VERTICAL)
|
|
140
|
|
- self.set_spacing(18)
|
|
141
|
|
- spinner = Gtk.Spinner()
|
|
142
|
|
- self.pack_start(spinner, True, True, 0)
|
|
143
|
|
- spinner.start()
|
|
|
158
|
+ self.get_page('success').set_title(_('Registration successful'))
|
|
|
159
|
+ self.get_page('success').set_text(_('Registration successful'))
|
|
|
160
|
+ self.show_page('success')
|
|
144
|
161
|
|
|
145
|
162
|
|
|
146
|
|
-class SendingPage(RequestPage):
|
|
|
163
|
+class Form(Page):
|
|
|
164
|
+ def __init__(self) -> None:
|
|
|
165
|
+ Page.__init__(self)
|
|
|
166
|
+ self.title = _('Register')
|
|
|
167
|
+ self.complete = False
|
|
147
|
168
|
|
|
148
|
|
- type_ = Gtk.AssistantPageType.PROGRESS
|
|
149
|
|
- title = _('Register')
|
|
150
|
|
- complete = False
|
|
151
|
|
-
|
|
152
|
|
-
|
|
153
|
|
-class FormPage(Gtk.Box):
|
|
154
|
|
-
|
|
155
|
|
- type_ = Gtk.AssistantPageType.INTRO
|
|
156
|
|
- title = _('Register')
|
|
157
|
|
- complete = True
|
|
158
|
|
-
|
|
159
|
|
- def __init__(self):
|
|
160
|
|
- super().__init__(orientation=Gtk.Orientation.VERTICAL)
|
|
161
|
|
- self._form = None
|
|
162
|
|
- self._label = Gtk.Label()
|
|
163
|
|
- self._label.set_no_show_all(True)
|
|
164
|
|
- self._label.get_style_context().add_class('error-color')
|
|
165
|
|
- self.pack_end(self._label, False, False, 0)
|
|
166
|
|
-
|
|
167
|
|
- def set_form(self, form, error_text=None):
|
|
168
|
|
- if self._form is not None:
|
|
169
|
|
- self.remove(self._form)
|
|
170
|
|
- self._form.destroy()
|
|
171
|
|
- self._label.hide()
|
|
172
|
|
- self._form = form
|
|
173
|
|
-
|
|
174
|
|
- if error_text is not None:
|
|
175
|
|
- self._label.set_text(error_text)
|
|
176
|
|
- self._label.show()
|
|
177
|
|
-
|
|
178
|
|
- self.pack_start(form, True, True, 0)
|
|
179
|
|
- self._form.show_all()
|
|
180
|
|
-
|
|
181
|
|
-
|
|
182
|
|
-class SuccessfulPage(Gtk.Box):
|
|
183
|
|
-
|
|
184
|
|
- type_ = Gtk.AssistantPageType.SUMMARY
|
|
185
|
|
- title = _('Registration successful')
|
|
186
|
|
- complete = True
|
|
187
|
|
-
|
|
188
|
|
- def __init__(self):
|
|
189
|
|
- super().__init__(orientation=Gtk.Orientation.VERTICAL)
|
|
190
|
|
- self.set_spacing(12)
|
|
191
|
|
- self.set_homogeneous(True)
|
|
192
|
|
-
|
|
193
|
|
- icon = Gtk.Image.new_from_icon_name('object-select-symbolic',
|
|
194
|
|
- Gtk.IconSize.DIALOG)
|
|
195
|
|
- icon.get_style_context().add_class('success-color')
|
|
196
|
|
- icon.set_valign(Gtk.Align.END)
|
|
197
|
|
- label = Gtk.Label(label=_('Registration successful'))
|
|
198
|
|
- label.get_style_context().add_class('bold16')
|
|
199
|
|
- label.set_valign(Gtk.Align.START)
|
|
200
|
|
-
|
|
201
|
|
- self.add(icon)
|
|
202
|
|
- self.add(label)
|
|
203
|
|
-
|
|
204
|
|
-
|
|
205
|
|
-class ErrorPage(Gtk.Box):
|
|
206
|
|
-
|
|
207
|
|
- type_ = Gtk.AssistantPageType.SUMMARY
|
|
208
|
|
- title = _('Registration failed')
|
|
209
|
|
- complete = True
|
|
210
|
|
-
|
|
211
|
|
- def __init__(self):
|
|
212
|
|
- super().__init__(orientation=Gtk.Orientation.VERTICAL)
|
|
213
|
|
- self.set_spacing(12)
|
|
214
|
|
- self.set_homogeneous(True)
|
|
|
169
|
+ self._dataform_widget: Optional[DataFormWidget] = None
|
|
|
170
|
+ self.show_all()
|
|
215
|
171
|
|
|
216
|
|
- icon = Gtk.Image.new_from_icon_name('dialog-error-symbolic',
|
|
217
|
|
- Gtk.IconSize.DIALOG)
|
|
218
|
|
- icon.get_style_context().add_class('error-color')
|
|
219
|
|
- icon.set_valign(Gtk.Align.END)
|
|
220
|
|
- self._label = Gtk.Label()
|
|
221
|
|
- self._label.set_valign(Gtk.Align.START)
|
|
222
|
|
- self._label.set_max_width_chars(50)
|
|
223
|
|
- self._label.set_line_wrap(True)
|
|
|
172
|
+ def add_form(self, form: Any) -> None:
|
|
|
173
|
+ self.remove_form()
|
|
|
174
|
+
|
|
|
175
|
+ options = {
|
|
|
176
|
+ 'form-width': 350,
|
|
|
177
|
+ 'entry-activates-default': True
|
|
|
178
|
+ }
|
|
|
179
|
+ self._dataform_widget = DataFormWidget(form, options)
|
|
|
180
|
+ self._dataform_widget.set_propagate_natural_height(True)
|
|
|
181
|
+ self._dataform_widget.connect('is-valid', self._on_is_valid)
|
|
|
182
|
+ self._dataform_widget.validate()
|
|
|
183
|
+ self._dataform_widget.show_all()
|
|
|
184
|
+ self.add(self._dataform_widget)
|
|
|
185
|
+
|
|
|
186
|
+ def _on_is_valid(self, _widget: DataFormWidget, is_valid: bool) -> None:
|
|
|
187
|
+ self.complete = is_valid
|
|
|
188
|
+ self.update_page_complete()
|
|
|
189
|
+
|
|
|
190
|
+ def get_submit_form(self) -> Any:
|
|
|
191
|
+ assert self._dataform_widget is not None
|
|
|
192
|
+ return self._dataform_widget.get_submit_form()
|
|
|
193
|
+
|
|
|
194
|
+ def remove_form(self) -> None:
|
|
|
195
|
+ if self._dataform_widget is None:
|
|
|
196
|
+ return
|
|
224
|
197
|
|
|
225
|
|
- self.add(icon)
|
|
226
|
|
- self.add(self._label)
|
|
|
198
|
+ self.remove(self._dataform_widget)
|
|
|
199
|
+ self._dataform_widget.destroy()
|
|
|
200
|
+ self._dataform_widget = None
|
|
227
|
201
|
|
|
228
|
|
- def set_text(self, text):
|
|
229
|
|
- self._label.set_text(text) |
|
|
202
|
+ def get_default_button(self) -> str:
|
|
|
203
|
+ return 'register' |