Mercurial > libervia-backend
comparison sat_frontends/quick_frontend/quick_profile_manager.py @ 2562:26edcf3a30eb
core, setup: huge cleaning:
- moved directories from src and frontends/src to sat and sat_frontends, which is the recommanded naming convention
- move twisted directory to root
- removed all hacks from setup.py, and added missing dependencies, it is now clean
- use https URL for website in setup.py
- removed "Environment :: X11 Applications :: GTK", as wix is deprecated and removed
- renamed sat.sh to sat and fixed its installation
- added python_requires to specify Python version needed
- replaced glib2reactor which use deprecated code by gtk3reactor
sat can now be installed directly from virtualenv without using --system-site-packages anymore \o/
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 02 Apr 2018 19:44:50 +0200 |
parents | frontends/src/quick_frontend/quick_profile_manager.py@0046283a285d |
children | 56f94936df1e |
comparison
equal
deleted
inserted
replaced
2561:bd30dc3ffe5a | 2562:26edcf3a30eb |
---|---|
1 #!/usr/bin/env python2 | |
2 # -*- coding: utf-8 -*- | |
3 | |
4 # helper class for making a SAT frontend | |
5 # Copyright (C) 2009-2018 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 sat.core.i18n import _ | |
21 from sat.core import log as logging | |
22 log = logging.getLogger(__name__) | |
23 from sat_frontends.primitivus.constants import Const as C | |
24 | |
25 | |
26 class ProfileRecord(object): | |
27 """Class which manage data for one profile""" | |
28 | |
29 def __init__(self, profile=None, login=None, password=None): | |
30 self._profile = profile | |
31 self._login = login | |
32 self._password = password | |
33 | |
34 @property | |
35 def profile(self): | |
36 return self._profile | |
37 | |
38 @profile.setter | |
39 def profile(self, value): | |
40 self._profile = value | |
41 # if we change the profile, | |
42 # we must have no login/password until backend give them | |
43 self._login = self._password = None | |
44 | |
45 @property | |
46 def login(self): | |
47 return self._login | |
48 | |
49 @login.setter | |
50 def login(self, value): | |
51 self._login = value | |
52 | |
53 @property | |
54 def password(self): | |
55 return self._password | |
56 | |
57 @password.setter | |
58 def password(self, value): | |
59 self._password = value | |
60 | |
61 | |
62 class QuickProfileManager(object): | |
63 """Class with manage profiles creation/deletion/connection""" | |
64 | |
65 def __init__(self, host, autoconnect=None): | |
66 """Create the manager | |
67 | |
68 @param host: %(doc_host)s | |
69 @param autoconnect(iterable): list of profiles to connect automatically | |
70 """ | |
71 self.host = host | |
72 self._autoconnect = bool(autoconnect) | |
73 self.current = ProfileRecord() | |
74 | |
75 def go(self, autoconnect): | |
76 if self._autoconnect: | |
77 self.autoconnect(autoconnect) | |
78 | |
79 def autoconnect(self, profile_keys): | |
80 """Automatically connect profiles | |
81 | |
82 @param profile_keys(iterable): list of profile keys to connect | |
83 """ | |
84 if not profile_keys: | |
85 log.warning("No profile given to autoconnect") | |
86 return | |
87 self._autoconnect = True | |
88 self._autoconnect_profiles=[] | |
89 self._do_autoconnect(profile_keys) | |
90 | |
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.actionManager(data, callback=authenticate_cb, profile=profile) | |
110 | |
111 def getProfileNameCb(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.showDialog(_("Profile plugging in error"), msg, 'error') | |
119 else: | |
120 self.host.launchAction(C.AUTHENTICATE_PROFILE_ID, callback=authenticate_cb, profile=profile) | |
121 | |
122 def getProfileNameEb(failure): | |
123 log.error(u"Can't retrieve profile name: {}".format(failure)) | |
124 | |
125 for profile_key in profile_keys: | |
126 self.host.bridge.profileNameGet(profile_key, callback=getProfileNameCb, errback=getProfileNameEb) | |
127 | |
128 | |
129 def getParamError(self, dummy): | |
130 self.host.showDialog(_(u"Error"), _("Can't get profile parameter"), 'error') | |
131 | |
132 ## Helping methods ## | |
133 | |
134 def _getErrorMessage(self, reason): | |
135 """Return an error message corresponding to profile creation error | |
136 | |
137 @param reason (str): reason as returned by profileCreate | |
138 @return (unicode): human readable error message | |
139 """ | |
140 if reason == "ConflictError": | |
141 message = _("A profile with this name already exists") | |
142 elif reason == "CancelError": | |
143 message = _("Profile creation cancelled by backend") | |
144 elif reason == "ValueError": | |
145 message = _("You profile name is not valid") # TODO: print a more informative message (empty name, name starting with '@') | |
146 else: | |
147 message = _("Can't create profile ({})").format(reason) | |
148 return message | |
149 | |
150 def _deleteProfile(self): | |
151 """Delete the currently selected profile""" | |
152 if self.current.profile: | |
153 self.host.bridge.asyncDeleteProfile(self.current.profile, callback=self.refillProfiles) | |
154 self.resetFields() | |
155 | |
156 ## workflow methods (events occuring during the profiles selection) ## | |
157 | |
158 # These methods must be called by the frontend at some point | |
159 | |
160 def _onConnectProfiles(self): | |
161 """Connect the profiles and start the main widget""" | |
162 if self._autoconnect: | |
163 self.host.showDialog(_('Internal error'), _("You can't connect manually and automatically at the same time"), 'error') | |
164 return | |
165 self.updateConnectionParams() | |
166 profiles = self.getProfiles() | |
167 if not profiles: | |
168 self.host.showDialog(_('No profile selected'), _('You need to create and select at least one profile before connecting'), 'error') | |
169 else: | |
170 # All profiles in the list are already validated, so we can plug them directly | |
171 self.host.plug_profiles(profiles) | |
172 | |
173 def getConnectionParams(self, profile): | |
174 """Get login and password and display them | |
175 | |
176 @param profile: %(doc_profile)s | |
177 """ | |
178 self.host.bridge.asyncGetParamA("JabberID", "Connection", profile_key=profile, callback=self.setJID, errback=self.getParamError) | |
179 self.host.bridge.asyncGetParamA("Password", "Connection", profile_key=profile, callback=self.setPassword, errback=self.getParamError) | |
180 | |
181 def updateConnectionParams(self): | |
182 """Check if connection parameters have changed, and update them if so""" | |
183 if self.current.profile: | |
184 login = self.getJID() | |
185 password = self.getPassword() | |
186 if login != self.current.login and self.current.login is not None: | |
187 self.current.login = login | |
188 self.host.bridge.setParam("JabberID", login, "Connection", profile_key=self.current.profile) | |
189 log.info(u"login updated for profile [{}]".format(self.current.profile)) | |
190 if password != self.current.password and self.current.password is not None: | |
191 self.current.password = password | |
192 self.host.bridge.setParam("Password", password, "Connection", profile_key=self.current.profile) | |
193 log.info(u"password updated for profile [{}]".format(self.current.profile)) | |
194 | |
195 ## graphic updates (should probably be overriden in frontends) ## | |
196 | |
197 def resetFields(self): | |
198 """Set profile to None, and reset fields""" | |
199 self.current.profile=None | |
200 self.setJID("") | |
201 self.setPassword("") | |
202 | |
203 def refillProfiles(self): | |
204 """Rebuild the list of profiles""" | |
205 profiles = self.host.bridge.profilesListGet() | |
206 profiles.sort() | |
207 self.setProfiles(profiles) | |
208 | |
209 ## Method which must be implemented by frontends ## | |
210 | |
211 # get/set data | |
212 | |
213 def getProfiles(self): | |
214 """Return list of selected profiles | |
215 | |
216 Must be implemented by frontends | |
217 @return (list): list of profiles | |
218 """ | |
219 raise NotImplementedError | |
220 | |
221 def setProfiles(self, profiles): | |
222 """Update the list of profiles""" | |
223 raise NotImplementedError | |
224 | |
225 | |
226 def getJID(self): | |
227 """Get current jid | |
228 | |
229 Must be implemented by frontends | |
230 @return (unicode): current jabber id | |
231 """ | |
232 raise NotImplementedError | |
233 | |
234 def getPassword(self): | |
235 """Get current password | |
236 | |
237 Must be implemented by frontends | |
238 @return (unicode): current password | |
239 """ | |
240 raise NotImplementedError | |
241 | |
242 def setJID(self, jid_): | |
243 """Set current jid | |
244 | |
245 Must be implemented by frontends | |
246 @param jid_(unicode): jabber id to set | |
247 """ | |
248 raise NotImplementedError | |
249 | |
250 def setPassword(self, password): | |
251 """Set current password | |
252 | |
253 Must be implemented by frontends | |
254 """ | |
255 raise NotImplementedError | |
256 | |
257 # dialogs | |
258 | |
259 # Note: a method which check profiles change must be implemented too |