@@ -4119,7 +4119,8 @@ def OnChoice(self,event):
41194119################################################################################
41204120def GetImportFile (G2frame , message , defaultDir = "" , defaultFile = "" ,
41214121 style = wx .FD_OPEN , parent = None ,* args , ** kwargs ):
4122- '''Uses a customized dialog that gets files from the appropriate import directory.
4122+ '''Uses a standard or GSASII-customized dialog that gets files
4123+ from the appropriate import directory.
41234124 Arguments are used the same as in :func:`wx.FileDialog`. Selection of
41244125 multiple files is allowed if argument style includes wx.FD_MULTIPLE.
41254126
@@ -4137,30 +4138,245 @@ def GetImportFile(G2frame, message, defaultDir="", defaultFile="",
41374138 #if GSASIIpath.GetConfigValue('debug'):
41384139 # print('debug: GetImportFile from '+defaultDir)
41394140 # print('debug: GetImportFile pth '+pth)
4140- dlg = wx .FileDialog (parent , message , defaultDir , defaultFile , * args ,style = style , ** kwargs )
4141- # dlg.CenterOnParent()
4142- if not defaultDir and pth : dlg .SetDirectory (pth )
4143- try :
4144- if dlg .ShowModal () == wx .ID_OK :
4145- if style & wx .FD_MULTIPLE :
4146- filelist = dlg .GetPaths ()
4147- if len (filelist ) == 0 : return []
4148- else :
4149- filelist = [dlg .GetPath (),]
4150- # not sure if we want to do this (why use wx.CHANGE_DIR?)
4151- if style & wx .FD_CHANGE_DIR : # to get Mac/Linux to change directory like windows!
4152- os .chdir (dlg .GetDirectory ())
4153- else : # cancel was pressed
4154- return []
4155- finally :
4156- dlg .Destroy ()
4141+ browseOpt = GSASIIpath .GetConfigValue ('G2FileBrowser' )
4142+ # unspecified value defaults to True on Linux, False for Windows/Linux
4143+ if sys .platform .startswith ("linux" ) and browseOpt is None :
4144+ browseOpt = True
4145+ if browseOpt :
4146+ filelist = G2FileBrowser (parent , message , defaultDir , style = style ,
4147+ ** kwargs )
4148+ if len (filelist ) == 0 : return []
4149+ if style & wx .FD_CHANGE_DIR : # to get Mac/Linux to change directory like windows!
4150+ os .chdir (os .path .dirname (filelist [0 ]))
4151+ else :
4152+ dlg = wx .FileDialog (parent , message , defaultDir , defaultFile , * args , style = style , ** kwargs )
4153+ # dlg.CenterOnParent()
4154+ if not defaultDir and pth : dlg .SetDirectory (pth )
4155+ try :
4156+ if dlg .ShowModal () == wx .ID_OK :
4157+ if style & wx .FD_MULTIPLE :
4158+ filelist = dlg .GetPaths ()
4159+ if len (filelist ) == 0 : return []
4160+ else :
4161+ filelist = [dlg .GetPath (),]
4162+ # not sure if we want to do this (why use wx.CHANGE_DIR?)
4163+ if style & wx .FD_CHANGE_DIR : # to get Mac/Linux to change directory like windows!
4164+ os .chdir (dlg .GetDirectory ())
4165+ else : # cancel was pressed
4166+ return []
4167+ finally :
4168+ dlg .Destroy ()
41574169 # save the path of the first file and reset the TutorialImportDir variable
41584170 pth = os .path .split (os .path .abspath (filelist [0 ]))[0 ]
41594171 if GSASIIpath .GetConfigValue ('Save_paths' ): SaveImportDirectory (pth )
41604172 G2frame .LastImportDir = pth
41614173 G2frame .TutorialImportDir = None
41624174 return filelist
41634175
4176+ def G2FileBrowser (parent , message , defaultDir , * args ,
4177+ style = wx .FD_OPEN ,wildcard = "any file (*.*)|*.*" ,
4178+ ** kwargs ):
4179+ '''Create a file browser for selecting one or more files from
4180+ a directory. The user may select the directory where the files
4181+ and must select an extension from a specified list. Optionally,
4182+ a filter may be supplied to ignore files not matching a glob
4183+ pattern. When a large number of files is found, the file list
4184+ is broken into ranges.
4185+
4186+ Arguments used are the same as in :func:`wx.FileDialog`. Selection of
4187+ multiple files is allowed if argument style includes wx.FD_MULTIPLE.
4188+ Note that other positional or keyword parameters, other than those below
4189+ are allowed, but are ignored.
4190+
4191+ :param parent: parent window to dialog to be created
4192+ :param message: message to place at top of dialog
4193+ :param defaultDir: starting directory
4194+ :param style: selection style. Bit settings other than wx.FD_MULTIPLE
4195+ are ignored. When wx.FD_MULTIPLE is specified, multiple files can
4196+ be selected.
4197+ :param wildcard: defines the extensions allowed for selecting files.
4198+ of form "type A (*.A;*.B;*.c)|*.A;*.B;*.c|any file (*.*)|*.*". See
4199+ :func:`wx.FileDialog` for more information on this.
4200+
4201+ :returns: a list of selected files. Will contain only one file unless
4202+ style=wx.FD_MULTIPLE has been used.
4203+ '''
4204+ maxFiles = 300 # when more than this number of files is found in a
4205+ # directory, after applying the extension and filter
4206+ # the list is broken into ranges
4207+ import fnmatch # import these now as not commonly used in GSAS-II
4208+ import wx .lib .filebrowsebutton as filebrowse
4209+ def OnDirSelect (event ,** kwargs ):
4210+ '''Called when a directory or an extension is selected.
4211+ Loads dlg.filelist with the files in that directory and
4212+ with the selected extension.
4213+ '''
4214+ try : # exit if listbox not yet created
4215+ listbox
4216+ except :
4217+ return
4218+ extSel = typeSel .GetValue ()
4219+ typeTxt .SetLabel (f"({ extDict .get (extSel ,'?' )} )" )
4220+ dlg .filelist = []
4221+ dirVal = fb .GetValue ()
4222+ if os .path .exists (dirVal ):
4223+ dlg .filelist = glob .glob (os .path .join (dirVal ,extSel ))
4224+ if filterTxt [0 ] and filterTxt [0 ].strip () != '*' :
4225+ dlg .filelist = [i for i in dlg .filelist if
4226+ fnmatch .fnmatch (os .path .split (i )[1 ], filterTxt [0 ])]
4227+ dlg .filelist .sort ()
4228+ if len (dlg .filelist ) == 0 :
4229+ dlg .choices = ['No matching files present' ]
4230+ listbox .Enable (False )
4231+ else :
4232+ last = int (1.1 * maxFiles )
4233+ dlg .choices = dlg .filelist [:last ]
4234+ listbox .Enable (True )
4235+ onSelection (None )
4236+ SetupNumSelect ()
4237+ listbox .SetItems ([os .path .split (f )[1 ] for f in dlg .choices ])
4238+ def onSelection (event ):
4239+ 'Called when a file is selected. Enables the Read button'
4240+ selections = []
4241+ if event is not None :
4242+ selections = listbox .GetSelections ()
4243+ if len (selections ) > 0 :
4244+ OKbtn .SetDefault ()
4245+ OKbtn .Enable (True )
4246+ else :
4247+ CNbtn .SetDefault ()
4248+ OKbtn .Enable (False )
4249+ def SetupNumSelect ():
4250+ 'defines the contents of the file range selector'
4251+ numfiles = len (dlg .filelist )
4252+ if numfiles < maxFiles :
4253+ choices = ['all files' ]
4254+ numSel .Enable (False )
4255+ else :
4256+ ranges = []
4257+ for i in range (numfiles // maxFiles + 1 ):
4258+ first = i * maxFiles + 1
4259+ if first > numfiles : break
4260+ last = min (numfiles ,int ((i + 1.1 )* maxFiles ))
4261+ ranges .append ((first ,last ))
4262+ if last >= numfiles : break
4263+ choices = []
4264+ for first ,last in ranges :
4265+ choices .append (f"files { first } -{ last } " )
4266+ numSel .Enable (True )
4267+ numSel .SetItems (choices )
4268+ numSel .SetSelection (0 )
4269+ def OnNumSelect (event ):
4270+ 'responds to a selection of a file range'
4271+ i = numSel .GetSelection ()
4272+ first = i * maxFiles + 1
4273+ last = int ((i + 1.1 )* maxFiles )
4274+ dlg .choices = dlg .filelist [first - 1 :last ]
4275+ listbox .SetItems ([os .path .split (f )[1 ] for f in dlg .choices ])
4276+
4277+ # parse the wildcard list
4278+ extDict = {}
4279+ for i ,item in enumerate (wildcard .split ('|' )):
4280+ if i % 2 == 0 :
4281+ nam = item .split ('(' )[0 ].strip ()
4282+ else :
4283+ for ext in item .split (';' ):
4284+ extDict [ext ] = nam
4285+ # single or multiple file selection?
4286+ if style & wx .FD_MULTIPLE :
4287+ multiple = True
4288+ lbl = 'Select one or more files'
4289+ else :
4290+ multiple = False
4291+ lbl = 'Select a file'
4292+ # make the GUI
4293+ dlg = wx .Dialog (parent ,wx .ID_ANY ,lbl ,
4294+ style = wx .DEFAULT_DIALOG_STYLE | wx .RESIZE_BORDER )
4295+ dlg .choices = []
4296+ dlg .filelist = []
4297+ mainSizer = wx .BoxSizer (wx .VERTICAL )
4298+ # title at top
4299+ mainSizer .Add ((0 ,5 ))
4300+ subSizer = wx .BoxSizer (wx .HORIZONTAL )
4301+ subSizer .Add ((- 1 ,- 1 ),1 ,wx .EXPAND )
4302+ subSizer .Add (wx .StaticText (dlg ,wx .ID_ANY ,message ))
4303+ subSizer .Add ((- 1 ,- 1 ),1 ,wx .EXPAND )
4304+ mainSizer .Add (subSizer ,0 ,wx .EXPAND ,0 )
4305+ mainSizer .Add ((0 ,10 ))
4306+ # directory selector
4307+ fb = filebrowse .DirBrowseButton (dlg , wx .ID_ANY ,
4308+ labelText = 'Directory:' ,
4309+ changeCallback = OnDirSelect )
4310+ mainSizer .Add (fb ,0 ,wx .EXPAND | wx .BOTTOM ,5 )
4311+ # extension selector
4312+ subSizer = wx .BoxSizer (wx .HORIZONTAL )
4313+ subSizer .Add (wx .StaticText (dlg ,wx .ID_ANY ,' Extension: ' ))
4314+ choices = list (extDict .keys ())
4315+ typeSel = wx .ComboBox (dlg ,choices = choices ,value = choices [0 ],
4316+ style = wx .CB_READONLY | wx .CB_DROPDOWN )
4317+ typeSel .Bind (wx .EVT_COMBOBOX , OnDirSelect )
4318+ if len (choices ) == 1 :
4319+ typeSel .Enable (False )
4320+ subSizer .Add (typeSel )
4321+ subSizer .Add ((5 ,- 1 ))
4322+ typeTxt = wx .StaticText (dlg ,wx .ID_ANY ,'' )
4323+ subSizer .Add (typeTxt )
4324+ # filter
4325+ mainSizer .Add (subSizer )
4326+ subSizer = wx .BoxSizer (wx .HORIZONTAL )
4327+ subSizer .Add (wx .StaticText (dlg ,wx .ID_ANY ,' Filter: ' ))
4328+ filterTxt = ['*' ]
4329+ txt = ValidatedTxtCtrl (dlg ,filterTxt ,0 ,notBlank = False ,
4330+ OKcontrol = OnDirSelect ,
4331+ OnLeave = OnDirSelect ,OnLeaveArgs = [])
4332+ txt .SetMinSize ((100 ,- 1 ))
4333+ txt .Bind (wx .EVT_LEAVE_WINDOW , OnDirSelect )
4334+ txt .Bind (wx .EVT_KILL_FOCUS , OnDirSelect )
4335+ txt .Bind (wx .EVT_TEXT_ENTER , OnDirSelect )
4336+ subSizer .Add (txt ,1 ,wx .EXPAND | wx .RIGHT ,2 )
4337+ mainSizer .Add (subSizer ,0 ,wx .EXPAND ,0 )
4338+ # listbox
4339+ if multiple :
4340+ listbox = wx .ListBox (dlg , wx .ID_ANY , style = wx .LB_MULTIPLE | wx .LB_ALWAYS_SB )
4341+ else :
4342+ listbox = wx .ListBox (dlg , wx .ID_ANY , style = wx .LB_SINGLE | wx .LB_ALWAYS_SB )
4343+ listbox .Bind (wx .EVT_LISTBOX ,onSelection )
4344+ listbox .SetMinSize ((350 ,200 ))
4345+ mainSizer .Add (listbox ,1 ,wx .EXPAND ,1 )
4346+ # file subset selection (disabled when not needed)
4347+ subSizer = wx .BoxSizer (wx .HORIZONTAL )
4348+ subSizer .Add (wx .StaticText (dlg ,wx .ID_ANY ,' range of files: ' ))
4349+ choices = ['all files' ]
4350+ numSel = wx .ComboBox (dlg ,choices = choices ,value = choices [0 ],
4351+ style = wx .CB_READONLY | wx .CB_DROPDOWN )
4352+ numSel .SetMinSize ((150 ,- 1 ))
4353+ numSel .Bind (wx .EVT_COMBOBOX , OnNumSelect )
4354+ if len (choices ) == 1 :
4355+ numSel .Enable (False )
4356+ subSizer .Add (numSel )
4357+ mainSizer .Add (subSizer ,0 ,wx .TOP ,5 )
4358+ # cancel/read buttons
4359+ btnsizer = wx .StdDialogButtonSizer ()
4360+ CNbtn = wx .Button (dlg , wx .ID_CANCEL )
4361+ btnsizer .AddButton (CNbtn )
4362+ OKbtn = wx .Button (dlg , wx .ID_OK ,'Read' )
4363+ OKbtn .SetDefault ()
4364+ btnsizer .AddButton (OKbtn )
4365+ btnsizer .Realize ()
4366+ mainSizer .Add (btnsizer ,0 ,wx .ALIGN_RIGHT ,50 )
4367+ # finish up
4368+ dlg .SetSizer (mainSizer )
4369+ mainSizer .Layout ()
4370+ mainSizer .Fit (dlg )
4371+ dlg .CenterOnParent ()
4372+ fb .SetValue (os .path .abspath (os .path .expanduser (defaultDir )))
4373+ # wait for button press
4374+ selections = []
4375+ if dlg .ShowModal () == wx .ID_OK :
4376+ selections = [dlg .choices [i ] for i in listbox .GetSelections ()]
4377+ dlg .Destroy ()
4378+ return selections
4379+
41644380def GetImportPath (G2frame ):
41654381 '''Determines the default location to use for importing files. Tries sequentially
41664382 G2frame.TutorialImportDir, config var Import_directory, G2frame.LastImportDir
@@ -4925,6 +5141,8 @@ def SetWildAfter(d,name,wname,mode):
49255141 subSizer .Add ((- 1 ,- 1 ),1 ,wx .EXPAND )
49265142 try :
49275143 value = G2fil .FormatSigFigs (self .parmWin .parmDict [name ])
5144+ except ValueError :
5145+ value = str (self .parmWin .parmDict [name ])
49285146 except TypeError :
49295147 value = str (self .parmWin .parmDict [name ])+ ' -?' # unexpected
49305148 subSizer .Add (wx .StaticText (dlg ,wx .ID_ANY ,
@@ -5076,6 +5294,8 @@ def OnGetItemText(self, item, col):
50765294 elif col == 3 :
50775295 try :
50785296 value = G2fil .FormatSigFigs (self .parmWin .parmDict [name ])
5297+ except ValueError :
5298+ value = str (self .parmWin .parmDict [name ]) #array!
50795299 except TypeError :
50805300 value = str (self .parmWin .parmDict [name ])+ ' -?' # unexpected
50815301 return value
0 commit comments