Changeset 1971 for trunk/GSASIIctrls.py


Ignore:
Timestamp:
Sep 7, 2015 1:25:13 PM (7 years ago)
Author:
toby
Message:

Add preferences option to edit configuration options

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/GSASIIctrls.py

    r1946 r1971  
    1717
    1818'''
     19import os
     20import sys
    1921import wx
    2022import wx.grid as wg
     
    2527import copy
    2628# import cPickle
    27 import sys
    28 import os
    2929# import numpy as np
    3030# import numpy.ma as ma
     
    347347                self._IndicateValidity()
    348348
    349         elif isinstance(val,str) or isinstance(val,unicode):
     349        elif isinstance(val,str) or isinstance(val,unicode) or typeHint is str:
    350350            if self.CIFinput:
    351351                wx.TextCtrl.__init__(
    352                     self,parent,wx.ID_ANY,val,
     352                    self,parent,wx.ID_ANY,
    353353                    validator=ASCIIValidator(result=loc,key=key),
    354354                    **kw)
    355355            else:
    356                 wx.TextCtrl.__init__(self,parent,wx.ID_ANY,val,**kw)
     356                wx.TextCtrl.__init__(self,parent,wx.ID_ANY,**kw)
     357            if val is not None:
     358                self.SetValue(val)
    357359            if notBlank:
    358360                self.Bind(wx.EVT_CHAR,self._onStringKey)
     
    518520            self._setValue(self.result[self.key])
    519521        elif self.result is not None: # show formatted result, as Bob wants
    520             self._setValue(self.result[self.key])
     522            if not self.invalid: # don't update an invalid expression
     523                self._setValue(self.result[self.key])
    521524        if self.OnLeave: self.OnLeave(invalid=self.invalid,
    522525                                      value=self.result[self.key],
     
    31263129       
    31273130################################################################################
     3131class SelectConfigSetting(wx.Dialog):
     3132    '''Dialog to select configuration variables and set associated values.
     3133    '''
     3134    def __init__(self,parent=None):
     3135        import config_example
     3136        style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER
     3137        wx.Dialog.__init__(self, parent, wx.ID_ANY, 'Set Config Variable', style=style)
     3138        self.sizer = wx.BoxSizer(wx.VERTICAL)
     3139        self.vars = self.GetVarDocs(config_example.__file__)
     3140       
     3141        label = wx.StaticText(
     3142            self,  wx.ID_ANY,
     3143            'Select a GSAS-II configuration variable to change'
     3144            )
     3145        self.sizer.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
     3146        self.choice = {}
     3147        btn = G2ChoiceButton(self, sorted(self.vars.keys(),key=lambda s: s.lower()),
     3148                                 strLoc=self.choice,strKey=0,
     3149                                 onChoice=self.OnSelection)
     3150        btn.SetLabel("")
     3151        self.sizer.Add(btn)
     3152
     3153        self.varsizer = wx.BoxSizer(wx.VERTICAL)
     3154        self.sizer.Add(self.varsizer,1,wx.ALL|wx.EXPAND,1)
     3155       
     3156        self.doclbl = wx.StaticBox(self, wx.ID_ANY, "")
     3157        self.doclblsizr = wx.StaticBoxSizer(self.doclbl)
     3158        self.docinfo = wx.StaticText(self,  wx.ID_ANY, "")
     3159        self.doclblsizr.Add(self.docinfo, 0, wx.ALIGN_LEFT|wx.ALL, 5)
     3160        self.sizer.Add(self.doclblsizr, 0, wx.ALIGN_LEFT|wx.EXPAND|wx.ALL, 5)
     3161        btnsizer = wx.BoxSizer(wx.HORIZONTAL)
     3162        self.saveBtn = wx.Button(self,-1,"Save current settings")
     3163        btnsizer.Add(self.saveBtn, 0, wx.ALL, 2)
     3164        self.saveBtn.Bind(wx.EVT_BUTTON, self.OnSave)
     3165        self.saveBtn.Enable(False)
     3166        self.applyBtn = wx.Button(self,-1,"Use current (no save)")
     3167        btnsizer.Add(self.applyBtn, 0, wx.ALL, 2)
     3168        self.applyBtn.Bind(wx.EVT_BUTTON, self.OnApplyChanges)
     3169        self.applyBtn.Enable(False)
     3170       
     3171        btn = wx.Button(self,wx.ID_CANCEL)
     3172        btnsizer.Add(btn, 0, wx.ALL, 2)
     3173        self.sizer.Add(btnsizer, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
     3174               
     3175        self.SetSizer(self.sizer)
     3176        self.sizer.Fit(self)
     3177        self.CenterOnParent()
     3178
     3179    def GetVarDocs(self,fname):
     3180        '''Read the module referenced in fname (often <module>.__file__) and return a
     3181        dict with names of global variables as keys.
     3182        For each global variable, the value contains four items:
     3183          item 0: the default value
     3184          item 1: the current value
     3185          item 2: the initial value (starts same as item 1)
     3186          item 3: the "docstring" that follows variable definition
     3187        '''
     3188        import config_example
     3189        import ast
     3190        fname = os.path.splitext(fname)[0]+'.py' # convert .pyc to .py
     3191        with open(fname, 'r') as f:
     3192            fstr = f.read()
     3193        fstr = fstr.replace('\r\n', '\n').replace('\r', '\n')
     3194        if not fstr.endswith('\n'):
     3195            fstr += '\n'
     3196        tree = ast.parse(fstr)
     3197        d = {}
     3198        key = None
     3199        for node in ast.walk(tree):
     3200            if isinstance(node,ast.Assign):
     3201                key = node.targets[0].id
     3202                d[key] = [config_example.__dict__.get(key),
     3203                          GSASIIpath.configDict.get(key),
     3204                          GSASIIpath.configDict.get(key),'']
     3205            elif isinstance(node,ast.Expr) and key:
     3206                d[key][3] = node.value.s.strip()
     3207            else:
     3208                key = None
     3209        return d
     3210   
     3211    def OnChange(self,event=None):
     3212        ''' Check if anything been changed. Turn the save button on/off.
     3213        '''
     3214        for var in self.vars:
     3215            if self.vars[var][0] is None and self.vars[var][1] is not None:
     3216                # make blank strings into None, if that is the default
     3217                if self.vars[var][1].strip() == '': self.vars[var][1] = None
     3218            if self.vars[var][1] != self.vars[var][2]:
     3219                #print 'changed',var,self.vars[var][:3]
     3220                self.saveBtn.Enable(True)
     3221                self.applyBtn.Enable(True)
     3222                break
     3223        else:
     3224            self.saveBtn.Enable(False)
     3225            self.applyBtn.Enable(False)
     3226        try:
     3227            self.resetBtn.Enable(True)
     3228        except:
     3229            pass
     3230       
     3231    def OnApplyChanges(self,event=None):
     3232        'Set config variables to match the current settings'
     3233        GSASIIpath.SetConfigValue(self.vars)
     3234        self.EndModal(wx.ID_OK)
     3235       
     3236    def OnSave(self,event):
     3237        '''Write the config variables to config.py and then set them
     3238        as the current settings
     3239        '''
     3240        # try to write to where an old config file is located
     3241        try:
     3242            import config
     3243            savefile = config.__file__
     3244        except ImportError: # no config.py file yet
     3245            savefile = os.path.join(GSASIIpath.path2GSAS2,'config.py')
     3246        # try to open file for write
     3247        try:
     3248            savefile = os.path.splitext(savefile)[0]+'.py' # convert .pyc to .py
     3249            fp = open(savefile,'w')
     3250        except IOError:  # can't write there, write in local mods directory
     3251            # create a local mods directory, if needed
     3252            if not os.path.exists(os.path.expanduser('~/.G2local/')):
     3253                print('Creating directory '+os.path.expanduser('~/.G2local/'))
     3254                os.mkdir(os.path.expanduser('~/.G2local/'))
     3255                sys.path.insert(0,os.path.expanduser('~/.G2local/'))
     3256            savefile = os.path.join(os.path.expanduser('~/.G2local/'),'config.py')
     3257            try:
     3258                fp = open(savefile,'w')
     3259            except IOError:
     3260                G2MessageBox(self,
     3261                                 'Error trying to write configuration to '+savefile,
     3262                                 'Unable to save')
     3263                return
     3264        import datetime
     3265        fp.write("'''\n")
     3266        fp.write("*config.py: Configuration options*\n----------------------------------\n")
     3267        fp.write("This file created in SelectConfigSetting on {:%d %b %Y %H:%M}\n".
     3268                 format(datetime.datetime.now()))
     3269        fp.write("'''\n\n")
     3270        fp.write("import os.path\n")
     3271        fp.write("import GSASIIpath\n\n")
     3272        for var in sorted(self.vars.keys(),key=lambda s: s.lower()):
     3273            if self.vars[var][1] is None: continue
     3274            if self.vars[var][1] == '': continue
     3275            if self.vars[var][0] == self.vars[var][1]: continue
     3276            try:
     3277                float(self.vars[var][1]) # test for number
     3278                fp.write(var + ' = ' + str(self.vars[var][1])+'\n')
     3279            except:
     3280                try:
     3281                    eval(self.vars[var][1]) # test for an expression
     3282                    fp.write(var + ' = ' + str(self.vars[var][1])+'\n')
     3283                except: # must be a string
     3284                    fp.write(var + ' = "' + str(self.vars[var][1])+'"\n')
     3285            if self.vars[var][3]:
     3286                fp.write("'''" + str(self.vars[var][3]) + "\n'''\n\n")
     3287        fp.close()
     3288        print('wrote file '+savefile)
     3289        # force a reload of the config settings
     3290        self.OnApplyChanges()
     3291        self.EndModal(wx.ID_OK)
     3292
     3293    def OnBoolSelect(self,event):
     3294        'Respond to a change in a True/False variable'
     3295        rb = event.GetEventObject()
     3296        var = self.choice[0]
     3297        self.vars[var][1] = (rb.GetSelection() == 0)
     3298        self.OnChange()
     3299        wx.CallAfter(self.OnSelection)
     3300       
     3301    def onSelDir(self,event):
     3302        'Select a directory from a menu'
     3303        dlg = wx.DirDialog(self, "Choose a directory:",style=wx.DD_DEFAULT_STYLE)
     3304        if dlg.ShowModal() == wx.ID_OK:
     3305            var = self.choice[0]
     3306            self.vars[var][1] = dlg.GetPath()
     3307            self.strEd.SetValue(self.vars[var][1])
     3308            self.OnChange()
     3309        dlg.Destroy()
     3310       
     3311    def OnSelection(self):
     3312        'show a selected variable'
     3313        self.varsizer.DeleteWindows()
     3314        var = self.choice[0]
     3315        showdef = True
     3316        if var not in self.vars:
     3317            raise Exception,"How did this happen?"
     3318        if type(self.vars[var][0]) is int:
     3319            ed = ValidatedTxtCtrl(self,self.vars[var],1,typeHint=int,OKcontrol=self.OnChange)
     3320            self.varsizer.Add(ed, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
     3321        elif type(self.vars[var][0]) is float:
     3322            ed = ValidatedTxtCtrl(self,self.vars[var],1,typeHint=float,OKcontrol=self.OnChange)
     3323            self.varsizer.Add(ed, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
     3324        elif type(self.vars[var][0]) is bool:
     3325            showdef = False
     3326            lbl = "value for "+var
     3327            ch = []
     3328            for i,v in enumerate((True,False)):
     3329                s = str(v)
     3330                if v == self.vars[var][0]:
     3331                    defopt = i
     3332                    s += ' (default)'
     3333                ch += [s]
     3334            rb = wx.RadioBox(
     3335                    self, wx.ID_ANY, lbl, wx.DefaultPosition, wx.DefaultSize,
     3336                    ch, 1, wx.RA_SPECIFY_COLS
     3337            )
     3338            # set initial value
     3339            if self.vars[var][1] is None:
     3340                rb.SetSelection(defopt)
     3341            elif self.vars[var][1]:
     3342                rb.SetSelection(0)
     3343            else:
     3344                rb.SetSelection(1)
     3345            rb.Bind(wx.EVT_RADIOBOX,self.OnBoolSelect)
     3346            self.varsizer.Add(rb, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
     3347        else:
     3348            if var.endswith('_directory') or var.endswith('_location'):
     3349                btn = wx.Button(self,wx.ID_ANY,'Select from dialog...')
     3350                sz = (400,-1)
     3351            else:
     3352                btn = None
     3353                sz = (250,-1)
     3354            self.strEd = ValidatedTxtCtrl(self,self.vars[var],1,typeHint=str,OKcontrol=self.OnChange,
     3355                                              size=sz)
     3356            if self.vars[var][1] is not None:
     3357                self.strEd.SetValue(self.vars[var][1])
     3358            self.varsizer.Add(self.strEd, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
     3359            if btn:
     3360                btn.Bind(wx.EVT_BUTTON,self.onSelDir)
     3361                self.varsizer.Add(btn, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
     3362        # button for reset to default value
     3363        lbl = "Reset to Default"
     3364        if showdef: # spell out default when needed
     3365            lbl += ' (='+str(self.vars[var][0])+')'
     3366            #label = wx.StaticText(self,  wx.ID_ANY, 'Default value = '+str(self.vars[var][0]))
     3367            #self.varsizer.Add(label, 0, wx.ALIGN_LEFT|wx.ALL, 5)
     3368        self.resetBtn = wx.Button(self,-1,lbl)
     3369        self.resetBtn.Bind(wx.EVT_BUTTON, self.OnClear)
     3370        if self.vars[var][1] is not None and self.vars[var][1] != '': # show current value, if one
     3371            #label = wx.StaticText(self,  wx.ID_ANY, 'Current value = '+str(self.vars[var][1]))
     3372            #self.varsizer.Add(label, 0, wx.ALIGN_LEFT|wx.ALL, 5)
     3373            self.resetBtn.Enable(True)
     3374        else:
     3375            self.resetBtn.Enable(False)
     3376        self.varsizer.Add(self.resetBtn, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
     3377        # show meaning, if defined
     3378        self.doclbl.SetLabel("Description of "+str(var))
     3379        if self.vars[var][3]:
     3380            self.docinfo.SetLabel(self.vars[var][3])
     3381        else:
     3382            self.docinfo.SetLabel("(not documented)")
     3383        self.sizer.Fit(self)
     3384        self.CenterOnParent()
     3385        wx.CallAfter(self.SendSizeEvent)
     3386
     3387    def OnClear(self, event):
     3388        var = self.choice[0]
     3389        self.vars[var][1] = self.vars[var][0]
     3390        self.OnChange()
     3391        wx.CallAfter(self.OnSelection)
     3392       
     3393################################################################################
    31283394class downdate(wx.Dialog):
    31293395    '''Dialog to allow a user to select a version of GSAS-II to install
Note: See TracChangeset for help on using the changeset viewer.