diff src/parpg/gui/filebrowser.py @ 0:1fd2201f5c36

Initial commit of parpg-core.
author M. George Hansen <technopolitica@gmail.com>
date Sat, 14 May 2011 01:12:35 -0700
parents
children d60f1dab8469
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parpg/gui/filebrowser.py	Sat May 14 01:12:35 2011 -0700
@@ -0,0 +1,159 @@
+#   This program is free software: you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation, either version 3 of the License, or
+#   (at your option) any later version.
+
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+
+#   You should have received a copy of the GNU General Public License
+#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from fife.extensions import pychan
+from fife.extensions.pychan import widgets
+
+import sys
+import os
+import logging
+
+logger = logging.getLogger('filebrowser')
+
+def u2s(string):
+    # TODO: cryptic function name
+    return string.encode(sys.getfilesystemencoding())
+
+class FileBrowser(object):
+    """FileBrowser displays directory and file listings from the vfs.
+       The file_selected parameter is a callback invoked when a file selection
+       has been made; its signature must be file_selected(path,filename). If
+       select_dir is set, file_selected's filename parameter should be optional.
+       The save_file option provides a box for supplying a new filename that
+       doesn't exist yet. The select_dir option allows directories to be
+       selected as well as files."""
+    def __init__(self, engine, settings, file_selected, gui_xml_path,
+                 close_callback=None, save_file=False, select_dir=False, 
+                 extensions=('.dat',)):
+        self.engine = engine
+        self.settings = settings
+        print self.settings.parpg.SavesPath
+        self.file_selected = file_selected
+
+        self._widget = None
+        self.save_file = save_file
+        self.select_dir = select_dir
+        self.close_callback = close_callback
+        self.gui_xml_path = gui_xml_path 
+        
+        self.extensions = extensions
+        self.path = os.path.join(self.settings.user_path,
+                                 self.settings.parpg.SavesPath)
+        self.dir_list = []
+        self.file_list = []
+        
+    def close(self):
+        """Closes the browser"""        
+        self._widget.hide()
+        if self.close_callback:
+            self.close_callback()
+    
+    def showBrowser(self):
+        """Shows the file dialog browser"""
+        if self._widget:
+            self._widget.show()
+            return
+        self._widget = pychan.loadXML(self.gui_xml_path)
+        self._widget.mapEvents({
+            'dirList'       : self._setPath,
+            'selectButton'  : self._selectFile,
+            'closeButton'   : self.close
+        })
+        self._setPath()
+        if self.save_file:
+            self._file_entry = widgets.TextField(name='saveField', text=u'')    
+            self._widget.findChild(name="fileColumn").\
+                addChild(self._file_entry)
+        self._widget.show()
+
+    def _setPath(self):
+        """Path change callback."""
+        selection = self._widget.collectData('dirList')
+        if not (selection < 0):
+            new_dir = u2s(self.dir_list[selection])
+            lst = self.path.split('/')
+            if new_dir == '..' and lst[-1] != '..' and lst[-1] != '.':
+                lst.pop()
+            else:
+                lst.append(new_dir)
+            self.path = '/'.join(lst)
+            
+        def decodeList(list):
+            fs_encoding = sys.getfilesystemencoding()
+            if fs_encoding is None: fs_encoding = "ascii"
+        
+            new_list = []
+            for i in list:
+                try:
+                    new_list.append(unicode(i, fs_encoding))
+                except:
+                    new_list.append(unicode(i, fs_encoding, 'replace'))
+                    logger.debug("WARNING: Could not decode item:\n"
+                                        "{0}".format(i))
+            return new_list
+            
+        
+
+        self.dir_list = []
+        self.file_list = []
+        
+        dir_list = ('..',) + filter(lambda d: not d.startswith('.'), \
+                                    self.engine.getVFS().\
+                                    listDirectories(self.path))
+        file_list = filter(lambda f: f.split('.')[-1] in self.extensions, \
+                           self.engine.getVFS().listFiles(self.path))
+                
+        self.dir_list = decodeList(dir_list)
+        self.file_list = decodeList(file_list)
+        self._widget.distributeInitialData({
+            'dirList'  : self.dir_list,
+            'fileList' : self.file_list
+        })
+
+    def _selectFile(self):
+        """ File selection callback. """
+        self._widget.hide()
+        selection = self._widget.collectData('fileList')
+
+        if self.save_file:
+            data = self._widget.collectData('saveField')
+            if data:
+                if (data.endswith(".dat")):
+                    self.file_selected(self.path, \
+                                u2s(self._widget.collectData('saveField')))
+                else:
+                    self.file_selected(self.path, 
+                                       u2s(self._widget.collectData('saveField')) + '.dat')
+                return
+            
+
+        if selection >= 0 and selection < len(self.file_list):
+            self.file_selected(self.path, u2s(self.file_list[selection]))
+            return
+        
+        if self.select_dir:
+            self.file_selected(self.path)
+            return
+
+        logger.error('no selection')
+
+    def _warningMessage(self):
+        """Shows the warning message dialog when a file with a
+           faulty extension was selected."""
+        window = widgets.Window(title="Warning")
+        text = "Please save the file as a .dat"
+        label = widgets.Label(text=text)
+        ok_button = widgets.Button(name="ok_button", text="Ok")
+        window.addChildren([label, ok_button])
+        window.mapEvents({'ok_button':window.hide})
+        window.show()