Mercurial > libervia-backend
comparison libervia/frontends/quick_frontend/quick_profile_manager.py @ 4074:26b7ed2817da
refactoring: rename `sat_frontends` to `libervia.frontends`
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 02 Jun 2023 14:12:38 +0200 |
parents | sat_frontends/quick_frontend/quick_profile_manager.py@4b842c1fb686 |
children | b620a8e882e1 |
comparison
equal
deleted
inserted
replaced
4073:7c5654c54fed | 4074:26b7ed2817da |
---|---|
1 #!/usr/bin/env python3 | |
2 | |
3 | |
4 # helper class for making a SAT frontend | |
5 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org) | |
6 | |
7 # This program is free software: you can redistribute it and/or modify | |
8 # it under the terms of the GNU Affero General Public License as published by | |
9 # the Free Software Foundation, either version 3 of the License, or | |
10 # (at your option) any later version. | |
11 | |
12 # This program is distributed in the hope that it will be useful, | |
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 # GNU Affero General Public License for more details. | |
16 | |
17 # You should have received a copy of the GNU Affero General Public License | |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | |
20 from libervia.backend.core.i18n import _ | |
21 from libervia.backend.core import log as logging | |
22 | |
23 log = logging.getLogger(__name__) | |
24 from libervia.frontends.primitivus.constants import Const as C | |
25 | |
26 | |
27 class ProfileRecord(object): | |
28 """Class which manage data for one profile""" | |
29 | |
30 def __init__(self, profile=None, login=None, password=None): | |
31 self._profile = profile | |
32 self._login = login | |
33 self._password = password | |
34 | |
35 @property | |
36 def profile(self): | |
37 return self._profile | |
38 | |
39 @profile.setter | |
40 def profile(self, value): | |
41 self._profile = value | |
42 # if we change the profile, | |
43 # we must have no login/password until backend give them | |
44 self._login = self._password = None | |
45 | |
46 @property | |
47 def login(self): | |
48 return self._login | |
49 | |
50 @login.setter | |
51 def login(self, value): | |
52 self._login = value | |
53 | |
54 @property | |
55 def password(self): | |
56 return self._password | |
57 | |
58 @password.setter | |
59 def password(self, value): | |
60 self._password = value | |
61 | |
62 | |
63 class QuickProfileManager(object): | |
64 """Class with manage profiles creation/deletion/connection""" | |
65 | |
66 def __init__(self, host, autoconnect=None): | |
67 """Create the manager | |
68 | |
69 @param host: %(doc_host)s | |
70 @param autoconnect(iterable): list of profiles to connect automatically | |
71 """ | |
72 self.host = host | |
73 self._autoconnect = bool(autoconnect) | |
74 self.current = ProfileRecord() | |
75 | |
76 def go(self, autoconnect): | |
77 if self._autoconnect: | |
78 self.autoconnect(autoconnect) | |
79 | |
80 def autoconnect(self, profile_keys): | |
81 """Automatically connect profiles | |
82 | |
83 @param profile_keys(iterable): list of profile keys to connect | |
84 """ | |
85 if not profile_keys: | |
86 log.warning("No profile given to autoconnect") | |
87 return | |
88 self._autoconnect = True | |
89 self._autoconnect_profiles = [] | |
90 self._do_autoconnect(profile_keys) | |
91 | |
92 def _do_autoconnect(self, profile_keys): | |
93 """Connect automatically given profiles | |
94 | |
95 @param profile_kes(iterable): profiles to connect | |
96 """ | |
97 assert self._autoconnect | |
98 | |
99 def authenticate_cb(data, cb_id, profile): | |
100 | |
101 if C.bool(data.pop("validated", C.BOOL_FALSE)): | |
102 self._autoconnect_profiles.append(profile) | |
103 if len(self._autoconnect_profiles) == len(profile_keys): | |
104 # all the profiles have been validated | |
105 self.host.plug_profiles(self._autoconnect_profiles) | |
106 else: | |
107 # a profile is not validated, we go to manual mode | |
108 self._autoconnect = False | |
109 self.host.action_manager(data, callback=authenticate_cb, profile=profile) | |
110 | |
111 def get_profile_name_cb(profile): | |
112 if not profile: | |
113 # FIXME: this method is not handling manual mode correclty anymore | |
114 # must be thought to be handled asynchronously | |
115 self._autoconnect = False # manual mode | |
116 msg = _("Trying to plug an unknown profile key ({})".format(profile_key)) | |
117 log.warning(msg) | |
118 self.host.show_dialog(_("Profile plugging in error"), msg, "error") | |
119 else: | |
120 self.host.action_launch( | |
121 C.AUTHENTICATE_PROFILE_ID, callback=authenticate_cb, profile=profile | |
122 ) | |
123 | |
124 def get_profile_name_eb(failure): | |
125 log.error("Can't retrieve profile name: {}".format(failure)) | |
126 | |
127 for profile_key in profile_keys: | |
128 self.host.bridge.profile_name_get( | |
129 profile_key, callback=get_profile_name_cb, errback=get_profile_name_eb | |
130 ) | |
131 | |
132 def get_param_error(self, __): | |
133 self.host.show_dialog(_("Error"), _("Can't get profile parameter"), "error") | |
134 | |
135 ## Helping methods ## | |
136 | |
137 def _get_error_message(self, reason): | |
138 """Return an error message corresponding to profile creation error | |
139 | |
140 @param reason (str): reason as returned by profile_create | |
141 @return (unicode): human readable error message | |
142 """ | |
143 if reason == "ConflictError": | |
144 message = _("A profile with this name already exists") | |
145 elif reason == "CancelError": | |
146 message = _("Profile creation cancelled by backend") | |
147 elif reason == "ValueError": | |
148 message = _( | |
149 "You profile name is not valid" | |
150 ) # TODO: print a more informative message (empty name, name starting with '@') | |
151 else: | |
152 message = _("Can't create profile ({})").format(reason) | |
153 return message | |
154 | |
155 def _delete_profile(self): | |
156 """Delete the currently selected profile""" | |
157 if self.current.profile: | |
158 self.host.bridge.profile_delete_async( | |
159 self.current.profile, callback=self.refill_profiles | |
160 ) | |
161 self.reset_fields() | |
162 | |
163 ## workflow methods (events occuring during the profiles selection) ## | |
164 | |
165 # These methods must be called by the frontend at some point | |
166 | |
167 def _on_connect_profiles(self): | |
168 """Connect the profiles and start the main widget""" | |
169 if self._autoconnect: | |
170 self.host.show_dialog( | |
171 _("Internal error"), | |
172 _("You can't connect manually and automatically at the same time"), | |
173 "error", | |
174 ) | |
175 return | |
176 self.update_connection_params() | |
177 profiles = self.get_profiles() | |
178 if not profiles: | |
179 self.host.show_dialog( | |
180 _("No profile selected"), | |
181 _("You need to create and select at least one profile before connecting"), | |
182 "error", | |
183 ) | |
184 else: | |
185 # All profiles in the list are already validated, so we can plug them directly | |
186 self.host.plug_profiles(profiles) | |
187 | |
188 def get_connection_params(self, profile): | |
189 """Get login and password and display them | |
190 | |
191 @param profile: %(doc_profile)s | |
192 """ | |
193 self.host.bridge.param_get_a_async( | |
194 "JabberID", | |
195 "Connection", | |
196 profile_key=profile, | |
197 callback=self.set_jid, | |
198 errback=self.get_param_error, | |
199 ) | |
200 self.host.bridge.param_get_a_async( | |
201 "Password", | |
202 "Connection", | |
203 profile_key=profile, | |
204 callback=self.set_password, | |
205 errback=self.get_param_error, | |
206 ) | |
207 | |
208 def update_connection_params(self): | |
209 """Check if connection parameters have changed, and update them if so""" | |
210 if self.current.profile: | |
211 login = self.get_jid() | |
212 password = self.getPassword() | |
213 if login != self.current.login and self.current.login is not None: | |
214 self.current.login = login | |
215 self.host.bridge.param_set( | |
216 "JabberID", login, "Connection", profile_key=self.current.profile | |
217 ) | |
218 log.info("login updated for profile [{}]".format(self.current.profile)) | |
219 if password != self.current.password and self.current.password is not None: | |
220 self.current.password = password | |
221 self.host.bridge.param_set( | |
222 "Password", password, "Connection", profile_key=self.current.profile | |
223 ) | |
224 log.info( | |
225 "password updated for profile [{}]".format(self.current.profile) | |
226 ) | |
227 | |
228 ## graphic updates (should probably be overriden in frontends) ## | |
229 | |
230 def reset_fields(self): | |
231 """Set profile to None, and reset fields""" | |
232 self.current.profile = None | |
233 self.set_jid("") | |
234 self.set_password("") | |
235 | |
236 def refill_profiles(self): | |
237 """Rebuild the list of profiles""" | |
238 profiles = self.host.bridge.profiles_list_get() | |
239 profiles.sort() | |
240 self.set_profiles(profiles) | |
241 | |
242 ## Method which must be implemented by frontends ## | |
243 | |
244 # get/set data | |
245 | |
246 def get_profiles(self): | |
247 """Return list of selected profiles | |
248 | |
249 Must be implemented by frontends | |
250 @return (list): list of profiles | |
251 """ | |
252 raise NotImplementedError | |
253 | |
254 def set_profiles(self, profiles): | |
255 """Update the list of profiles""" | |
256 raise NotImplementedError | |
257 | |
258 def get_jid(self): | |
259 """Get current jid | |
260 | |
261 Must be implemented by frontends | |
262 @return (unicode): current jabber id | |
263 """ | |
264 raise NotImplementedError | |
265 | |
266 def getPassword(self): | |
267 """Get current password | |
268 | |
269 Must be implemented by frontends | |
270 @return (unicode): current password | |
271 """ | |
272 raise NotImplementedError | |
273 | |
274 def set_jid(self, jid_): | |
275 """Set current jid | |
276 | |
277 Must be implemented by frontends | |
278 @param jid_(unicode): jabber id to set | |
279 """ | |
280 raise NotImplementedError | |
281 | |
282 def set_password(self, password): | |
283 """Set current password | |
284 | |
285 Must be implemented by frontends | |
286 """ | |
287 raise NotImplementedError | |
288 | |
289 # dialogs | |
290 | |
291 # Note: a method which check profiles change must be implemented too |