#!/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)