1
"""File selection dialog classes.
12
from Dialog import Dialog
23
"""Standard file selection dialog -- no checks on selected file.
27
d = FileDialog(master)
28
fname = d.go(dir_or_file, pattern, default, key)
29
if fname is None: ...canceled...
32
All arguments to go() are optional.
34
The 'key' argument specifies a key in the global dictionary
35
'dialogstates', which keeps track of the values for the directory
36
and pattern arguments, overriding the values passed in (it does
37
not keep track of the default argument!). If no key is specified,
38
the dialog keeps no memory of previous state. Note that memory is
39
kept even when the dialog is canceled. (All this emulates the
40
behavior of the Macintosh file selection dialogs.)
44
title = "File Selection Dialog"
46
def __init__(self, master, title=None):
47
if title is None: title = self.title
51
self.top = Toplevel(master)
53
self.top.iconname(title)
55
self.botframe = Frame(self.top)
56
self.botframe.pack(side=BOTTOM, fill=X)
58
self.selection = Entry(self.top)
59
self.selection.pack(side=BOTTOM, fill=X)
60
self.selection.bind('<Return>', self.ok_event)
62
self.filter = Entry(self.top)
63
self.filter.pack(side=TOP, fill=X)
64
self.filter.bind('<Return>', self.filter_command)
66
self.midframe = Frame(self.top)
67
self.midframe.pack(expand=YES, fill=BOTH)
69
self.filesbar = Scrollbar(self.midframe)
70
self.filesbar.pack(side=RIGHT, fill=Y)
71
self.files = Listbox(self.midframe, exportselection=0,
72
yscrollcommand=(self.filesbar, 'set'))
73
self.files.pack(side=RIGHT, expand=YES, fill=BOTH)
74
btags = self.files.bindtags()
75
self.files.bindtags(btags[1:] + btags[:1])
76
self.files.bind('<ButtonRelease-1>', self.files_select_event)
77
self.files.bind('<Double-ButtonRelease-1>', self.files_double_event)
78
self.filesbar.config(command=(self.files, 'yview'))
80
self.dirsbar = Scrollbar(self.midframe)
81
self.dirsbar.pack(side=LEFT, fill=Y)
82
self.dirs = Listbox(self.midframe, exportselection=0,
83
yscrollcommand=(self.dirsbar, 'set'))
84
self.dirs.pack(side=LEFT, expand=YES, fill=BOTH)
85
self.dirsbar.config(command=(self.dirs, 'yview'))
86
btags = self.dirs.bindtags()
87
self.dirs.bindtags(btags[1:] + btags[:1])
88
self.dirs.bind('<ButtonRelease-1>', self.dirs_select_event)
89
self.dirs.bind('<Double-ButtonRelease-1>', self.dirs_double_event)
91
self.ok_button = Button(self.botframe,
93
command=self.ok_command)
94
self.ok_button.pack(side=LEFT)
95
self.filter_button = Button(self.botframe,
97
command=self.filter_command)
98
self.filter_button.pack(side=LEFT, expand=YES)
99
self.cancel_button = Button(self.botframe,
101
command=self.cancel_command)
102
self.cancel_button.pack(side=RIGHT)
104
self.top.protocol('WM_DELETE_WINDOW', self.cancel_command)
105
# XXX Are the following okay for a general audience?
106
self.top.bind('<Alt-w>', self.cancel_command)
107
self.top.bind('<Alt-W>', self.cancel_command)
109
def go(self, dir_or_file=os.curdir, pattern="*", default="", key=None):
110
if key and dialogstates.has_key(key):
111
self.directory, pattern = dialogstates[key]
113
dir_or_file = os.path.expanduser(dir_or_file)
114
if os.path.isdir(dir_or_file):
115
self.directory = dir_or_file
117
self.directory, default = os.path.split(dir_or_file)
118
self.set_filter(self.directory, pattern)
119
self.set_selection(default)
120
self.filter_command()
121
self.selection.focus_set()
122
self.top.wait_visibility() # window needs to be visible for the grab
125
self.master.mainloop() # Exited by self.quit(how)
127
directory, pattern = self.get_filter()
129
directory = os.path.dirname(self.how)
130
dialogstates[key] = directory, pattern
134
def quit(self, how=None):
136
self.master.quit() # Exit mainloop()
138
def dirs_double_event(self, event):
139
self.filter_command()
141
def dirs_select_event(self, event):
142
dir, pat = self.get_filter()
143
subdir = self.dirs.get('active')
144
dir = os.path.normpath(os.path.join(self.directory, subdir))
145
self.set_filter(dir, pat)
147
def files_double_event(self, event):
150
def files_select_event(self, event):
151
file = self.files.get('active')
152
self.set_selection(file)
154
def ok_event(self, event):
157
def ok_command(self):
158
self.quit(self.get_selection())
160
def filter_command(self, event=None):
161
dir, pat = self.get_filter()
163
names = os.listdir(dir)
168
self.set_filter(dir, pat)
170
subdirs = [os.pardir]
173
fullname = os.path.join(dir, name)
174
if os.path.isdir(fullname):
176
elif fnmatch.fnmatch(name, pat):
177
matchingfiles.append(name)
178
self.dirs.delete(0, END)
180
self.dirs.insert(END, name)
181
self.files.delete(0, END)
182
for name in matchingfiles:
183
self.files.insert(END, name)
184
head, tail = os.path.split(self.get_selection())
185
if tail == os.curdir: tail = ''
186
self.set_selection(tail)
188
def get_filter(self):
189
filter = self.filter.get()
190
filter = os.path.expanduser(filter)
191
if filter[-1:] == os.sep or os.path.isdir(filter):
192
filter = os.path.join(filter, "*")
193
return os.path.split(filter)
195
def get_selection(self):
196
file = self.selection.get()
197
file = os.path.expanduser(file)
200
def cancel_command(self, event=None):
203
def set_filter(self, dir, pat):
204
if not os.path.isabs(dir):
210
dir = os.path.join(pwd, dir)
211
dir = os.path.normpath(dir)
212
self.filter.delete(0, END)
213
self.filter.insert(END, os.path.join(dir or os.curdir, pat or "*"))
215
def set_selection(self, file):
216
self.selection.delete(0, END)
217
self.selection.insert(END, os.path.join(self.directory, file))
220
class LoadFileDialog(FileDialog):
222
"""File selection dialog which checks that the file exists."""
224
title = "Load File Selection Dialog"
226
def ok_command(self):
227
file = self.get_selection()
228
if not os.path.isfile(file):
234
class SaveFileDialog(FileDialog):
236
"""File selection dialog which checks that the file may be created."""
238
title = "Save File Selection Dialog"
240
def ok_command(self):
241
file = self.get_selection()
242
if os.path.exists(file):
243
if os.path.isdir(file):
247
title="Overwrite Existing File Question",
248
text="Overwrite existing file %r?" % (file,),
251
strings=("Yes", "Cancel"))
255
head, tail = os.path.split(file)
256
if not os.path.isdir(head):
263
"""Simple test program."""
266
fd = LoadFileDialog(root)
267
loadfile = fd.go(key="test")
268
fd = SaveFileDialog(root)
269
savefile = fd.go(key="test")
270
print loadfile, savefile
273
if __name__ == '__main__':