1 | #!/usr/bin/python |
---|
2 | |
---|
3 | # This program is free software: you can redistribute it and/or modify |
---|
4 | # it under the terms of the GNU General Public License as published by |
---|
5 | # the Free Software Foundation, either version 3 of the License, or |
---|
6 | # (at your option) any later version. |
---|
7 | |
---|
8 | # This program is distributed in the hope that it will be useful, |
---|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
11 | # GNU General Public License for more details. |
---|
12 | |
---|
13 | # You should have received a copy of the GNU General Public License |
---|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
---|
15 | |
---|
16 | import pychan |
---|
17 | import pychan.widgets as widgets |
---|
18 | import sys |
---|
19 | |
---|
20 | def u2s(string): |
---|
21 | return string.encode(sys.getfilesystemencoding()) |
---|
22 | |
---|
23 | class FileBrowser(object): |
---|
24 | """ |
---|
25 | FileBrowser displays directory and file listings from the vfs. |
---|
26 | The file_selected parameter is a callback invoked when a file selection |
---|
27 | has been made; its signature must be file_selected(path,filename). If |
---|
28 | select_dir is set, file_selected's filename parameter should be optional. |
---|
29 | The save_file option provides a box for supplying a new filename that |
---|
30 | doesn't exist yet. The select_dir option allows directories to be |
---|
31 | selected as well as files. |
---|
32 | """ |
---|
33 | def __init__(self, engine, file_selected, save_file=False, \ |
---|
34 | select_dir=False, extensions=('.dat',), \ |
---|
35 | gui_xml_path="gui/filebrowser.xml"): |
---|
36 | self.engine = engine |
---|
37 | self.file_selected = file_selected |
---|
38 | |
---|
39 | self._widget = None |
---|
40 | self.save_file = save_file |
---|
41 | self.select_dir = select_dir |
---|
42 | |
---|
43 | self.gui_xml_path = gui_xml_path |
---|
44 | |
---|
45 | self.extensions = extensions |
---|
46 | self.path = './saves/' |
---|
47 | self.dir_list = [] |
---|
48 | self.file_list = [] |
---|
49 | |
---|
50 | def showBrowser(self): |
---|
51 | """ Shows the file dialog browser """ |
---|
52 | if self._widget: |
---|
53 | self._widget.show() |
---|
54 | return |
---|
55 | self._widget = pychan.loadXML(self.gui_xml_path) |
---|
56 | self._widget.mapEvents({ |
---|
57 | 'dirList' : self._setDirectory, |
---|
58 | 'selectButton' : self._selectFile, |
---|
59 | 'closeButton' : self._widget.hide |
---|
60 | }) |
---|
61 | self._setDirectory() |
---|
62 | if self.save_file: |
---|
63 | self._file_entry = widgets.TextField(name='saveField', text=u'') |
---|
64 | self._widget.findChild(name="fileColumn").\ |
---|
65 | addChild(self._file_entry) |
---|
66 | self._widget.show() |
---|
67 | |
---|
68 | def _setDirectory(self): |
---|
69 | """ Directory change callback. """ |
---|
70 | selection = self._widget.collectData('dirList') |
---|
71 | if not (selection < 0): |
---|
72 | new_dir = u2s(self.dir_list[selection]) |
---|
73 | lst = self.path.split('/') |
---|
74 | if new_dir == '..' and lst[-1] != '..' and lst[-1] != '.': |
---|
75 | lst.pop() |
---|
76 | else: |
---|
77 | lst.append(new_dir) |
---|
78 | self.path = '/'.join(lst) |
---|
79 | |
---|
80 | def decodeList(list): |
---|
81 | fs_encoding = sys.getfilesystemencoding() |
---|
82 | if fs_encoding is None: fs_encoding = "ascii" |
---|
83 | |
---|
84 | new_list = [] |
---|
85 | for i in list: |
---|
86 | try: |
---|
87 | new_list.append(unicode(i, fs_encoding)) |
---|
88 | except: |
---|
89 | new_list.append(unicode(i, fs_encoding, 'replace')) |
---|
90 | print "WARNING: Could not decode item:", i |
---|
91 | return new_list |
---|
92 | |
---|
93 | |
---|
94 | |
---|
95 | self.dir_list = [] |
---|
96 | self.file_list = [] |
---|
97 | |
---|
98 | dir_list = ('..',) + filter(lambda d: not d.startswith('.'), \ |
---|
99 | self.engine.getVFS().\ |
---|
100 | listDirectories(self.path)) |
---|
101 | file_list = filter(lambda f: f.split('.')[-1] in self.extensions, \ |
---|
102 | self.engine.getVFS().listFiles(self.path)) |
---|
103 | |
---|
104 | self.dir_list = decodeList(dir_list) |
---|
105 | self.file_list = decodeList(file_list) |
---|
106 | self._widget.distributeInitialData({ |
---|
107 | 'dirList' : self.dir_list, |
---|
108 | 'fileList' : self.file_list |
---|
109 | }) |
---|
110 | |
---|
111 | def _selectFile(self): |
---|
112 | """ File selection callback. """ |
---|
113 | self._widget.hide() |
---|
114 | selection = self._widget.collectData('fileList') |
---|
115 | |
---|
116 | if self.save_file: |
---|
117 | data = self._widget.collectData('saveField') |
---|
118 | if data: |
---|
119 | if (data.split('.')[1] == 'dat'): |
---|
120 | self.file_selected(self.path, \ |
---|
121 | u2s(self._widget.collectData('saveField'))) |
---|
122 | else: |
---|
123 | self._warningMessage() |
---|
124 | return |
---|
125 | |
---|
126 | |
---|
127 | if selection >= 0 and selection < len(self.file_list): |
---|
128 | self.file_selected(self.path, u2s(self.file_list[selection])) |
---|
129 | return |
---|
130 | |
---|
131 | if self.select_dir: |
---|
132 | self.file_selected(self.path) |
---|
133 | return |
---|
134 | |
---|
135 | print 'FileBrowser: error, no selection.' |
---|
136 | |
---|
137 | def _warningMessage(self): |
---|
138 | """ Shows the warning message dialog when a file with a |
---|
139 | faulty extension was selected. """ |
---|
140 | window = widgets.Window(title="Warning") |
---|
141 | text = "Please save the file as a .dat" |
---|
142 | label = widgets.Label(text=text) |
---|
143 | ok_button = widgets.Button(name="ok_button", text="Ok") |
---|
144 | window.addChildren([label, ok_button]) |
---|
145 | window.mapEvents({'ok_button':window.hide}) |
---|
146 | window.show() |
---|