comparison frontends/src/quick_frontend/quick_profile_manager.py @ 1288:7cf32aeeebdb frontends_multi_profiles

quick_frontend, primitivus: moved parts of primitivus's profileManager to quick_frontend
author Goffi <goffi@goffi.org>
date Sat, 24 Jan 2015 00:14:58 +0100
parents frontends/src/primitivus/profile_manager.py@e3a9ea76de35
children 948dc273ad93
comparison
equal deleted inserted replaced
1265:e3a9ea76de35 1288:7cf32aeeebdb
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3
4 # helper class for making a SAT frontend
5 # Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 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(callback_id, data, profile):
100
101 if C.bool(data['validated']):
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
110 for profile_key in profile_keys:
111 profile = self.host.bridge.getProfileName(profile_key)
112 if not profile:
113 self._autoconnect = False # manual mode
114 msg = _("Trying to plug an unknown profile key ({})".format(profile_key))
115 log.warning(msg)
116 self.alert(_("Profile plugging in error"), msg, ok_cb=self.host.removePopUp)
117 break
118 self.host.launchAction(C.AUTHENTICATE_PROFILE_ID, callback=authenticate_cb, profile=profile)
119
120
121 def getParamError(self, dummy):
122 self.alert(_(u"Error"), _("Can't get profile parameter"))
123
124 ## Helping methods ##
125
126 def _getErrorMessage(self, reason):
127 """Return an error message corresponding to profile creation error
128
129 @param reason (str): reason as returned by asyncCreateProfile
130 @return (unicode): human readable error message
131 """
132 if reason == "ConflictError":
133 message = _("A profile with this name already exists")
134 elif reason == "CancelError":
135 message = _("Profile creation cancelled by backend")
136 elif reason == "ValueError":
137 message = _("You profile name is not valid") # TODO: print a more informative message (empty name, name starting with '@')
138 else:
139 message = _("Can't create profile ({})").format(reason)
140 return message
141
142 def _deleteProfile(self):
143 """Delete the currently selected profile"""
144 if self.current.profile:
145 self.host.bridge.asyncDeleteProfile(self.current.profile, callback=self.refillProfiles)
146 self.resetFields()
147
148 ## workflow methods (events occuring during the profiles selection) ##
149
150 # These methods must be called by the frontend at some point
151
152 def _onConnectProfiles(self):
153 """Connect the profiles and start the main widget"""
154 if self._autoconnect:
155 self.alert(_('Internal error'), _('You can connect manually and automatically at the same time'))
156 return
157 self.updateConnectionParams()
158 profiles = self.getProfiles()
159 if not profiles:
160 self.alert(_('No profile selected'), _('You need to create and select at least one profile before connecting'))
161 else:
162 # All profiles in the list are already validated, so we can plug them directly
163 self.host.plug_profiles(profiles)
164
165 def getConnectionParams(self, profile):
166 """Get login and password and display them
167
168 @param profile: %(doc_profile)s
169 """
170 self.host.bridge.asyncGetParamA("JabberID", "Connection", profile_key=profile, callback=self.setJID, errback=self.getParamError)
171 self.host.bridge.asyncGetParamA("Password", "Connection", profile_key=profile, callback=self.setPassword, errback=self.getParamError)
172
173 def updateConnectionParams(self):
174 """Check if connection parameters have changed, and update them if so"""
175 if self.current.profile:
176 login = self.getJID()
177 password = self.getPassword()
178 if login != self.current.login and self.current.login is not None:
179 self.current.login = login
180 self.host.bridge.setParam("JabberID", login, "Connection", profile_key=self.current.profile)
181 log.info("login updated for profile [{}]".format(self.current.profile))
182 if password != self.current.password and self.current.password is not None:
183 self.current.password = password
184 self.host.bridge.setParam("Password", password, "Connection", profile_key=self.current.profile)
185 log.info("password updated for profile [{}]".format(self.current.profile))
186
187 ## graphic updates (should probably be overriden in frontends) ##
188
189 def resetFields(self):
190 """Set profile to None, and reset fields"""
191 self.current.profile=None
192 self.setJID("")
193 self.setPassword("")
194
195 def refillProfiles(self):
196 """Rebuild the list of profiles"""
197 profiles = self.host.bridge.getProfilesList()
198 profiles.sort()
199 self.setProfiles(profiles)
200
201 ## Method which must be implemented by frontends ##
202
203 # get/set data
204
205 def getProfiles(self):
206 """Return list of selected profiles
207
208 Must be implemented by frontends
209 @return (list): list of profiles
210 """
211 raise NotImplementedError
212
213 def setProfiles(self, profiles):
214 """Update the list of profiles"""
215 raise NotImplementedError
216
217
218 def getJID(self):
219 """Get current jid
220
221 Must be implemented by frontends
222 @return (unicode): current jabber id
223 """
224 raise NotImplementedError
225
226 def getPassword(self):
227 """Get current password
228
229 Must be implemented by frontends
230 @return (unicode): current password
231 """
232 raise NotImplementedError
233
234 def setJID(self, jid_):
235 """Set current jid
236
237 Must be implemented by frontends
238 @param jid_(unicode): jabber id to set
239 """
240 raise NotImplementedError
241
242 def setPassword(self, password):
243 """Set current password
244
245 Must be implemented by frontends
246 """
247 raise NotImplementedError
248
249 # dialogs
250
251 def alert(self, title, message):
252 """Show an alert message, must be implemented by frontends
253
254 @param title: title of the dialog/popup
255 @param message: error message
256 """
257 raise NotImplementedError
258
259 # Note: a method which check profiles change must be implemented too