~malept/ubuntu/lucid/python2.6/dev-dependency-fix

« back to all changes in this revision

Viewing changes to Lib/lib-tk/FileDialog.py

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-02-13 12:51:00 UTC
  • Revision ID: james.westby@ubuntu.com-20090213125100-uufgcb9yeqzujpqw
Tags: upstream-2.6.1
ImportĀ upstreamĀ versionĀ 2.6.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""File selection dialog classes.
 
2
 
 
3
Classes:
 
4
 
 
5
- FileDialog
 
6
- LoadFileDialog
 
7
- SaveFileDialog
 
8
 
 
9
"""
 
10
 
 
11
from Tkinter import *
 
12
from Dialog import Dialog
 
13
 
 
14
import os
 
15
import fnmatch
 
16
 
 
17
 
 
18
dialogstates = {}
 
19
 
 
20
 
 
21
class FileDialog:
 
22
 
 
23
    """Standard file selection dialog -- no checks on selected file.
 
24
 
 
25
    Usage:
 
26
 
 
27
        d = FileDialog(master)
 
28
        fname = d.go(dir_or_file, pattern, default, key)
 
29
        if fname is None: ...canceled...
 
30
        else: ...open file...
 
31
 
 
32
    All arguments to go() are optional.
 
33
 
 
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.)
 
