OLD | NEW |
| (Empty) |
1 | |
2 # Copyright (c) 2001-2004 Twisted Matrix Laboratories. | |
3 # See LICENSE for details. | |
4 | |
5 """Utilities for building L{PB<twisted.spread.pb>} clients with L{Tkinter}. | |
6 """ | |
7 from Tkinter import * | |
8 from tkSimpleDialog import _QueryString | |
9 from tkFileDialog import _Dialog | |
10 from twisted.spread import pb | |
11 from twisted.internet import reactor | |
12 from twisted import copyright | |
13 | |
14 import string | |
15 | |
16 #normalFont = Font("-adobe-courier-medium-r-normal-*-*-120-*-*-m-*-iso8859-1") | |
17 #boldFont = Font("-adobe-courier-bold-r-normal-*-*-120-*-*-m-*-iso8859-1") | |
18 #errorFont = Font("-adobe-courier-medium-o-normal-*-*-120-*-*-m-*-iso8859-1") | |
19 | |
20 class _QueryPassword(_QueryString): | |
21 def body(self, master): | |
22 | |
23 w = Label(master, text=self.prompt, justify=LEFT) | |
24 w.grid(row=0, padx=5, sticky=W) | |
25 | |
26 self.entry = Entry(master, name="entry",show="*") | |
27 self.entry.grid(row=1, padx=5, sticky=W+E) | |
28 | |
29 if self.initialvalue: | |
30 self.entry.insert(0, self.initialvalue) | |
31 self.entry.select_range(0, END) | |
32 | |
33 return self.entry | |
34 | |
35 def askpassword(title, prompt, **kw): | |
36 '''get a password from the user | |
37 | |
38 @param title: the dialog title | |
39 @param prompt: the label text | |
40 @param **kw: see L{SimpleDialog} class | |
41 | |
42 @returns: a string | |
43 ''' | |
44 d = apply(_QueryPassword, (title, prompt), kw) | |
45 return d.result | |
46 | |
47 def grid_setexpand(widget): | |
48 cols,rows=widget.grid_size() | |
49 for i in range(cols): | |
50 widget.columnconfigure(i,weight=1) | |
51 for i in range(rows): | |
52 widget.rowconfigure(i,weight=1) | |
53 | |
54 class CList(Frame): | |
55 def __init__(self,parent,labels,disablesorting=0,**kw): | |
56 Frame.__init__(self,parent) | |
57 self.labels=labels | |
58 self.lists=[] | |
59 self.disablesorting=disablesorting | |
60 kw["exportselection"]=0 | |
61 for i in range(len(labels)): | |
62 b=Button(self,text=labels[i],anchor=W,height=1,pady=0) | |
63 b.config(command=lambda s=self,i=i:s.setSort(i)) | |
64 b.grid(column=i,row=0,sticky=N+E+W) | |
65 box=apply(Listbox,(self,),kw) | |
66 box.grid(column=i,row=1,sticky=N+E+S+W) | |
67 self.lists.append(box) | |
68 grid_setexpand(self) | |
69 self.rowconfigure(0,weight=0) | |
70 self._callall("bind",'<Button-1>',self.Button1) | |
71 self._callall("bind",'<B1-Motion>',self.Button1) | |
72 self.bind('<Up>',self.UpKey) | |
73 self.bind('<Down>',self.DownKey) | |
74 self.sort=None | |
75 | |
76 def _callall(self,funcname,*args,**kw): | |
77 rets=[] | |
78 for l in self.lists: | |
79 func=getattr(l,funcname) | |
80 ret=apply(func,args,kw) | |
81 if ret!=None: rets.append(ret) | |
82 if rets: return rets | |
83 | |
84 def Button1(self,e): | |
85 index=self.nearest(e.y) | |
86 self.select_clear(0,END) | |
87 self.select_set(index) | |
88 self.activate(index) | |
89 return "break" | |
90 | |
91 def UpKey(self,e): | |
92 index=self.index(ACTIVE) | |
93 if index: | |
94 self.select_clear(0,END) | |
95 self.select_set(index-1) | |
96 return "break" | |
97 | |
98 def DownKey(self,e): | |
99 index=self.index(ACTIVE) | |
100 if index!=self.size()-1: | |
101 self.select_clear(0,END) | |
102 self.select_set(index+1) | |
103 return "break" | |
104 | |
105 def setSort(self,index): | |
106 if self.sort==None: | |
107 self.sort=[index,1] | |
108 elif self.sort[0]==index: | |
109 self.sort[1]=-self.sort[1] | |
110 else: | |
111 self.sort=[index,1] | |
112 self._sort() | |
113 | |
114 def _sort(self): | |
115 if self.disablesorting: | |
116 return | |
117 if self.sort==None: | |
118 return | |
119 ind,direc=self.sort | |
120 li=list(self.get(0,END)) | |
121 li.sort(lambda x,y,i=ind,d=direc:d*cmp(x[i],y[i])) | |
122 self.delete(0,END) | |
123 for l in li: | |
124 self._insert(END,l) | |
125 def activate(self,index): | |
126 self._callall("activate",index) | |
127 | |
128 # def bbox(self,index): | |
129 # return self._callall("bbox",index) | |
130 | |
131 def curselection(self): | |
132 return self.lists[0].curselection() | |
133 | |
134 def delete(self,*args): | |
135 apply(self._callall,("delete",)+args) | |
136 | |
137 def get(self,*args): | |
138 bad=apply(self._callall,("get",)+args) | |
139 if len(args)==1: | |
140 return bad | |
141 ret=[] | |
142 for i in range(len(bad[0])): | |
143 r=[] | |
144 for j in range(len(bad)): | |
145 r.append(bad[j][i]) | |
146 ret.append(r) | |
147 return ret | |
148 | |
149 def index(self,index): | |
150 return self.lists[0].index(index) | |
151 | |
152 def insert(self,index,items): | |
153 self._insert(index,items) | |
154 self._sort() | |
155 | |
156 def _insert(self,index,items): | |
157 for i in range(len(items)): | |
158 self.lists[i].insert(index,items[i]) | |
159 | |
160 def nearest(self,y): | |
161 return self.lists[0].nearest(y) | |
162 | |
163 def see(self,index): | |
164 self._callall("see",index) | |
165 | |
166 def size(self): | |
167 return self.lists[0].size() | |
168 | |
169 def selection_anchor(self,index): | |
170 self._callall("selection_anchor",index) | |
171 | |
172 select_anchor=selection_anchor | |
173 | |
174 def selection_clear(self,*args): | |
175 apply(self._callall,("selection_clear",)+args) | |
176 | |
177 select_clear=selection_clear | |
178 | |
179 def selection_includes(self,index): | |
180 return self.lists[0].select_includes(index) | |
181 | |
182 select_includes=selection_includes | |
183 | |
184 def selection_set(self,*args): | |
185 apply(self._callall,("selection_set",)+args) | |
186 | |
187 select_set=selection_set | |
188 | |
189 def xview(self,*args): | |
190 if not args: return self.lists[0].xview() | |
191 apply(self._callall,("xview",)+args) | |
192 | |
193 def yview(self,*args): | |
194 if not args: return self.lists[0].yview() | |
195 apply(self._callall,("yview",)+args) | |
196 | |
197 class ProgressBar: | |
198 def __init__(self, master=None, orientation="horizontal", | |
199 min=0, max=100, width=100, height=18, | |
200 doLabel=1, appearance="sunken", | |
201 fillColor="blue", background="gray", | |
202 labelColor="yellow", labelFont="Verdana", | |
203 labelText="", labelFormat="%d%%", | |
204 value=0, bd=2): | |
205 # preserve various values | |
206 self.master=master | |
207 self.orientation=orientation | |
208 self.min=min | |
209 self.max=max | |
210 self.width=width | |
211 self.height=height | |
212 self.doLabel=doLabel | |
213 self.fillColor=fillColor | |
214 self.labelFont= labelFont | |
215 self.labelColor=labelColor | |
216 self.background=background | |
217 self.labelText=labelText | |
218 self.labelFormat=labelFormat | |
219 self.value=value | |
220 self.frame=Frame(master, relief=appearance, bd=bd) | |
221 self.canvas=Canvas(self.frame, height=height, width=width, bd=0, | |
222 highlightthickness=0, background=background) | |
223 self.scale=self.canvas.create_rectangle(0, 0, width, height, | |
224 fill=fillColor) | |
225 self.label=self.canvas.create_text(self.canvas.winfo_reqwidth() / 2, | |
226 height / 2, text=labelText, | |
227 anchor="c", fill=labelColor, | |
228 font=self.labelFont) | |
229 self.update() | |
230 self.canvas.pack(side='top', fill='x', expand='no') | |
231 | |
232 def updateProgress(self, newValue, newMax=None): | |
233 if newMax: | |
234 self.max = newMax | |
235 self.value = newValue | |
236 self.update() | |
237 | |
238 def update(self): | |
239 # Trim the values to be between min and max | |
240 value=self.value | |
241 if value > self.max: | |
242 value = self.max | |
243 if value < self.min: | |
244 value = self.min | |
245 # Adjust the rectangle | |
246 if self.orientation == "horizontal": | |
247 self.canvas.coords(self.scale, 0, 0, | |
248 float(value) / self.max * self.width, self.height) | |
249 else: | |
250 self.canvas.coords(self.scale, 0, | |
251 self.height - (float(value) / | |
252 self.max*self.height), | |
253 self.width, self.height) | |
254 # Now update the colors | |
255 self.canvas.itemconfig(self.scale, fill=self.fillColor) | |
256 self.canvas.itemconfig(self.label, fill=self.labelColor) | |
257 # And update the label | |
258 if self.doLabel: | |
259 if value: | |
260 if value >= 0: | |
261 pvalue = int((float(value) / float(self.max)) * | |
262 100.0) | |
263 else: | |
264 pvalue = 0 | |
265 self.canvas.itemconfig(self.label, text=self.labelFormat | |
266 % pvalue) | |
267 else: | |
268 self.canvas.itemconfig(self.label, text='') | |
269 else: | |
270 self.canvas.itemconfig(self.label, text=self.labelFormat % | |
271 self.labelText) | |
272 self.canvas.update_idletasks() | |
273 | |
274 class DirectoryBrowser(_Dialog): | |
275 command = "tk_chooseDirectory" | |
276 | |
277 def askdirectory(**options): | |
278 "Ask for a directory to save to." | |
279 | |
280 return apply(DirectoryBrowser, (), options).show() | |
281 | |
282 class GenericLogin(Toplevel): | |
283 def __init__(self,callback,buttons): | |
284 Toplevel.__init__(self) | |
285 self.callback=callback | |
286 Label(self,text="Twisted v%s"%copyright.version).grid(column=0,row=0,col
umnspan=2) | |
287 self.entries={} | |
288 row=1 | |
289 for stuff in buttons: | |
290 label,value=stuff[:2] | |
291 if len(stuff)==3: | |
292 dict=stuff[2] | |
293 else: dict={} | |
294 Label(self,text=label+": ").grid(column=0,row=row) | |
295 e=apply(Entry,(self,),dict) | |
296 e.grid(column=1,row=row) | |
297 e.insert(0,value) | |
298 self.entries[label]=e | |
299 row=row+1 | |
300 Button(self,text="Login",command=self.doLogin).grid(column=0,row=row) | |
301 Button(self,text="Cancel",command=self.close).grid(column=1,row=row) | |
302 self.protocol('WM_DELETE_WINDOW',self.close) | |
303 | |
304 def close(self): | |
305 self.tk.quit() | |
306 self.destroy() | |
307 | |
308 def doLogin(self): | |
309 values={} | |
310 for k in self.entries.keys(): | |
311 values[string.lower(k)]=self.entries[k].get() | |
312 self.callback(values) | |
313 self.destroy() | |
314 | |
315 class Login(Toplevel): | |
316 def __init__(self, | |
317 callback, | |
318 referenced = None, | |
319 initialUser = "guest", | |
320 initialPassword = "guest", | |
321 initialHostname = "localhost", | |
322 initialService = "", | |
323 initialPortno = pb.portno): | |
324 Toplevel.__init__(self) | |
325 version_label = Label(self,text="Twisted v%s" % copyright.version) | |
326 self.pbReferenceable = referenced | |
327 self.pbCallback = callback | |
328 # version_label.show() | |
329 self.username = Entry(self) | |
330 self.password = Entry(self,show='*') | |
331 self.hostname = Entry(self) | |
332 self.service = Entry(self) | |
333 self.port = Entry(self) | |
334 | |
335 self.username.insert(0,initialUser) | |
336 self.password.insert(0,initialPassword) | |
337 self.service.insert(0,initialService) | |
338 self.hostname.insert(0,initialHostname) | |
339 self.port.insert(0,str(initialPortno)) | |
340 | |
341 userlbl=Label(self,text="Username:") | |
342 passlbl=Label(self,text="Password:") | |
343 servicelbl=Label(self,text="Service:") | |
344 hostlbl=Label(self,text="Hostname:") | |
345 portlbl=Label(self,text="Port #:") | |
346 self.logvar=StringVar() | |
347 self.logvar.set("Protocol PB-%s"%pb.Broker.version) | |
348 self.logstat = Label(self,textvariable=self.logvar) | |
349 self.okbutton = Button(self,text="Log In", command=self.login) | |
350 | |
351 version_label.grid(column=0,row=0,columnspan=2) | |
352 z=0 | |
353 for i in [[userlbl,self.username], | |
354 [passlbl,self.password], | |
355 [hostlbl,self.hostname], | |
356 [servicelbl,self.service], | |
357 [portlbl,self.port]]: | |
358 i[0].grid(column=0,row=z+1) | |
359 i[1].grid(column=1,row=z+1) | |
360 z = z+1 | |
361 | |
362 self.logstat.grid(column=0,row=6,columnspan=2) | |
363 self.okbutton.grid(column=0,row=7,columnspan=2) | |
364 | |
365 self.protocol('WM_DELETE_WINDOW',self.tk.quit) | |
366 | |
367 def loginReset(self): | |
368 self.logvar.set("Idle.") | |
369 | |
370 def loginReport(self, txt): | |
371 self.logvar.set(txt) | |
372 self.after(30000, self.loginReset) | |
373 | |
374 def login(self): | |
375 host = self.hostname.get() | |
376 port = self.port.get() | |
377 service = self.service.get() | |
378 try: | |
379 port = int(port) | |
380 except: | |
381 pass | |
382 user = self.username.get() | |
383 pswd = self.password.get() | |
384 pb.connect(host, port, user, pswd, service, | |
385 client=self.pbReferenceable).addCallback(self.pbCallback).add
Errback( | |
386 self.couldNotConnect) | |
387 | |
388 def couldNotConnect(self,f): | |
389 self.loginReport("could not connect:"+f.getErrorMessage()) | |
390 | |
391 if __name__=="__main__": | |
392 root=Tk() | |
393 o=CList(root,["Username","Online","Auto-Logon","Gateway"]) | |
394 o.pack() | |
395 for i in range(0,16,4): | |
396 o.insert(END,[i,i+1,i+2,i+3]) | |
397 mainloop() | |
OLD | NEW |