historical/toontown-classic.git/panda/Pmw/Pmw_1_3/contrib/PmwFileDialog.py
2024-01-16 11:20:27 -06:00

498 lines
14 KiB
Python

#
__version__ = '$Id: PmwFileDialog.py,v 1.2 2002/08/23 15:03:35 gregm Exp $'
#
# Filename dialogs using Pmw
#
# (C) Rob W.W. Hooft, Nonius BV, 1998
#
# Modifications:
#
# J. Willem M. Nissink, Cambridge Crystallographic Data Centre, 8/2002
# Added optional information pane at top of dialog; if option
# 'info' is specified, the text given will be shown (in blue).
# Modified example to show both file and directory-type dialog
#
# No Guarantees. Distribute Freely.
# Please send bug-fixes/patches/features to <r.hooft@euromail.com>
#
################################################################################
import os,fnmatch,time
import Tkinter,Pmw
#Pmw.setversion("0.8.5")
def _errorpop(master,text):
d=Pmw.MessageDialog(master,
title="Error",
message_text=text,
buttons=("OK",))
d.component('message').pack(ipadx=15,ipady=15)
d.activate()
d.destroy()
class PmwFileDialog(Pmw.Dialog):
"""File Dialog using Pmw"""
def __init__(self, parent = None, **kw):
# Define the megawidget options.
optiondefs = (
('filter', '*', self.newfilter),
('directory', os.getcwd(), self.newdir),
('filename', '', self.newfilename),
('historylen',10, None),
('command', None, None),
('info', None, None),
)
self.defineoptions(kw, optiondefs)
# Initialise base class (after defining options).
Pmw.Dialog.__init__(self, parent)
self.withdraw()
# Create the components.
interior = self.interior()
if self['info'] is not None:
rowoffset=1
dn = self.infotxt()
dn.grid(row=0,column=0,columnspan=2,padx=3,pady=3)
else:
rowoffset=0
dn = self.mkdn()
dn.grid(row=0+rowoffset,column=0,columnspan=2,padx=3,pady=3)
del dn
# Create the directory list component.
dnb = self.mkdnb()
dnb.grid(row=1+rowoffset,column=0,sticky='news',padx=3,pady=3)
del dnb
# Create the filename list component.
fnb = self.mkfnb()
fnb.grid(row=1+rowoffset,column=1,sticky='news',padx=3,pady=3)
del fnb
# Create the filter entry
ft = self.mkft()
ft.grid(row=2+rowoffset,column=0,columnspan=2,padx=3,pady=3)
del ft
# Create the filename entry
fn = self.mkfn()
fn.grid(row=3+rowoffset,column=0,columnspan=2,padx=3,pady=3)
fn.bind('<Return>',self.okbutton)
del fn
# Buttonbox already exists
bb=self.component('buttonbox')
bb.add('OK',command=self.okbutton)
bb.add('Cancel',command=self.cancelbutton)
del bb
Pmw.alignlabels([self.component('filename'),
self.component('filter'),
self.component('dirname')])
def infotxt(self):
""" Make information block component at the top """
return self.createcomponent(
'infobox',
(), None,
Tkinter.Label, (self.interior(),),
width=51,
relief='groove',
foreground='darkblue',
justify='left',
text=self['info']
)
def mkdn(self):
"""Make directory name component"""
return self.createcomponent(
'dirname',
(), None,
Pmw.ComboBox, (self.interior(),),
entryfield_value=self['directory'],
entryfield_entry_width=40,
entryfield_validate=self.dirvalidate,
selectioncommand=self.setdir,
labelpos='w',
label_text='Directory:')
def mkdnb(self):
"""Make directory name box"""
return self.createcomponent(
'dirnamebox',
(), None,
Pmw.ScrolledListBox, (self.interior(),),
label_text='directories',
labelpos='n',
hscrollmode='none',
dblclickcommand=self.selectdir)
def mkft(self):
"""Make filter"""
return self.createcomponent(
'filter',
(), None,
Pmw.ComboBox, (self.interior(),),
entryfield_value=self['filter'],
entryfield_entry_width=40,
selectioncommand=self.setfilter,
labelpos='w',
label_text='Filter:')
def mkfnb(self):
"""Make filename list box"""
return self.createcomponent(
'filenamebox',
(), None,
Pmw.ScrolledListBox, (self.interior(),),
label_text='files',
labelpos='n',
hscrollmode='none',
selectioncommand=self.singleselectfile,
dblclickcommand=self.selectfile)
def mkfn(self):
"""Make file name entry"""
return self.createcomponent(
'filename',
(), None,
Pmw.ComboBox, (self.interior(),),
entryfield_value=self['filename'],
entryfield_entry_width=40,
entryfield_validate=self.filevalidate,
selectioncommand=self.setfilename,
labelpos='w',
label_text='Filename:')
def dirvalidate(self,string):
if os.path.isdir(string):
return Pmw.OK
else:
return Pmw.PARTIAL
def filevalidate(self,string):
if string=='':
return Pmw.PARTIAL
elif os.path.isfile(string):
return Pmw.OK
elif os.path.exists(string):
return Pmw.PARTIAL
else:
return Pmw.OK
def okbutton(self):
"""OK action: user thinks he has input valid data and wants to
proceed. This is also called by <Return> in the filename entry"""
fn=self.component('filename').get()
self.setfilename(fn)
if self.validate(fn):
self.canceled=0
self.deactivate()
def cancelbutton(self):
"""Cancel the operation"""
self.canceled=1
self.deactivate()
def tidy(self,w,v):
"""Insert text v into the entry and at the top of the list of
the combobox w, remove duplicates"""
if not v:
return
entry=w.component('entry')
entry.delete(0,'end')
entry.insert(0,v)
list=w.component('scrolledlist')
list.insert(0,v)
index=1
while index<list.index('end'):
k=list.get(index)
if k==v or index>self['historylen']:
list.delete(index)
else:
index=index+1
w.checkentry()
def setfilename(self,value):
if not value:
return
value=os.path.join(self['directory'],value)
dir,fil=os.path.split(value)
self.configure(directory=dir,filename=value)
c=self['command']
if callable(c):
c()
def newfilename(self):
"""Make sure a newly set filename makes it into the combobox list"""
self.tidy(self.component('filename'),self['filename'])
def setfilter(self,value):
self.configure(filter=value)
def newfilter(self):
"""Make sure a newly set filter makes it into the combobox list"""
self.tidy(self.component('filter'),self['filter'])
self.fillit()
def setdir(self,value):
self.configure(directory=value)
def newdir(self):
"""Make sure a newly set dirname makes it into the combobox list"""
self.tidy(self.component('dirname'),self['directory'])
self.fillit()
def singleselectfile(self):
"""Single click in file listbox. Move file to "filename" combobox"""
cs=self.component('filenamebox').curselection()
if cs!=():
value=self.component('filenamebox').get(cs)
self.setfilename(value)
def selectfile(self):
"""Take the selected file from the filename, normalize it, and OK"""
self.singleselectfile()
value=self.component('filename').get()
self.setfilename(value)
if value:
self.okbutton()
def selectdir(self):
"""Take selected directory from the dirnamebox into the dirname"""
cs=self.component('dirnamebox').curselection()
if cs!=():
value=self.component('dirnamebox').get(cs)
dir=self['directory']
if not dir:
dir=os.getcwd()
if value:
if value=='..':
dir=os.path.split(dir)[0]
else:
dir=os.path.join(dir,value)
self.configure(directory=dir)
self.fillit()
def askfilename(self,directory=None,filter=None):
"""The actual client function. Activates the dialog, and
returns only after a valid filename has been entered
(return value is that filename) or when canceled (return
value is None)"""
if directory!=None:
self.configure(directory=directory)
if filter!=None:
self.configure(filter=filter)
self.fillit()
self.canceled=1 # Needed for when user kills dialog window
self.activate()
if self.canceled:
return None
else:
return self.component('filename').get()
lastdir=""
lastfilter=None
lasttime=0
def fillit(self):
"""Get the directory list and show it in the two listboxes"""
# Do not run unnecesarily
if self.lastdir==self['directory'] and self.lastfilter==self['filter'] and self.lasttime>os.stat(self.lastdir)[8]:
return
self.lastdir=self['directory']
self.lastfilter=self['filter']
self.lasttime=time.time()
dir=self['directory']
if not dir:
dir=os.getcwd()
dirs=['..']
files=[]
try:
fl=os.listdir(dir)
fl.sort()
except os.error,arg:
if arg[0] in (2,20):
return
raise
for f in fl:
if os.path.isdir(os.path.join(dir,f)):
dirs.append(f)
else:
filter=self['filter']
if not filter:
filter='*'
if fnmatch.fnmatch(f,filter):
files.append(f)
self.component('filenamebox').setlist(files)
self.component('dirnamebox').setlist(dirs)
def validate(self,filename):
"""Validation function. Should return 1 if the filename is valid,
0 if invalid. May pop up dialogs to tell user why. Especially
suited to subclasses: i.e. only return 1 if the file does/doesn't
exist"""
return 1
class PmwDirDialog(PmwFileDialog):
"""Directory Dialog using Pmw"""
def __init__(self, parent = None, **kw):
# Define the megawidget options.
optiondefs = (
('directory', os.getcwd(), self.newdir),
('historylen',10, None),
('command', None, None),
('info', None, None),
)
self.defineoptions(kw, optiondefs)
# Initialise base class (after defining options).
Pmw.Dialog.__init__(self, parent)
self.withdraw()
# Create the components.
interior = self.interior()
if self['info'] is not None:
rowoffset=1
dn = self.infotxt()
dn.grid(row=0,column=0,columnspan=2,padx=3,pady=3)
else:
rowoffset=0
dn = self.mkdn()
dn.grid(row=1+rowoffset,column=0,columnspan=2,padx=3,pady=3)
dn.bind('<Return>',self.okbutton)
del dn
# Create the directory list component.
dnb = self.mkdnb()
dnb.grid(row=0+rowoffset,column=0,columnspan=2,sticky='news',padx=3,pady=3)
del dnb
# Buttonbox already exists
bb=self.component('buttonbox')
bb.add('OK',command=self.okbutton)
bb.add('Cancel',command=self.cancelbutton)
del bb
lastdir=""
def fillit(self):
"""Get the directory list and show it in the two listboxes"""
# Do not run unnecesarily
if self.lastdir==self['directory']:
return
self.lastdir=self['directory']
dir=self['directory']
if not dir:
dir=os.getcwd()
dirs=['..']
try:
fl=os.listdir(dir)
fl.sort()
except os.error,arg:
if arg[0] in (2,20):
return
raise
for f in fl:
if os.path.isdir(os.path.join(dir,f)):
dirs.append(f)
self.component('dirnamebox').setlist(dirs)
def okbutton(self):
"""OK action: user thinks he has input valid data and wants to
proceed. This is also called by <Return> in the dirname entry"""
fn=self.component('dirname').get()
self.configure(directory=fn)
if self.validate(fn):
self.canceled=0
self.deactivate()
def askfilename(self,directory=None):
"""The actual client function. Activates the dialog, and
returns only after a valid filename has been entered
(return value is that filename) or when canceled (return
value is None)"""
if directory!=None:
self.configure(directory=directory)
self.fillit()
self.activate()
if self.canceled:
return None
else:
return self.component('dirname').get()
def dirvalidate(self,string):
if os.path.isdir(string):
return Pmw.OK
elif os.path.exists(string):
return Pmw.PARTIAL
else:
return Pmw.OK
def validate(self,filename):
"""Validation function. Should return 1 if the filename is valid,
0 if invalid. May pop up dialogs to tell user why. Especially
suited to subclasses: i.e. only return 1 if the file does/doesn't
exist"""
if filename=='':
_errorpop(self.interior(),"Empty filename")
return 0
if os.path.isdir(filename) or not os.path.exists(filename):
return 1
else:
_errorpop(self.interior(),"This is not a directory")
return 0
class PmwExistingFileDialog(PmwFileDialog):
def filevalidate(self,string):
if os.path.isfile(string):
return Pmw.OK
else:
return Pmw.PARTIAL
def validate(self,filename):
if os.path.isfile(filename):
return 1
elif os.path.exists(filename):
_errorpop(self.interior(),"This is not a plain file")
return 0
else:
_errorpop(self.interior(),"Please select an existing file")
return 0
class PmwExistingDirDialog(PmwDirDialog):
def dirvalidate(self,string):
if os.path.isdir(string):
return Pmw.OK
else:
return Pmw.PARTIAL
def validate(self,filename):
if os.path.isdir(filename):
return 1
elif os.path.exists(filename):
_errorpop(self.interior(),"This is not a directory")
return 0
else:
_errorpop(self.interior(),"Please select an existing directory")
if __name__=="__main__":
root=Tkinter.Tk()
root.withdraw()
Pmw.initialise()
f0=PmwFileDialog(root)
f0.title('File name dialog')
n=f0.askfilename()
print '\nFilename : ',repr(n),'\n'
f1=PmwDirDialog(root,info='This is a directory dialog')
f1.title('Directory name dialog')
while 1:
n=f1.askfilename()
if n is None:
break
print "Dirname : ",repr(n)