python-2.5.2/win32/Lib/lib-tk/FileDialog.py
changeset 0 ae805ac0140d
equal deleted inserted replaced
-1:000000000000 0:ae805ac0140d
       
     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()