__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
# 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>
################################################################################
def _errorpop(master
,text
):
d
=Pmw
.MessageDialog(master
,
d
.component('message').pack(ipadx
=15,ipady
=15)
class PmwFileDialog(Pmw
.Dialog
):
"""File Dialog using Pmw"""
def __init__(self
, parent
= None, **kw
):
# Define the megawidget options.
('filter', '*', self
.newfilter
),
('directory', os
.getcwd(), self
.newdir
),
('filename', '', self
.newfilename
),
self
.defineoptions(kw
, optiondefs
)
# Initialise base class (after defining options).
Pmw
.Dialog
.__init
__(self
, parent
)
interior
= self
.interior()
if self
['info'] is not None:
dn
.grid(row
=0,column
=0,columnspan
=2,padx
=3,pady
=3)
dn
.grid(row
=0+rowoffset
,column
=0,columnspan
=2,padx
=3,pady
=3)
# Create the directory list component.
dnb
.grid(row
=1+rowoffset
,column
=0,sticky
='news',padx
=3,pady
=3)
# Create the filename list component.
fnb
.grid(row
=1+rowoffset
,column
=1,sticky
='news',padx
=3,pady
=3)
# Create the filter entry
ft
.grid(row
=2+rowoffset
,column
=0,columnspan
=2,padx
=3,pady
=3)
# Create the filename entry
fn
.grid(row
=3+rowoffset
,column
=0,columnspan
=2,padx
=3,pady
=3)
fn
.bind('<Return>',self
.okbutton
)
# Buttonbox already exists
bb
=self
.component('buttonbox')
bb
.add('OK',command
=self
.okbutton
)
bb
.add('Cancel',command
=self
.cancelbutton
)
Pmw
.alignlabels([self
.component('filename'),
self
.component('filter'),
self
.component('dirname')])
""" Make information block component at the top """
return self
.createcomponent(
Tkinter
.Label
, (self
.interior(),),
"""Make directory name component"""
return self
.createcomponent(
Pmw
.ComboBox
, (self
.interior(),),
entryfield_value
=self
['directory'],
entryfield_entry_width
=40,
entryfield_validate
=self
.dirvalidate
,
selectioncommand
=self
.setdir
,
"""Make directory name box"""
return self
.createcomponent(
Pmw
.ScrolledListBox
, (self
.interior(),),
label_text
='directories',
dblclickcommand
=self
.selectdir
)
return self
.createcomponent(
Pmw
.ComboBox
, (self
.interior(),),
entryfield_value
=self
['filter'],
entryfield_entry_width
=40,
selectioncommand
=self
.setfilter
,
"""Make filename list box"""
return self
.createcomponent(
Pmw
.ScrolledListBox
, (self
.interior(),),
selectioncommand
=self
.singleselectfile
,
dblclickcommand
=self
.selectfile
)
"""Make file name entry"""
return self
.createcomponent(
Pmw
.ComboBox
, (self
.interior(),),
entryfield_value
=self
['filename'],
entryfield_entry_width
=40,
entryfield_validate
=self
.filevalidate
,
selectioncommand
=self
.setfilename
,
def dirvalidate(self
,string
):
if os
.path
.isdir(string
):
def filevalidate(self
,string
):
elif os
.path
.isfile(string
):
elif os
.path
.exists(string
):
"""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()
"""Cancel the operation"""
"""Insert text v into the entry and at the top of the list of
the combobox w, remove duplicates"""
entry
=w
.component('entry')
list=w
.component('scrolledlist')
while index
<list.index('end'):
if k
==v
or index
>self
['historylen']:
def setfilename(self
,value
):
value
=os
.path
.join(self
['directory'],value
)
dir,fil
=os
.path
.split(value
)
self
.configure(directory
=dir,filename
=value
)
"""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
)
"""Make sure a newly set filter makes it into the combobox list"""
self
.tidy(self
.component('filter'),self
['filter'])
self
.configure(directory
=value
)
"""Make sure a newly set dirname makes it into the combobox list"""
self
.tidy(self
.component('dirname'),self
['directory'])
def singleselectfile(self
):
"""Single click in file listbox. Move file to "filename" combobox"""
cs
=self
.component('filenamebox').curselection()
value
=self
.component('filenamebox').get(cs
)
"""Take the selected file from the filename, normalize it, and OK"""
value
=self
.component('filename').get()
"""Take selected directory from the dirnamebox into the dirname"""
cs
=self
.component('dirnamebox').curselection()
value
=self
.component('dirnamebox').get(cs
)
dir=os
.path
.split(dir)[0]
dir=os
.path
.join(dir,value
)
self
.configure(directory
=dir)
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
self
.configure(directory
=directory
)
self
.configure(filter=filter)
self
.canceled
=1 # Needed for when user kills dialog window
return self
.component('filename').get()
"""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]:
self
.lastdir
=self
['directory']
self
.lastfilter
=self
['filter']
self
.lasttime
=time
.time()
if os
.path
.isdir(os
.path
.join(dir,f
)):
if fnmatch
.fnmatch(f
,filter):
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
class PmwDirDialog(PmwFileDialog
):
"""Directory Dialog using Pmw"""
def __init__(self
, parent
= None, **kw
):
# Define the megawidget options.
('directory', os
.getcwd(), self
.newdir
),
self
.defineoptions(kw
, optiondefs
)
# Initialise base class (after defining options).
Pmw
.Dialog
.__init
__(self
, parent
)
interior
= self
.interior()
if self
['info'] is not None:
dn
.grid(row
=0,column
=0,columnspan
=2,padx
=3,pady
=3)
dn
.grid(row
=1+rowoffset
,column
=0,columnspan
=2,padx
=3,pady
=3)
dn
.bind('<Return>',self
.okbutton
)
# Create the directory list component.
dnb
.grid(row
=0+rowoffset
,column
=0,columnspan
=2,sticky
='news',padx
=3,pady
=3)
# Buttonbox already exists
bb
=self
.component('buttonbox')
bb
.add('OK',command
=self
.okbutton
)
bb
.add('Cancel',command
=self
.cancelbutton
)
"""Get the directory list and show it in the two listboxes"""
# Do not run unnecesarily
if self
.lastdir
==self
['directory']:
self
.lastdir
=self
['directory']
if os
.path
.isdir(os
.path
.join(dir,f
)):
self
.component('dirnamebox').setlist(dirs
)
"""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
)
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
self
.configure(directory
=directory
)
return self
.component('dirname').get()
def dirvalidate(self
,string
):
if os
.path
.isdir(string
):
elif os
.path
.exists(string
):
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
_errorpop(self
.interior(),"Empty filename")
if os
.path
.isdir(filename
) or not os
.path
.exists(filename
):
_errorpop(self
.interior(),"This is not a directory")
class PmwExistingFileDialog(PmwFileDialog
):
def filevalidate(self
,string
):
if os
.path
.isfile(string
):
def validate(self
,filename
):
if os
.path
.isfile(filename
):
elif os
.path
.exists(filename
):
_errorpop(self
.interior(),"This is not a plain file")
_errorpop(self
.interior(),"Please select an existing file")
class PmwExistingDirDialog(PmwDirDialog
):
def dirvalidate(self
,string
):
if os
.path
.isdir(string
):
def validate(self
,filename
):
if os
.path
.isdir(filename
):
elif os
.path
.exists(filename
):
_errorpop(self
.interior(),"This is not a directory")
_errorpop(self
.interior(),"Please select an existing directory")
f0
.title('File name dialog')
print '\nFilename : ',repr(n
),'\n'
f1
=PmwDirDialog(root
,info
='This is a directory dialog')
f1
.title('Directory name dialog')
print "Dirname : ",repr(n
)