41
 
 
42
    """
 
43
 
 
44
    title = "File Selection Dialog"
 
45
 
 
46
    def __init__(self, master, title=None):
 
47
        if title is None: title = self.title
 
48
        self.master = master
 
49
        self.directory = None
 
50
 
 
51
        self.top = Toplevel(master)
 
52
        self.top.title(title)
 
53
        self.top.iconname(title)
 
54
 
 
55
        self.botframe = Frame(self.top)
 
56
        self.botframe.pack(side=BOTTOM, fill=X)
 
57
 
 
58
        self.selection = Entry(self.top)
 
59
        self.selection.pack(side=BOTTOM, fill=X)
 
60
        self.selection.bind('<Return>', self.ok_event)
 
61
 
 
62
        self.filter = Entry(self.top)
 
63
        self.filter.pack(side=TOP, fill=X)
 
64
        self.filter.bind('<Return>', self.filter_command)
 
65
 
 
66
        self.midframe = Frame(self.top)
 
67
        self.midframe.pack(expand=YES, fill=BOTH)
 
68
 
 
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'))
 
79
 
 
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)
 
90
 
 
91
        self.ok_button = Button(self.botframe,
 
92
                                 text="OK",
 
93
                                 command=self.ok_command)
 
94
        self.ok_button.pack(side=LEFT)
 
95
        self.filter_button = Button(self.botframe,
 
96
                                    text="Filter",
 
97
                                    command=self.filter_command)
 
98
        self.filter_button.pack(side=LEFT, expand=YES)
 
99
        self.cancel_button = Button(self.botframe,
 
100
                                    text="Cancel",
 
101
                                    command=self.cancel_command)
 
102
        self.cancel_button.pack(side=RIGHT)
 
103
 
 
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)
 
108
 
 
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]
 
112
        else:
 
113
            dir_or_file = os.path.expanduser(dir_or_file)
 
114
            if os.path.isdir(dir_or_file):
 
115
                self.directory = dir_or_file
 
116
            else:
 
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
 
123
        self.top.grab_set()
 
124
        self.how = None
 
125
        self.master.mainloop()          # Exited by self.quit(how)
 
126
        if key:
 
127
            directory, pattern = self.get_filter()
 
128
            if self.how:
 
129
                directory = os.path.dirname(self.how)
 
130
            dialogstates[key] = directory, pattern
 
131
        self.top.destroy()
 
132
        return self.how
 
133
 
 
134
    def quit(self, how=None):
 
135
        self.how = how
 
136
        self.master.quit()              # Exit mainloop()
 
137
 
 
138
    def dirs_double_event(self, event):
 
139
        self.filter_command()
 
140
 
 
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)
 
146
 
 
147
    def files_double_event(self, event):
 
148
        self.ok_command()
 
149
 
 
150
    def files_select_event(self, event):
 
151
        file = self.files.get('active')
 
152
        self.set_selection(file)
 
153
 
 
154
    def ok_event(self, event):
 
155
        self.ok_command()
 
156
 
 
157
    def ok_command(self):
 
158
        self.quit(self.get_selection())
 
159
 
 
160
    def filter_command(self, event=None):
 
161
        dir, pat = self.get_filter()
 
162
        try:
 
163
            names = os.listdir(dir)
 
164
        except os.error:
 
165
            self.master.bell()
 
166
            return
 
167
        self.directory = dir
 
168
        self.set_filter(dir, pat)
 
169
        names.sort()
 
170
        subdirs = [os.pardir]
 
171
        matchingfiles = []
 
172
        for name in names:
 
173
            fullname = os.path.join(dir, name)
 
174
            if os.path.isdir(fullname):
 
175
                subdirs.append(name)
 
176
            elif fnmatch.fnmatch(name, pat):
 
177
                matchingfiles.append(name)
 
178
        self.dirs.delete(0, END)
 
179
        for name in subdirs:
 
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)
 
187
 
 
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)
 
194
 
 
195
    def get_selection(self):
 
196
        file = self.selection.get()
 
197
        file = os.path.expanduser(file)
 
198
        return file
 
199
 
 
200
    def cancel_command(self, event=None):
 
201
        self.quit()
 
202
 
 
203
    def set_filter(self, dir, pat):
 
204
        if not os.path.isabs(dir):
 
205
            try:
 
206
                pwd = os.getcwd()
 
207
            except os.error:
 
208
                pwd = None
 
209
            if pwd:
 
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 "*"))
 
214
 
 
215
    def set_selection(self, file):
 
216
        self.selection.delete(0, END)
 
217
        self.selection.insert(END, os.path.join(self.directory, file))
 
218
 
 
219
 
 
220
class LoadFileDialog(FileDialog):
 
221
 
 
222
    """File selection dialog which checks that the file exists."""
 
223
 
 
224
    title = "Load File Selection Dialog"
 
225
 
 
226
    def ok_command(self):
 
227
        file = self.get_selection()
 
228
        if not os.path.isfile(file):
 
229
            self.master.bell()
 
230
        else:
 
231
            self.quit(file)
 
232
 
 
233
 
 
234
class SaveFileDialog(FileDialog):
 
235
 
 
236
    """File selection dialog which checks that the file may be created."""
 
237
 
 
238
    title = "Save File Selection Dialog"
 
239
 
 
240
    def ok_command(self):
 
241
        file = self.get_selection()
 
242
        if os.path.exists(file):
 
243
            if os.path.isdir(file):
 
244
                self.master.bell()
 
245
                return
 
246
            d = Dialog(self.top,
 
247
                       title="Overwrite Existing File Question",
 
248
                       text="Overwrite existing file %r?" % (file,),
 
249
                       bitmap='questhead',
 
250
                       default=1,
 
251
                       strings=("Yes", "Cancel"))
 
252
            if d.num != 0:
 
253
                return
 
254
        else:
 
255
            head, tail = os.path.split(file)
 
256
            if not os.path.isdir(head):
 
257
                self.master.bell()
 
258
                return
 
259
        self.quit(file)
 
260
 
 
261
 
 
262
def test():
 
263
    """Simple test program."""
 
264
    root = Tk()
 
265
    root.withdraw()
 
266
    fd = LoadFileDialog(root)
 
267
    loadfile = fd.go(key="test")
 
268
    fd = SaveFileDialog(root)
 
269
    savefile = fd.go(key="test")
 
270
    print loadfile, savefile
 
271
 
 
272
 
 
273
if __name__ == '__main__':
 
274
    test()