Changeset 1497 for branch/logging/log.py


Ignore:
Timestamp:
Sep 16, 2014 2:28:31 PM (7 years ago)
Author:
toby
Message:

logging more complete

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branch/logging/log.py

    r1477 r1497  
    11'Module to provide logging services'
    22import wx
    3 G2loggingData = {}
     3import GSASIIgrid as G2gd
     4MenuBindingLookup = {}
    45G2logList = [None]
     6'Contains a list of logged actions; first item is ignored'
     7LogInfo = {'Logging':False, 'Tree':None}
     8'Contains a dict with values that are needed in the module'
     9
     10debug = True
     11
     12# TODO:
     13### Note: no provinance info for histogram instrument parameters: need to remove insVal etc.
     14
     15# track histograms and phases with relative indices
     16
     17#===========================================================================
     18# objects for logging variables
     19def _l2s(lst,separator='+'):
     20    'Combine a list of objects into a string, with a separator'
     21    s = ''
     22    for i in lst:
     23        if s != '': s += separator
     24        s += '"'+str(i)+'"'
     25    return s
    526
    627class VarLogEntry(object):
     28    'object that tracks changes to a variable'
    729    def __init__(self,treeRefs,indexRefs,value):
    830        self.treeRefs = treeRefs
    931        self.indexRefs = indexRefs
    1032        self.value = value
    11 
    12 def LogVarChange(result,key):
    13     if hasattr(result,'treeRefs'):
    14         lastLog = G2logList[-1]
    15         fullrefs = result.indexRefs+[key]
    16         if type(lastLog) is VarLogEntry:
    17             if lastLog.treeRefs == result.treeRefs and lastLog.indexRefs == fullrefs:
    18                 lastLog.value = result[key]
    19                 print 'update last to ',result[key]
    20                 return
    21         G2logList.append(VarLogEntry(result.treeRefs,fullrefs,result[key]))
    22         print 'treeRefs',result.treeRefs,'indexRefs',fullrefs,'new value=',result[key]
    23     else:
    24         print key,'no provenance'
    25 
    26 class G2TreeCtrl(wx.TreeCtrl):
    27     '''Create a wrapper around the standard TreeCtrl so we can "trap"
    28     various events'''
    29     def __init__(self,parent=None,*args,**kwargs):
    30         super(self.__class__,self).__init__(parent=parent,*args,**kwargs)
    31         G2loggingData['frame'] = parent.GetParent()
    32         G2loggingData['tree'] = self
    33         G2loggingData['root'] = self.root = self.AddRoot('Loaded Data: ')
    34 
    35     def GetItemPyData(self,*args,**kwargs):
    36         data = super(self.__class__,self).GetItemPyData(*args,**kwargs)
    37         item = args[0]
    38         textlist = [self.GetItemText(item)]
    39         parent = self.GetItemParent(item)
    40         while parent:
    41             if parent == G2loggingData['root']: break
    42             textlist.insert(0,self.GetItemText(parent))
    43             parent = self.GetItemParent(parent)
    44         #print 'GetItemPyData from ',textlist,
    45         #data._treeorigin = textlist
    46         #print type(data)
    47         if type(data) is dict:
    48             #print 'dict'
    49             return dictLogged(data,textlist)
    50             #return data
    51         if type(data) is list:
    52             #print 'list'
    53             return listLogged(data,textlist)
    54         if type(data) is tuple:
    55             return listLogged(list(data),textlist)
    56         #print 'other'
    57         return data
    58 
    59 # class loggedDict(object):
    60 #     def __init__(self,dictobj,treeRefs,indexRefs=[]):
    61 #         self.treeRefs = treeRefs
    62 #         self.indexRefs = indexRefs
    63 #         self.obj = dictobj
    64 
    65 #     def __getitem__(self,*args,**kwargs):
    66 #         print 'getitem',args,kwargs,'...',
    67 #         val = self.obj.__getitem__(*args,**kwargs)
    68 # #        if type(val) is dict and len(args) == 1:
    69 # #            print 'dict'
    70 # #            return loggedDict(val,self.treeRefs,self.indexRefs+[args[0]])
    71 # #        elif type(val) is list and len(args) == 1:
    72 # #            print 'list'
    73 # #            return loggedList(val,self.treeRefs,self.indexRefs+[args[0]])
    74 # #        else:
    75 # #            print type(val),val
    76 # #            return val
    77 #         return val
    78 #     def get(self,*args,**kwargs):
    79 #         print 'get',args,kwargs
    80 #         val = self.obj.get(*args,**kwargs)
    81 #         if val is None: return None
    82 #         return self.__getitem__(*args,**kwargs)
    83 #     def __setitem__(self,*args,**kwargs):
    84 #         self.obj.__setitem__(*args,**kwargs)
    85 
    86        
    87 #     def __repr__(self):
    88 #         return "loggedDict with "+str(len(self.obj))+" members; from "+str(self.treeRefs)+" indexed by "+str(self.indexRefs)
    89 
    90 #     def __str__(self):
    91 #         return str(self.obj)
    92 
    93 #     def clear(self,*args,**kwargs):
    94 #         return self.obj.clear(*args,**kwargs)
    95 #     def copy(self,*args,**kwargs):
    96 #         return self.obj.copy(*args,**kwargs)
    97 #     def fromkeys(self,*args,**kwargs):
    98 #         return self.obj.fromkey(*args,**kwargs)
    99 #     def has_key(self,*args,**kwargs):
    100 #         return self.obj.has_key(*args,**kwargs)
    101 #     def items(self,*args,**kwargs):
    102 #         return self.obj.items(*args,**kwargs)
    103 #     def iteritems(self,*args,**kwargs):
    104 #         return self.obj.iteritems(*args,**kwargs)
    105 #     def iterkeys(self,*args,**kwargs):
    106 #         return self.obj.iterkeys(*args,**kwargs)
    107 #     def itervalues(self,*args,**kwargs):
    108 #         return self.obj.itervalues(*args,**kwargs)
    109 #     def keys(self,*args,**kwargs):
    110 #         return self.obj.keys(*args,**kwargs)
    111 #     def pop(self,*args,**kwargs):
    112 #         return self.obj.pop(*args,**kwargs)
    113 #     def popitem(self,*args,**kwargs):
    114 #         return self.obj.popitem(*args,**kwargs)
    115 #     def setdefault(self,*args,**kwargs):
    116 #         return self.obj.setdefault(*args,**kwargs)
    117 #     def update(self,*args,**kwargs):
    118 #         return self.obj.update(*args,**kwargs)
    119 #     def values(self,*args,**kwargs):
    120 #         return self.obj.values(*args,**kwargs)
    121 #     def viewitems(self,*args,**kwargs):
    122 #         return self.obj.viewitems(*args,**kwargs)
    123 #     def viewkeys(self,*args,**kwargs):
    124 #         return self.obj.viewkeys(*args,**kwargs)
    125 #     def viewvalues(self,*args,**kwargs):
    126 #         return self.obj.viewvalues(*args,**kwargs)
    127 
    128    
    129 
    130 # class loggedList(object):
    131 #     def __init__(self,listobj,treeRefs,indexRefs=[]):
    132 #         self.treeRefs = treeRefs
    133 #         self.indexRefs = indexRefs
    134 #         self.obj = listobj
    135 
    136 #     def __getitem__(self,*args,**kwargs):
    137 #         print 'list getitem',args,kwargs,'...',
    138 #         val = self.obj.__getitem__(*args,**kwargs)
    139 #         # if type(val) is dict and len(args) == 1:
    140 #         #     print 'dict'
    141 #         #     return loggedDict(val,self.treeRefs,self.indexRefs+[args[0]])
    142 #         # elif type(val) is list and len(args) == 1:
    143 #         #     print 'list'
    144 #         #     return loggedList(val,self.treeRefs,self.indexRefs+[args[0]])
    145 #         # else:
    146 #         #     print type(val),val
    147 #         #     return val
    148 #         return val
    149 
    150 #     def __len__(self,*args,**kwargs):
    151 #         return self.obj.__len__(*args,**kwargs)
    152 
    153 #     def __setitem__(self,*args,**kwargs):
    154 #         return self.obj.__setitem__(*args,**kwargs)
    155        
    156 #     def __repr__(self):
    157 #         return "loggedList with "+str(len(self.obj))+" members; from "+str(self.treeRefs)+" indexed by "+str(self.indexRefs)
    158 
    159 #     def __str__(self):
    160 #         return str(self.obj)
    161 
    162 ###############
     33        if debug: print 'Logging var change: w/treeRefs',treeRefs,'indexRefs',indexRefs,'new value=',value
     34    def __str__(self):
     35        return 'Variable change: Key(s)= '+_l2s(self.indexRefs)+' to value='+str(self.value)
     36
     37class MenuLogEntry(object):
     38    'object that tracks when a menu command is executed'
     39    def __init__(self,menulabellist):
     40        self.menulabellist = menulabellist
     41        if debug:
     42            t = menulabellist[:]
     43            t.reverse()
     44            l = ''
     45            for item in t:
     46                if l: l += ' -> '
     47                l += item
     48        if debug: print 'Logging menu command: '+l
     49    def __str__(self):
     50        return 'Menu press: From '+_l2s(self.menulabellist,'/')
     51           
     52class TabLogEntry(object):
     53    'Object to track when tabs are pressed in the DataFrame window'
     54    def __init__(self,title,tabname):
     55        self.wintitle = title
     56        self.tablabel = tabname
     57        if debug: print 'Logging tab: "'+tabname+'" on window titled '+title
     58    def __str__(self):
     59        return 'Tab press: Tab='+_l2s([self.tablabel])+' on window labeled '+str(self.wintitle)
     60
     61class TreeLogEntry(object):
     62    'Object to track when tree items are pressed in the main window'
     63    def __init__(self,itemlist):
     64        self.treeItemList = itemlist
     65        if debug: print 'Logging press on tree: "',itemlist
     66    def __str__(self):
     67        return 'Tree item pressed: '+_l2s(self.treeItemList)
     68           
    16369def _wrapper(func):
    16470    def _wrapped(self, *args, **kwargs):
     
    17581
    17682class dictLogged(object):
     83    '''A version of a dict object that tracks the source of the
     84    object back to the location on the G2 tree.
     85    If a list (tuple) or dict are pulled from inside this object
     86    the source information is appended to the provinance tracking
     87    lists.
     88
     89    tuples are converted to lists.
     90    '''
    17791    __metaclass__ = DictMeta
    17892
     
    18397
    18498    def __getitem__(self,key):
    185         #print "logging", key,
    18699        val = self.obj.__getitem__(key)   
    187100        if type(val) is tuple:
    188             print 'Converting to list',key
     101            #if debug: print 'Converting to list',key
    189102            val = list(val)
    190103            self.obj[key] = val
     
    195108            #print 'list'
    196109            return listLogged(val,self.treeRefs,self.indexRefs+[key])
    197         elif type(val) is tuple:
    198             print type(val),val
    199             raise Exception
    200             return val
    201110        else:
    202111            #print type(val)
    203112            return val
    204 #        return val
    205113
    206114    def __str__(self):
     
    216124
    217125class listLogged(object):
     126    '''A version of a list object that tracks the source of the
     127    object back to the location on the G2 tree.
     128    If a list (tuple) or dict are pulled from inside this object
     129    the source information is appended to the provinance tracking
     130    lists.
     131   
     132    tuples are converted to lists.
     133    '''
    218134    __metaclass__ = ListMeta
    219135
     
    224140
    225141    def __getitem__(self,key):
    226         #print "logging", key,
    227142        val = self.obj.__getitem__(key)   
    228143        if type(val) is tuple:
    229             print 'Converting to list',key,
     144            #if debug: print 'Converting to list',key
    230145            val = list(val)
    231146            self.obj[key] = val
     
    236151            #print 'list'
    237152            return listLogged(val,self.treeRefs,self.indexRefs+[key])
    238         elif type(val) is tuple:
    239             print type(val),val
    240             raise Exception
    241153        else:
    242154            #print type(val)
    243155            return val
    244         return self.obj.__getitem__(key)   
    245156
    246157    def __str__(self):
    247158        return self.obj.__str__() + " : " + str(self.treeRefs) + ',' + str(self.indexRefs)
    248 ###############
    249 
    250    
    251 def SimTreeEvent(treekeylist):
    252     # lookup key from list of items
    253     parent = G2loggingData['root']
    254     for txt in treekeylist:
    255         item = GetPatternTreeItemId(G2loggingData['frame'],parent,txt)
    256         if not item:
    257             print 'Not found',txt
     159
     160#===========================================================================
     161class G2TreeCtrl(wx.TreeCtrl):
     162    '''Create a wrapper around the standard TreeCtrl so we can "wrap"
     163    various events.
     164   
     165    This logs when a tree item is selected (in :meth:`onSelectionChanged`)
     166
     167    This also wraps lists and dicts pulled out of the tree to track where
     168    they were retrieved from.
     169    '''
     170    def __init__(self,parent=None,*args,**kwargs):
     171        super(self.__class__,self).__init__(parent=parent,*args,**kwargs)
     172        self.G2frame = parent.GetParent()
     173        self.root = self.AddRoot('Loaded Data: ')
     174        self.SelectionChanged = None
     175        self.repaintAction = None
     176        LogInfo['Tree'] = self
     177
     178    def _getTreeItemsList(self,item):
     179        '''Get the full tree hierarchy from a reference to a tree item.
     180        Note that this effectively hard-codes phase and histogram names in the
     181        returned list. We may want to make these names relative in the future.
     182        '''
     183        textlist = [self.GetItemText(item)]
     184        parent = self.GetItemParent(item)
     185        while parent:
     186            if parent == self.root: break
     187            textlist.insert(0,self.GetItemText(parent))
     188            parent = self.GetItemParent(parent)
     189        return textlist
     190
     191    def onSelectionChanged(self,event):
     192        '''Log each press on a tree item here.
     193        '''
     194        if self.SelectionChanged:
     195            textlist = self._getTreeItemsList(event.GetItem())
     196            if LogInfo['Logging']:
     197                G2logList.append(TreeLogEntry(textlist))
     198            self.SelectionChanged(event)
     199
     200    def Bind(self,eventtype,handler,*args,**kwargs):
     201        '''Override the Bind() function so that page change events can be trapped
     202        '''
     203        if eventtype == wx.EVT_TREE_SEL_CHANGED:
     204            self.SelectionChanged = handler
     205            wx.TreeCtrl.Bind(self,eventtype,self.onSelectionChanged)
    258206            return
    259         else:
    260             parent = item
     207        wx.TreeCtrl.Bind(self,eventtype,handler,*args,**kwargs)
     208
     209    def GetItemPyData(self,*args,**kwargs):
     210        '''Override the standard method to wrap the contents
     211        so that the source can be tracked
     212        '''
     213        data = super(self.__class__,self).GetItemPyData(*args,**kwargs)
     214        textlist = self._getTreeItemsList(args[0])
     215        if type(data) is dict:
     216            return dictLogged(data,textlist)
     217        if type(data) is list:
     218            return listLogged(data,textlist)
     219        if type(data) is tuple: #N.B. tuples get converted to lists
     220            return listLogged(list(data),textlist)
     221        return data
     222
     223    def ClearDataRepaint(self):
     224        self.repaintAction = None
     225
     226    def RepaintDataWindow(self):
     227        item = self.repaintAction
     228        if isinstance(item,TreeLogEntry):
     229            self.SelectItem(self.root) # need to select something else
     230            self.ReplayTreePress(item)
     231        elif isinstance(item,TabLogEntry):
     232            self.ReplayTabPress(item)
     233           
     234    def ReplayLogItem(self,item):
     235        'Execute an action taken from a log file entry'
     236        if isinstance(item,MenuLogEntry):
     237            self.ReplayMenuCommand(item)
     238        elif isinstance(item,TreeLogEntry):
     239            self.ReplayTreePress(item)
     240            self.repaintAction = item
     241        elif isinstance(item,VarLogEntry):
     242            self.ReplayVariableChange(item)
     243        elif isinstance(item,TabLogEntry):
     244            self.ReplayTabPress(item)
     245            self.repaintAction = item
     246        else:
     247            raise Exception("Unknown object in log: "+str(type(item))+": "
     248                            +str(item))
     249       
     250    def ReplayTreePress(self,logitem):
     251        'Perform a Tree press action when read from the log'
     252        parent = self.root
     253        for txt in logitem.treeItemList:
     254            item = G2gd.GetPatternTreeItemId(self.G2frame,parent,txt)
     255            if not item:
     256                print 'Not found',txt
     257                return
     258            else:
     259                parent = item
     260        else:
     261            self.SelectItem(item)
     262               
     263    def ReplayTabPress(self,logitem):
     264        'Perform a Tab press action when read from the log'
     265        wintitle = logitem.wintitle
     266        tabname = logitem.tablabel
     267        if self.G2frame.dataFrame.GetTitle() != wintitle:
     268            print self.G2frame.dataFrame.GetTitle(),' != ',wintitle
     269            raise Exception('tab in wrong window')
     270        for PageNum in range(self.G2frame.dataDisplay.GetPageCount()):
     271            if tabname == self.G2frame.dataDisplay.GetPageText(PageNum):
     272                self.G2frame.dataDisplay.SetSelection(PageNum)
     273                return
     274        else:
     275            print tabname,'not in',[
     276                self.G2frame.dataDisplay.GetPageText(PageNum) for
     277                PageNum in range(self.G2frame.dataDisplay.GetPageCount())]
     278            raise Exception('tab not found')
     279    def ReplayVariableChange(self,logitem):
     280        'Perform a Variable Change action, when read from the log'
     281        parentId = self.root
     282        for treeitem in logitem.treeRefs:
     283            item, cookie = self.GetFirstChild(parentId)
     284            while item:
     285                if self.GetItemText(item) == treeitem:
     286                    parentId = item
     287                    break
     288                else:
     289                    item, cookie = self.GetNextChild(parentId, cookie)
     290            else:
     291                raise Exception("Tree item not found for "+str(logitem))
     292        # get the inner most data array
     293        data = super(self.__class__,self).GetItemPyData(item)
     294        for item in logitem.indexRefs[:-1]:
     295            data = data[item]
     296        # set the value
     297        data[logitem.indexRefs[-1]] = logitem.value
     298    def ReplayMenuCommand(self,logitem):
     299        'Perform a Menu item action when read from the log'
     300        key = ''
     301        for item in logitem.menulabellist:
     302            if key: key += '+'
     303            key += item
     304        if MenuBindingLookup.get(key):
     305            MenuBindingLookup[key](None)
     306        else:
     307            raise Exception('No binding for menu item '+key)       
     308       
     309#===========================================================================
     310# variable tracking
     311def LogVarChange(result,key):
     312    'Called when a variable is changed to log that action'
     313    if not LogInfo['Logging']: return
     314    if hasattr(result,'treeRefs'):
     315        lastLog = G2logList[-1]
     316        fullrefs = result.indexRefs+[key]
     317        if type(lastLog) is VarLogEntry:
     318            if lastLog.treeRefs == result.treeRefs and lastLog.indexRefs == fullrefs:
     319                lastLog.value = result[key]
     320                if debug: print 'update last log to ',result[key]
     321                return
     322        G2logList.append(VarLogEntry(result.treeRefs,fullrefs,result[key]))
    261323    else:
    262         print 'found',G2loggingData['tree'].GetItemText(item)
    263         print item
    264         #code = wx.EVT_TREE_SEL_CHANGED.typeId
    265         #clickEvent = wx.TreeEvent(code, G2loggingData['tree'].GetId())
    266         #print clickEvent
    267         #clickEvent.SetItem(item)
    268         #G2loggingData['tree'].GetEventHandler().ProcessEvent(clickEvent)
    269     G2loggingData['tree'].SelectItem(item)   
    270 def SimTabPress(wintitle,tabname):
    271     if G2loggingData['frame'].dataFrame.GetTitle() != wintitle:
    272             print G2loggingData['frame'].dataFrame.GetTitle(),' != ','Phase Data for CuCr2O4'
    273             raise Exception('tab in wrong window')
    274     for PageNum in range(G2loggingData['frame'].dataDisplay.GetPageCount()):
    275         if tabname == G2loggingData['frame'].dataDisplay.GetPageText(PageNum):
    276             G2loggingData['frame'].dataDisplay.SetSelection(PageNum)
     324        print key,'Error: var change has no provenance info'
     325
     326#===========================================================================
     327# menu command tracking
     328def _getmenuinfo(id,G2frame,handler):
     329    '''Look up the menu/menu-item label tree from a menuitem's Id
     330   
     331    Note that menubars contain multiple menus which contain multiple menuitems.
     332    A menuitem can itself point to a menu and if so that menu can contain
     333    multiple menuitems.
     334
     335    Here we start with the last menuitem and look up the label for that as well
     336    as all parents, which will be found in parent menuitems (if any) and the menubar.
     337   
     338        menuitem    ->  menu ->  menubar
     339           |                          |
     340           |->itemlabel               |-> menulabel
     341           
     342    or
     343
     344        menuitem    ->  (submenu -> menuitem)*(n times) -> menu -> menubar
     345           |                            |                             |
     346           |->itemlabel                 |-> sublabel(s)               |-> menulabel
     347           
     348    :returns: a list containing all the labels (or None)           
     349    '''
     350    # don't worry about help menuitems
     351    if id == wx.ID_ABOUT: return
     352    # get the menu item object by searching through all menubars and then its label
     353    for menubar in G2frame.dataMenuBars:
     354        menuitem = menubar.FindItemById(id)
     355        if menuitem:
     356            #print 'getmenuinfo found',id,menuitem
     357            break
     358    else:
     359        print '****** getmenuinfo failed for id=',id,'binding to=',handler
     360        #raise Exception('debug: getmenuinfo failed')
     361        return
     362    menuLabelList = [menuitem.GetItemLabel()]
     363   
     364    # get the menu where the current item is located
     365    menu = menuitem.GetMenu()
     366    while menu.GetParent(): # is this menu a submenu of a previous menu?
     367        parentmenu = menu.GetParent()
     368        # cycle through the parentmenu until we find the menu
     369        for i in range(parentmenu.GetMenuItemCount()):
     370            if parentmenu.FindItemByPosition(i).GetSubMenu()==menu:
     371                menuLabelList += [parentmenu.FindItemByPosition(i).GetItemLabel()]
     372                break
     373        else:
     374            # menu not found in menu, something is wrong
     375            print 'error tracing menuitem to parent menu',menuLabelList
     376            #raise Exception('debug1: error tracing menuitem')
    277377            return
     378        menu = parentmenu
     379
     380    menubar = menu.MenuBar
     381    for i in range(menubar.GetMenuCount()):
     382        if menubar.GetMenu(i) == menu:
     383            menuLabelList += [menubar.GetMenuLabel(i)]
     384            break
    278385    else:
    279         print tabname,'not in',[
    280             G2loggingData['frame'].dataDisplay.GetPageText(PageNum) for
    281             PageNum in range(G2loggingData['frame'].dataDisplay.GetPageCount())]
    282         raise Exception('tab not found')
    283 def LogTabPress(G2frame,page):
    284     print 'Log page tab'
    285     print G2frame.dataFrame.GetTitle()
    286     print G2frame.dataDisplay.GetPageText(page)
    287        
     386        # menu not found in menubar, something is wrong
     387        print 'error tracing menuitem to menubar',menuLabelList
     388        #raise Exception('debug2: error tracing menuitem')
     389        return
     390    return menuLabelList
     391
     392def SaveMenuCommand(id,G2frame,handler):
     393    '''Creates a table of menu items and their pseudo-bindings
     394    '''
     395    menuLabelList = _getmenuinfo(id,G2frame,handler)
     396    if not menuLabelList: return
     397    key = ''
     398    for item in menuLabelList:
     399        if key: key += '+'
     400        key += item
     401    MenuBindingLookup[key] = handler
     402    return menuLabelList
     403
     404def InvokeMenuCommand(id,G2frame,event):
     405    '''Called when a menu item is used to log the action as well as call the
     406    routine "bind"ed to that menu item
     407    '''
     408    menuLabelList = _getmenuinfo(id,G2frame,None)
     409    key = ''
     410    if menuLabelList:
     411        for item in menuLabelList:
     412            if key: key += '+'
     413            key += item
     414    if key in MenuBindingLookup:
     415        if LogInfo['Logging']:
     416            G2logList.append(MenuLogEntry(menuLabelList))
     417        MenuBindingLookup[key](event)
     418    else:
     419        print 'Error no binding for menu command',menuLabelList,'id=',id
     420        return
     421
     422#===========================================================================
     423# Misc externally callable routines
     424def LogOn():
     425    'Turn On logging of actions'
     426    LogInfo['Logging'] = True
     427
     428def LogOff():
     429    'Turn Off logging of actions'
     430    LogInfo['Logging'] = False
     431
     432def ShowLogStatus():
     433    'Return the logging status'
     434    return LogInfo['Logging']
     435
     436def ReplayLog(event):
     437    'replay the logged actions (needs to be a wx.widget)'
     438    LogOff() # TODO: need to update menu item as well
     439    LogInfo['Tree'].ClearDataRepaint()
     440    print 70*'='
     441    print 'Performing logged actions:'
     442    for item in G2logList:
     443        if item:
     444            print item
     445            LogInfo['Tree'].ReplayLogItem(item)
     446            wx.Yield()
     447    # do repaint here
     448    LogInfo['Tree'].RepaintDataWindow()
     449    print 70*'='
     450   
     451   
     452   
Note: See TracChangeset for help on using the changeset viewer.