root/trunk/twisted/spread/ui/tkutil.py

Revision 30752, 12.5 KB (checked in by exarkun, 15 months ago)

Rewrite the copyright headers to exclude date information.

Author: exarkun
Reviewer: glyph
Fixes: #4857

To avoid the need to perpetually update copyright dates in each file in Twisted,
remove the dates from most files and just leave them in the LICENSE file.

As a side effect, some files also have had a trailing newline added where it was
missing before.

Line 
1
2# Copyright (c) Twisted Matrix Laboratories.
3# See LICENSE for details.
4
5"""Utilities for building L{PB<twisted.spread.pb>} clients with L{Tkinter}.
6"""
7from Tkinter import *
8from tkSimpleDialog import _QueryString
9from tkFileDialog import _Dialog
10from twisted.spread import pb
11from twisted.internet import reactor
12from twisted import copyright
13
14import 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
20class _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
35def 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
47def 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
54class 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
197class 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
274class DirectoryBrowser(_Dialog):
275    command = "tk_chooseDirectory"
276
277def askdirectory(**options):
278    "Ask for a directory to save to."
279
280    return apply(DirectoryBrowser, (), options).show()
281
282class 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,columnspan=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
315class 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).addErrback(
386            self.couldNotConnect)
387
388    def couldNotConnect(self,f):
389        self.loginReport("could not connect:"+f.getErrorMessage())
390
391if __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()
Note: See TracBrowser for help on using the browser.