comparison frontends/src/primitivus/profile_manager.py @ 1367:f71a0fc26886

merged branch frontends_multi_profiles
author Goffi <goffi@goffi.org>
date Wed, 18 Mar 2015 10:52:28 +0100
parents 948dc273ad93
children 069ad98b360d
comparison
equal deleted inserted replaced
1295:1e3b1f9ad6e2 1367:f71a0fc26886
16 16
17 # You should have received a copy of the GNU Affero General Public License 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/>. 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 19
20 from sat.core.i18n import _ 20 from sat.core.i18n import _
21 from sat.core import log as logging
22 log = logging.getLogger(__name__)
23 from sat_frontends.quick_frontend.quick_profile_manager import QuickProfileManager
21 from sat_frontends.primitivus.constants import Const as C 24 from sat_frontends.primitivus.constants import Const as C
25 from sat_frontends.primitivus.keys import action_key_map as a_key
26 from urwid_satext import sat_widgets
22 import urwid 27 import urwid
23 from urwid_satext.sat_widgets import AdvancedEdit, Password, List, InputDialog, ConfirmDialog, Alert
24 from sat_frontends.primitivus.keys import action_key_map as a_key
25 28
26 29
27 class ProfileManager(urwid.WidgetWrap): 30 class ProfileManager(QuickProfileManager, urwid.WidgetWrap):
28 31
29 def __init__(self, host): 32 def __init__(self, host, autoconnect=None):
30 self.host = host 33 QuickProfileManager.__init__(self, host, autoconnect)
31 #profiles list
32 profiles = self.host.bridge.getProfilesList()
33 profiles.sort()
34 34
35 #login & password box must be created before list because of onProfileChange 35 #login & password box must be created before list because of onProfileChange
36 self.login_wid = AdvancedEdit(_('Login:'), align='center') 36 self.login_wid = sat_widgets.AdvancedEdit(_('Login:'), align='center')
37 self.pass_wid = Password(_('Password:'), align='center') 37 self.pass_wid = sat_widgets.Password(_('Password:'), align='center')
38 38
39 self.selected_profile = None # allow to reselect the previous selection until the profile is authenticated 39 style = ['no_first_select']
40 style = ['single'] 40 profiles = host.bridge.getProfilesList()
41 if self.host.options.profile: 41 profiles.sort()
42 style.append('no_first_select') 42 self.list_profile = sat_widgets.List(profiles, style=style, align='center', on_change=self.onProfileChange)
43 self.list_profile = List(profiles, style=style, align='center', on_change=self.onProfileChange)
44 43
45 #new & delete buttons 44 #new & delete buttons
46 buttons = [urwid.Button(_("New"), self.onNewProfile), 45 buttons = [urwid.Button(_("New"), self.onNewProfile),
47 urwid.Button(_("Delete"), self.onDeleteProfile)] 46 urwid.Button(_("Delete"), self.onDeleteProfile)]
48 buttons_flow = urwid.GridFlow(buttons, max([len(button.get_label()) for button in buttons])+4, 1, 1, 'center') 47 buttons_flow = urwid.GridFlow(buttons, max([len(button.get_label()) for button in buttons])+4, 1, 1, 'center')
49 48
50 #second part: login information: 49 #second part: login information:
51 divider = urwid.Divider('-') 50 divider = urwid.Divider('-')
52 51
53 #connect button 52 #connect button
54 connect_button = urwid.Button(_("Connect"), self.onConnectProfile) 53 connect_button = sat_widgets.CustomButton(_("Connect"), self.onConnectProfiles, align='center')
55 54
56 #we now build the widget 55 #we now build the widget
57 list_walker = urwid.SimpleFocusListWalker([buttons_flow,self.list_profile,divider,self.login_wid, self.pass_wid, connect_button]) 56 list_walker = urwid.SimpleFocusListWalker([buttons_flow,self.list_profile, divider, self.login_wid, self.pass_wid, connect_button])
58 frame_body = urwid.ListBox(list_walker) 57 frame_body = urwid.ListBox(list_walker)
59 frame = urwid.Frame(frame_body,urwid.AttrMap(urwid.Text(_("Profile Manager"),align='center'),'title')) 58 frame = urwid.Frame(frame_body,urwid.AttrMap(urwid.Text(_("Profile Manager"),align='center'),'title'))
60 self.main_widget = urwid.LineBox(frame) 59 self.main_widget = urwid.LineBox(frame)
61 urwid.WidgetWrap.__init__(self, self.main_widget) 60 urwid.WidgetWrap.__init__(self, self.main_widget)
61
62 self.go(autoconnect)
63
62 64
63 def keypress(self, size, key): 65 def keypress(self, size, key):
64 if key == a_key['APP_QUIT']: 66 if key == a_key['APP_QUIT']:
65 self.host.onExit() 67 self.host.onExit()
66 raise urwid.ExitMainLoop() 68 raise urwid.ExitMainLoop()
78 list_box.set_focus(current_focus, 'above' if focus_diff == 1 else 'below') 80 list_box.set_focus(current_focus, 'above' if focus_diff == 1 else 'below')
79 list_box._invalidate() 81 list_box._invalidate()
80 return 82 return
81 return super(ProfileManager, self).keypress(size, key) 83 return super(ProfileManager, self).keypress(size, key)
82 84
83 def __refillProfiles(self):
84 """Update the list of profiles"""
85 profiles = self.host.bridge.getProfilesList()
86 profiles.sort()
87 self.list_profile.changeValues(profiles)
88
89 def cancelDialog(self, button): 85 def cancelDialog(self, button):
90 self.host.removePopUp() 86 self.host.removePopUp()
91 87
92 def newProfile(self, button, edit): 88 def newProfile(self, button, edit):
93 """Create the profile""" 89 """Create the profile"""
94 name = edit.get_edit_text() 90 name = edit.get_edit_text()
95 self.host.bridge.asyncCreateProfile(name, callback=lambda: self._newProfileCreated(name), errback=self._profileCreationFailure) 91 self.host.bridge.asyncCreateProfile(name, callback=lambda: self.newProfileCreated(name), errback=self.profileCreationFailure)
96 92
97 def _newProfileCreated(self, name): 93 def newProfileCreated(self, profile):
98 self.__refillProfiles()
99 #We select the profile created in the list
100 self.list_profile.selectValue(name)
101 self.host.removePopUp() 94 self.host.removePopUp()
95 self.refillProfiles()
96 self.list_profile.selectValue(profile)
97 self.current.profile=profile
98 self.getConnectionParams(profile)
102 self.host.redraw() 99 self.host.redraw()
103 100
104 def _profileCreationFailure(self, reason): 101 def profileCreationFailure(self, reason):
105 self.host.removePopUp() 102 self.host.removePopUp()
106 if reason == "ConflictError": 103 message = self._getErrorMessage(reason)
107 message = _("A profile with this name already exists") 104 self.alert(_("Can't create profile"), message)
108 elif reason == "CancelError":
109 message = _("Profile creation cancelled by backend")
110 else:
111 message = _("Unknown reason (%s)") % reason
112 popup = Alert(_("Can't create profile"), message, ok_cb=self.host.removePopUp)
113 self.host.showPopUp(popup)
114 105
115 def deleteProfile(self, button): 106 def deleteProfile(self, button):
116 profile_name = self.list_profile.getSelectedValue() 107 self._deleteProfile()
117 if profile_name:
118 self.host.bridge.asyncDeleteProfile(profile_name, callback=self.__refillProfiles)
119 self.host.removePopUp() 108 self.host.removePopUp()
120 109
121 def onNewProfile(self, e): 110 def onNewProfile(self, e):
122 pop_up_widget = InputDialog(_("New profile"), _("Please enter a new profile name"), cancel_cb=self.cancelDialog, ok_cb=self.newProfile) 111 pop_up_widget = sat_widgets.InputDialog(_("New profile"), _("Please enter a new profile name"), cancel_cb=self.cancelDialog, ok_cb=self.newProfile)
123 self.host.showPopUp(pop_up_widget) 112 self.host.showPopUp(pop_up_widget)
124 113
125 def onDeleteProfile(self, e): 114 def onDeleteProfile(self, e):
126 pop_up_widget = ConfirmDialog(_("Are you sure you want to delete the profile %s ?") % self.list_profile.getSelectedValue(), no_cb=self.cancelDialog, yes_cb=self.deleteProfile) 115 if self.current.profile:
127 self.host.showPopUp(pop_up_widget) 116 pop_up_widget = sat_widgets.ConfirmDialog(_("Are you sure you want to delete the profile {} ?").format(self.current.profile), no_cb=self.cancelDialog, yes_cb=self.deleteProfile)
117 self.host.showPopUp(pop_up_widget)
128 118
129 def getXMPPParams(self, profile): 119 def onConnectProfiles(self, button):
130 """This is called from PrimitivusApp.launchAction when the profile has been authenticated. 120 """Connect the profiles and start the main widget
131 121
132 @param profile: %(doc_profile)s 122 @param button: the connect button
133 """ 123 """
134 def setJID(jabberID): 124 self._onConnectProfiles()
135 self.login_wid.set_edit_text(jabberID)
136 self.host.redraw()
137 125
138 def setPassword(password): 126 def resetFields(self):
139 self.pass_wid.set_edit_text(password) 127 """Set profile to None, and reset fields"""
140 self.host.redraw() 128 super(ProfileManager, self).resetFields()
129 self.list_profile.unselectAll(invisible=True)
141 130
142 self.list_profile.selectValue(profile, move_focus=False) 131 def setProfiles(self, profiles):
143 self.selected_profile = profile 132 """Update the list of profiles"""
144 self.host.bridge.asyncGetParamA("JabberID", "Connection", profile_key=profile, callback=setJID, errback=self.getParamError) 133 self.list_profile.changeValues(profiles)
145 self.host.bridge.asyncGetParamA("Password", "Connection", profile_key=profile, callback=setPassword, errback=self.getParamError) 134 self.host.redraw()
135
136 def getProfiles(self):
137 return self.list_profile.getSelectedValues()
138
139 def getJID(self):
140 return self.login_wid.get_edit_text()
141
142 def getPassword(self):
143 return self.pass_wid.get_edit_text()
144
145 def setJID(self, jid_):
146 self.login_wid.set_edit_text(jid_)
147 self.current.login = jid_
148 self.host.redraw() # FIXME: redraw should be avoided
149
150 def setPassword(self, password):
151 self.pass_wid.set_edit_text(password)
152 self.current.password = password
153 self.host.redraw()
154
155 def alert(self, title, message):
156 popup = sat_widgets.Alert(title, message, ok_cb=self.host.removePopUp)
157 self.host.showPopUp(popup)
146 158
147 def onProfileChange(self, list_wid): 159 def onProfileChange(self, list_wid):
148 """This is called when a profile is selected in the profile list. 160 """This is called when a profile is selected in the profile list.
149 161
150 @param list_wid: the List widget who sent the event 162 @param list_wid: the List widget who sent the event
151 """ 163 """
152 profile_name = list_wid.getSelectedValue() 164 self.updateConnectionParams()
153 if not profile_name or profile_name == self.selected_profile: 165 focused = list_wid.focus
154 return # avoid infinite loop 166 selected = focused.getState()
155 if self.selected_profile: 167 if not selected: # profile was just unselected
156 list_wid.selectValue(self.selected_profile, move_focus=False) 168 return
157 else: 169 focused.setState(False, invisible=True) # we don't want the widget to be selected until we are sure we can access it
158 list_wid.unselectAll(invisible=True) 170 def authenticate_cb(callback_id, data, profile):
159 self.host.redraw() 171 if C.bool(data['validated']):
160 self.host.profile = profile_name # FIXME: EXTREMELY DIRTY, needed for sat_frontends.tools.xmlui.XMLUI._xmluiLaunchAction 172 self.current.profile = profile
161 self.host.launchAction(C.AUTHENTICATE_PROFILE_ID, {'caller': 'profile_manager'}, profile_key=profile_name) 173 focused.setState(True, invisible=True)
174 self.getConnectionParams(profile)
175 self.host.redraw()
176 self.host.launchAction(C.AUTHENTICATE_PROFILE_ID, callback=authenticate_cb, profile=focused.text)
162 177
163 def onConnectProfile(self, button):
164 profile_name = self.list_profile.getSelectedValue()
165 assert(profile_name == self.selected_profile) # if not, there's a bug somewhere...
166 if not profile_name:
167 pop_up_widget = Alert(_('No profile selected'), _('You need to create and select a profile before connecting'), ok_cb=self.cancelDialog)
168 self.host.showPopUp(pop_up_widget)
169 elif profile_name[0] == '@':
170 pop_up_widget = Alert(_('Bad profile name'), _("A profile name can't start with a @"), ok_cb=self.cancelDialog)
171 self.host.showPopUp(pop_up_widget)
172 else:
173 profile = self.host.bridge.getProfileName(profile_name)
174 assert(profile)
175 #TODO: move this to quick_app
176 self.host.bridge.asyncGetParamA("JabberID", "Connection", profile_key=profile,
177 callback=lambda old_jid: self.__old_jidReceived(old_jid, profile), errback=self.getParamError)
178
179 def __old_jidReceived(self, old_jid, profile):
180 self.host.bridge.asyncGetParamA("Password", "Connection", profile_key=profile,
181 callback=lambda old_pass: self.__old_passReceived(old_jid, old_pass, profile), errback=self.getParamError)
182
183 def __old_passReceived(self, old_jid, old_pass, profile):
184 """Check if we have new jid/pass, save them if it is the case, and plug profile"""
185 new_jid = self.login_wid.get_edit_text()
186 new_pass = self.pass_wid.get_edit_text()
187
188 if old_jid != new_jid:
189 self.host.bridge.setParam("JabberID", new_jid, "Connection", profile_key=profile)
190 if old_pass != new_pass:
191 self.host.bridge.setParam("Password", new_pass, "Connection", profile_key=profile)
192 self.host.plug_profile(profile)
193
194 def getParamError(self, ignore):
195 popup = Alert("Error", _("Can't get profile parameter"), ok_cb=self.host.removePopUp)
196 self.host.showPopUp(popup)