Source code for tesfdmtools.utils.widgets.filechooser

#!/usr/bin/env python3
'''
.. module:: filechooser
   :synopsis: Select file or directory using a widget
.. moduleauthor:: Cor de Vries <c.p.de.vries@sron.nl>

Module to interactively select a file or directory.
Uses the GtkFileChooser widget.
'''
#
# file chooser dialog with glade
#

import sys
import os

# apppath=os.path.dirname(os.path.realpath(sys.argv[0]))
apppath=os.path.dirname(os.path.realpath(__file__))

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

from tesfdmtools.utils.widgets.msg import msg

class _fcwidget:
   '''                                                                          
   Display file selection widget and select file or directory. Called from **getfile** and **getdir**

   Args:
      * gfile: Glade XML file for window definition

   Kwargs:                      
      * `fpatt` = File pattern for selection of files                       
      * `path` = Initial path for files
      * `parent` = Parent window, if it exists
      * `newfile` = Allow specification of a new file when **True**
      * `directory` = Ask for directory name only instead of a filename                                     
      * `multiple` =  Allow multiple files to be selected when **True**
               
   '''                                                                          
   def __init__(self,gfile,fpatt=None,path=None,parent=None,newfile=False,\
                           directory=False,multiple=False):
        self.widgets=Gtk.Builder()
        if not os.path.exists(gfile):
            msg("Error,\nfile %s not found" % gfile)
            sys.exit(1) 
        self.widgets.add_from_file(gfile)
        self.fchooser=self.widgets.get_object('selectfile')
        self.fwidget=self.widgets.get_object('filter')
        self.toolbar=self.widgets.get_object('toolbar')
        dic={"on_selectfile_destroy":self._cancel,
             "on_cancel_clicked":self._cancel,
             "on_ok_clicked":self._ok,
             "on_filter_changed":self._ffilter
          }
        if parent is not None:
           self.fchooser.set_transient_for(parent)
        self.widgets.connect_signals(dic)
        self.fchooser.connect("file_activated",self._ok)
        self.filter=Gtk.FileFilter()
        if path is not None:
           self.fchooser.set_current_folder(path)
        if directory:
           self.fchooser.set_action(Gtk.FileChooserAction.SELECT_FOLDER)
        else:
           if newfile:
              self.fchooser.set_action(Gtk.FileChooserAction.SAVE)
           else:
              self.fchooser.set_action(Gtk.FileChooserAction.OPEN)
              if multiple:
                 print("select multiple files")
                 self.fchooser.set_select_multiple(True)
           if fpatt is None:
              set.fwidget.set_text('*')
              self.filter.add_pattern('*')
           else:
              self.filter.add_pattern(fpatt)
              self.fwidget.set_text(fpatt)
           self.fchooser.set_filter(self.filter)
        self.selected_file=[]
        self.fchooser.show_all()

   def _ffilter(self,event):
        self.filter=Gtk.FileFilter()
        ff=self.fwidget.get_text()
        self.filter.add_pattern(ff.strip(' '))
        self.fchooser.set_filter(self.filter)

   def _cancel(self,event):
        self.selected_file=[]

   def _ok(self,event):
        self.selected_file=self.fchooser.get_filenames()
        self.fchooser.response(0)

   def getfile(self):
        '''
        Returns:
           * selected file or directory
        '''
        return self.selected_file

[docs]def getfile(fpatt='*',pattern=None,parent=None,newfile=False,path=None,multiple=False): ''' Interactively select a file. Kwargs: * `fpatt` = File pattern to seach for (e.g. \*.typ,\*.\*,\*aa\*.txt) * `pattern` = File pattern to seach for (e.g. \*.typ,\*.\*,\*aa\*.txt) (identical to `fpatt` ) * `path` = Path where to search for files * `parent` = Parent window, if it exists * `newfile` = Allow specification of a new file when **True** * `multiple` = Allow multiple files to be selected when **True** Returns: * selected file ''' if pattern is not None: fpatt=pattern ftype=None if fpatt.find('.') >= 0: ftype=fpatt.split('.')[1] ww=_fcwidget(apppath+'/fileselection.glade',fpatt=fpatt,parent=parent,\ newfile=newfile,path=path,multiple=multiple) ww.fchooser.run() selected_file=ww.getfile() ww.fchooser.destroy() while Gtk.events_pending(): Gtk.main_iteration() if len(selected_file) == 0: sfile='' else: if multiple: sfile=selected_file else: sfile=selected_file[0] if newfile: if selected_file[0].find('.') < 0 and ftype is not None: sfile=selected_file[0]+'.'+ftype return sfile
[docs]def getdir(path=None,parent=None): ''' Interactively select a directory Kwargs: * `path` = Path where to search for directories * `parent` = Parent window, if it exists Returns: * selected directory ''' ww=_fcwidget(apppath+'/fileselection.glade',parent=parent,directory=True,path=path) ww.fchooser.run() selected_dir=ww.getfile() ww.fchooser.destroy() while Gtk.events_pending(): Gtk.main_iteration() if len(selected_dir) == 0: sdir='' else: sdir=selected_dir[0] return sdir
# #==================================================================================== # # for testing the code # if __name__ == "__main__": path=os.environ['PWD'] if len(sys.argv) > 1: if sys.argv[1] == '-new': if len(sys.argv) > 2: aa=getfile(newfile=True,fpatt=('*.%s' % sys.argv[2]),path=path) else: aa=getfile(newfile=True,path=path) print('new file: ',aa) elif sys.argv[1] == '-dir': aa=getdir(path=path) print('selected directory: ',aa) elif sys.argv[1] == '-multiple': if len(sys.argv) > 2: aa=getfile(fpatt=('*.%s' % sys.argv[2]),path=path,multiple=True) else: aa=getfile(path=path,multiple=True) print('multiple files: ',aa) else: if sys.argv[1][0] == '-': print('Use: %s [-new|-dir] [typ]' % sys.argv[0]) else: aa=getfile(fpatt=('*.%s' % sys.argv[1]),path=path) print('selected file: ',aa) else: aa=getfile(path=path) print('selected file: ',aa)