OLD | NEW |
| (Empty) |
1 | |
2 # Copyright (c) 2001-2004 Twisted Matrix Laboratories. | |
3 # See LICENSE for details. | |
4 | |
5 | |
6 from __future__ import nested_scopes | |
7 | |
8 import gtk | |
9 | |
10 from twisted import copyright | |
11 from twisted.internet import defer | |
12 from twisted.python import failure, log, util | |
13 from twisted.spread import pb | |
14 from twisted.cred.credentials import UsernamePassword | |
15 | |
16 from twisted.internet import error as netError | |
17 | |
18 def login(client=None, **defaults): | |
19 """ | |
20 @param host: | |
21 @param port: | |
22 @param identityName: | |
23 @param password: | |
24 @param serviceName: | |
25 @param perspectiveName: | |
26 | |
27 @returntype: Deferred RemoteReference of Perspective | |
28 """ | |
29 d = defer.Deferred() | |
30 LoginDialog(client, d, defaults) | |
31 return d | |
32 | |
33 class GladeKeeper: | |
34 """ | |
35 @cvar gladefile: The file in which the glade GUI definition is kept. | |
36 @type gladefile: str | |
37 | |
38 @cvar _widgets: Widgets that should be attached to me as attributes. | |
39 @type _widgets: list of strings | |
40 """ | |
41 | |
42 gladefile = None | |
43 _widgets = () | |
44 | |
45 def __init__(self): | |
46 from gtk import glade | |
47 self.glade = glade.XML(self.gladefile) | |
48 | |
49 # mold can go away when we get a newer pygtk (post 1.99.14) | |
50 mold = {} | |
51 for k in dir(self): | |
52 mold[k] = getattr(self, k) | |
53 self.glade.signal_autoconnect(mold) | |
54 self._setWidgets() | |
55 | |
56 def _setWidgets(self): | |
57 get_widget = self.glade.get_widget | |
58 for widgetName in self._widgets: | |
59 setattr(self, "_" + widgetName, get_widget(widgetName)) | |
60 | |
61 | |
62 class LoginDialog(GladeKeeper): | |
63 # IdentityConnector host port identityName password | |
64 # requestLogin -> identityWrapper or login failure | |
65 # requestService serviceName perspectiveName client | |
66 | |
67 # window killed | |
68 # cancel button pressed | |
69 # login button activated | |
70 | |
71 fields = ['host','port','identityName','password', | |
72 'perspectiveName'] | |
73 | |
74 _widgets = ("hostEntry", "portEntry", "identityNameEntry", "passwordEntry", | |
75 "perspectiveNameEntry", "statusBar", | |
76 "loginDialog") | |
77 | |
78 _advancedControls = ['perspectiveLabel', 'perspectiveNameEntry', | |
79 'protocolLabel', 'versionLabel'] | |
80 | |
81 gladefile = util.sibpath(__file__, "login2.glade") | |
82 | |
83 def __init__(self, client, deferred, defaults): | |
84 self.client = client | |
85 self.deferredResult = deferred | |
86 | |
87 GladeKeeper.__init__(self) | |
88 | |
89 self.setDefaults(defaults) | |
90 self._loginDialog.show() | |
91 | |
92 | |
93 def setDefaults(self, defaults): | |
94 if not defaults.has_key('port'): | |
95 defaults['port'] = str(pb.portno) | |
96 elif isinstance(defaults['port'], (int, long)): | |
97 defaults['port'] = str(defaults['port']) | |
98 | |
99 for k, v in defaults.iteritems(): | |
100 if k in self.fields: | |
101 widget = getattr(self, "_%sEntry" % (k,)) | |
102 widget.set_text(v) | |
103 | |
104 def _setWidgets(self): | |
105 GladeKeeper._setWidgets(self) | |
106 self._statusContext = self._statusBar.get_context_id("Login dialog.") | |
107 get_widget = self.glade.get_widget | |
108 get_widget("versionLabel").set_text(copyright.longversion) | |
109 get_widget("protocolLabel").set_text("Protocol PB-%s" % | |
110 (pb.Broker.version,)) | |
111 | |
112 def _on_loginDialog_response(self, widget, response): | |
113 handlers = {gtk.RESPONSE_NONE: self._windowClosed, | |
114 gtk.RESPONSE_DELETE_EVENT: self._windowClosed, | |
115 gtk.RESPONSE_OK: self._doLogin, | |
116 gtk.RESPONSE_CANCEL: self._cancelled} | |
117 handler = handlers.get(response) | |
118 if handler is not None: | |
119 handler() | |
120 else: | |
121 log.msg("Unexpected dialog response %r from %s" % (response, | |
122 widget)) | |
123 | |
124 def _on_loginDialog_close(self, widget, userdata=None): | |
125 self._windowClosed() | |
126 | |
127 def _on_loginDialog_destroy_event(self, widget, userdata=None): | |
128 self._windowClosed() | |
129 | |
130 def _cancelled(self): | |
131 if not self.deferredResult.called: | |
132 self.deferredResult.errback(netError.UserError("User hit Cancel.")) | |
133 self._loginDialog.destroy() | |
134 | |
135 def _windowClosed(self, reason=None): | |
136 if not self.deferredResult.called: | |
137 self.deferredResult.errback(netError.UserError("Window closed.")) | |
138 | |
139 def _doLogin(self): | |
140 idParams = {} | |
141 | |
142 idParams['host'] = self._hostEntry.get_text() | |
143 idParams['port'] = self._portEntry.get_text() | |
144 idParams['identityName'] = self._identityNameEntry.get_text() | |
145 idParams['password'] = self._passwordEntry.get_text() | |
146 | |
147 try: | |
148 idParams['port'] = int(idParams['port']) | |
149 except ValueError: | |
150 pass | |
151 | |
152 f = pb.PBClientFactory() | |
153 from twisted.internet import reactor | |
154 reactor.connectTCP(idParams['host'], idParams['port'], f) | |
155 creds = UsernamePassword(idParams['identityName'], idParams['password']) | |
156 f.login(creds, self.client | |
157 ).addCallbacks(self._cbGotPerspective, self._ebFailedLogin | |
158 ).setTimeout(30 | |
159 ) | |
160 self.statusMsg("Contacting server...") | |
161 | |
162 # serviceName = self._serviceNameEntry.get_text() | |
163 # perspectiveName = self._perspectiveNameEntry.get_text() | |
164 # if not perspectiveName: | |
165 # perspectiveName = idParams['identityName'] | |
166 | |
167 # d = _identityConnector.requestService(serviceName, perspectiveName, | |
168 # self.client) | |
169 # d.addCallbacks(self._cbGotPerspective, self._ebFailedLogin) | |
170 # setCursor to waiting | |
171 | |
172 def _cbGotPerspective(self, perspective): | |
173 self.statusMsg("Connected to server.") | |
174 self.deferredResult.callback(perspective) | |
175 # clear waiting cursor | |
176 self._loginDialog.destroy() | |
177 | |
178 def _ebFailedLogin(self, reason): | |
179 if isinstance(reason, failure.Failure): | |
180 reason = reason.value | |
181 self.statusMsg(reason) | |
182 if isinstance(reason, (unicode, str)): | |
183 text = reason | |
184 else: | |
185 text = unicode(reason) | |
186 msg = gtk.MessageDialog(self._loginDialog, | |
187 gtk.DIALOG_DESTROY_WITH_PARENT, | |
188 gtk.MESSAGE_ERROR, | |
189 gtk.BUTTONS_CLOSE, | |
190 text) | |
191 msg.show_all() | |
192 msg.connect("response", lambda *a: msg.destroy()) | |
193 | |
194 # hostname not found | |
195 # host unreachable | |
196 # connection refused | |
197 # authentication failed | |
198 # no such service | |
199 # no such perspective | |
200 # internal server error | |
201 | |
202 def _on_advancedButton_toggled(self, widget, userdata=None): | |
203 active = widget.get_active() | |
204 if active: | |
205 op = "show" | |
206 else: | |
207 op = "hide" | |
208 for widgetName in self._advancedControls: | |
209 widget = self.glade.get_widget(widgetName) | |
210 getattr(widget, op)() | |
211 | |
212 def statusMsg(self, text): | |
213 if not isinstance(text, (unicode, str)): | |
214 text = unicode(text) | |
215 return self._statusBar.push(self._statusContext, text) | |
OLD | NEW |