Changeset 1509


Ignore:
Timestamp:
Sep 29, 2014 2:31:04 PM (9 years ago)
Author:
toby
Message:

logging refactored, and much cleaner\!

Location:
branch/logging
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branch/logging/GSASII.py

    r1505 r1509  
    16321632        if nextvalue:
    16331633            log.LogOn()
    1634             setto = True
     1634            set2 = True
    16351635        else:
    16361636            log.LogOff()
    1637             setto = False
     1637            set2 = False
    16381638        for menuitem in self.MacroStatusList:
    1639             menuitem.Check(setto)
     1639            menuitem.Check(set2)
    16401640
    16411641    def _init_Macro(self):
     
    16561656            print 70*'='
    16571657            print 'List of logged actions'
    1658             for line in log.G2logList:
    1659                 if line: print line
     1658            for i,line in enumerate(log.G2logList):
     1659                if line: print i,line
    16601660            print 70*'='
    16611661        self.Bind(wx.EVT_MENU, OnShowLog, item)
    16621662
     1663        item = menu.Append(
     1664            help='Clear logged commands', id=wx.ID_ANY,
     1665            kind=wx.ITEM_NORMAL,text='Clear log')
     1666        def OnClearLog(event): log.G2logList=[None]
     1667        self.Bind(wx.EVT_MENU, OnClearLog, item)
     1668       
    16631669        item = menu.Append(
    16641670            help='Save logged commands to file', id=wx.ID_ANY,
     
    16861692            if filename:
    16871693                fp = open(filename,'wb')
    1688                 fp.write(str(len(log.G2logList))+'\n')
     1694                fp.write(str(len(log.G2logList)-1)+'\n')
    16891695                for item in log.G2logList:
    1690                     cPickle.dump(item,fp)
     1696                    if item: cPickle.dump(item,fp)
    16911697                fp.close()
    16921698        self.Bind(wx.EVT_MENU, OnSaveLog, item)
     
    16961702            kind=wx.ITEM_NORMAL,text='Load log')
    16971703        def OnLoadLog(event):
     1704            # this appends. Perhaps we should ask to clear?
    16981705            import log
    16991706            import cPickle
     
    19741981        #self.PatternTree = wx.TreeCtrl(id=wxID_PATTERNTREE,
    19751982        import log
    1976         self.PatternTree = log.G2TreeCtrl(id=wxID_PATTERNTREE,
     1983        self.PatternTree = G2gd.G2TreeCtrl(id=wxID_PATTERNTREE,
    19771984            parent=self.mainPanel, pos=wx.Point(0, 0),style=wx.TR_DEFAULT_STYLE )
    19781985        self.PatternTree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnPatternTreeSelChanged)
  • branch/logging/GSASIIgrid.py

    r1497 r1509  
    160160#### GSAS-II class definitions
    161161################################################################################       
    162 
     162class G2TreeCtrl(wx.TreeCtrl):
     163    '''Create a wrapper around the standard TreeCtrl so we can "wrap"
     164    various events.
     165   
     166    This logs when a tree item is selected (in :meth:`onSelectionChanged`)
     167
     168    This also wraps lists and dicts pulled out of the tree to track where
     169    they were retrieved from.
     170    '''
     171    def __init__(self,parent=None,*args,**kwargs):
     172        super(self.__class__,self).__init__(parent=parent,*args,**kwargs)
     173        log.LogInfo['G2frame'] = self.G2frame = parent.GetParent()
     174        self.root = self.AddRoot('Loaded Data: ')
     175        self.SelectionChanged = None
     176        log.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 log.LogInfo['Logging'] and event.GetItem() != self.root:
     197                textlist[0] = self.GetRelativeHistNum(textlist[0])
     198                if textlist[0] == "Phases" and len(textlist) > 1:
     199                    textlist[1] = self.GetRelativePhaseNum(textlist[1])
     200                log.G2logList.append(log.TreeLogEntry(textlist))
     201            self.SelectionChanged(event)
     202
     203    def Bind(self,eventtype,handler,*args,**kwargs):
     204        '''Override the Bind() function so that page change events can be trapped
     205        '''
     206        if eventtype == wx.EVT_TREE_SEL_CHANGED:
     207            self.SelectionChanged = handler
     208            wx.TreeCtrl.Bind(self,eventtype,self.onSelectionChanged)
     209            return
     210        wx.TreeCtrl.Bind(self,eventtype,handler,*args,**kwargs)
     211
     212    def GetItemPyData(self,*args,**kwargs):
     213        '''Override the standard method to wrap the contents
     214        so that the source can be tracked
     215        '''
     216        data = super(self.__class__,self).GetItemPyData(*args,**kwargs)
     217        textlist = self._getTreeItemsList(args[0])
     218        if type(data) is dict:
     219            return log.dictLogged(data,textlist)
     220        if type(data) is list:
     221            return log.listLogged(data,textlist)
     222        if type(data) is tuple: #N.B. tuples get converted to lists
     223            return log.listLogged(list(data),textlist)
     224        return data
     225
     226    def GetRelativeHistNum(self,histname):
     227        '''Returns list with a histogram type and a relative number for that
     228        histogram, or the original string if not a histogram
     229        '''
     230        histtype = histname.split()[0]
     231        if histtype != histtype.upper(): # histograms (only) have a keyword all in caps
     232            return histname
     233        item, cookie = self.GetFirstChild(self.root)
     234        i = 0
     235        while item:
     236            itemtext = self.GetItemText(item)
     237            if itemtext == histname:
     238                return histtype,i
     239            elif itemtext.split()[0] == histtype:
     240                i += 1
     241            item, cookie = self.GetNextChild(self.root, cookie)
     242        else:
     243            raise Exception("Histogram not found: "+histname)
     244
     245    def ConvertRelativeHistNum(self,histtype,histnum):
     246        '''Converts a histogram type and relative histogram number to a
     247        histogram name in the current project
     248        '''
     249        item, cookie = self.GetFirstChild(self.root)
     250        i = 0
     251        while item:
     252            itemtext = self.GetItemText(item)
     253            if itemtext.split()[0] == histtype:
     254                if i == histnum: return itemtext
     255                i += 1
     256            item, cookie = self.GetNextChild(self.root, cookie)
     257        else:
     258            raise Exception("Histogram #'+str(histnum)+' of type "+histtype+' not found')
     259       
     260    def GetRelativePhaseNum(self,phasename):
     261        '''Returns a phase number if the string matches a phase name
     262        or else returns the original string
     263        '''
     264        item, cookie = self.GetFirstChild(self.root)
     265        while item:
     266            itemtext = self.GetItemText(item)
     267            if itemtext == "Phases":
     268                parent = item
     269                item, cookie = self.GetFirstChild(parent)
     270                i = 0
     271                while item:
     272                    itemtext = self.GetItemText(item)
     273                    if itemtext == phasename:
     274                        return i
     275                    item, cookie = self.GetNextChild(parent, cookie)
     276                    i += 1
     277                else:
     278                    return phasename # not a phase name
     279            item, cookie = self.GetNextChild(self.root, cookie)
     280        else:
     281            raise Exception("No phases found ")
     282
     283    def ConvertRelativePhaseNum(self,phasenum):
     284        '''Converts relative phase number to a phase name in
     285        the current project
     286        '''
     287        item, cookie = self.GetFirstChild(self.root)
     288        while item:
     289            itemtext = self.GetItemText(item)
     290            if itemtext == "Phases":
     291                parent = item
     292                item, cookie = self.GetFirstChild(parent)
     293                i = 0
     294                while item:
     295                    if i == phasenum:
     296                        return self.GetItemText(item)
     297                    item, cookie = self.GetNextChild(parent, cookie)
     298                    i += 1
     299                else:
     300                    raise Exception("Phase "+str(phasenum)+" not found")
     301            item, cookie = self.GetNextChild(self.root, cookie)
     302        else:
     303            raise Exception("No phases found ")
     304#===========================================================================
     305class G2LoggedButton(wx.Button):
     306    '''A version of wx.Button that creates logging events. Bindings are saved
     307    in the object, and are looked up rather than directly set with a bind.
     308    An index to these buttons is saved as log.ButtonBindingLookup
     309    '''
     310    def __init__(self,parent,id,label,locationcode,handler,*args,**kwargs):
     311        super(self.__class__,self).__init__(parent,id,label,*args,**kwargs)
     312        self.label = label
     313        self.handler = handler
     314        self.locationcode = locationcode
     315        key = locationcode + '+' + label # hash code to find button
     316        self.Bind(wx.EVT_BUTTON,self.onPress)
     317        log.ButtonBindingLookup[key] = self
     318    def onPress(self,event):
     319        'create log event and call handler'
     320        G2logList.append(log.ButtonLogEntry(self.locationcode,self.label))
     321        self.handler(event)
     322
     323#===========================================================================
    163324class ValidatedTxtCtrl(wx.TextCtrl):
    164325    '''Create a TextCtrl widget that uses a validator to prevent the
     
    26702831        For other platforms, either wrap calls that will be logged
    26712832        or call the default wx.Frame Bind() to bind to the menu item directly.
     2833
     2834        Note that bindings can be made to objects by Id or by direct reference to the
     2835        object. As a convention, when bindings are to objects, they are not logged
     2836        but when bindings are by Id, they are logged.
    26722837        '''
    26732838        if sys.platform == "darwin": # mac
     
    39754140        print event
    39764141        treekeylist = [u'Phases', u'CuCr2O4']
    3977         log.SimTreeEvent(treekeylist)
    3978         log.SimTabPress('Phase Data for CuCr2O4','Atoms')
    3979     btn = wx.Button(G2frame.dataDisplay, wx.ID_ANY,"test")
    3980     btn.Bind(wx.EVT_BUTTON, TestButton)
     4142        #log.SimTreeEvent(treekeylist)
     4143        #log.SimTabPress('Phase Data for CuCr2O4','Atoms')
     4144    btn = G2LoggedButton(G2frame.dataDisplay, wx.ID_ANY,"test",
     4145                         locationcode='Controls',handler=TestButton)
     4146    #btn = wx.Button(G2frame.dataDisplay, wx.ID_ANY,"test")
     4147    #btn.Bind(wx.EVT_BUTTON, TestButton)
    39814148    mainSizer.Add(btn,0,wx.ALL,10)
    39824149   
  • branch/logging/log.py

    r1505 r1509  
    33import GSASIIgrid as G2gd
    44MenuBindingLookup = {}
     5'Lookup table for Menu buttons'
     6ButtonBindingLookup = {}
     7'Lookup table for button objects'
    58G2logList = [None]
    69'Contains a list of logged actions; first item is ignored'
    7 LogInfo = {'Logging':False, 'Tree':None, 'G2frame':None}
     10LogInfo = {'Logging':False, 'Tree':None, 'G2frame':None, 'LastPaintAction':None}
    811'Contains a dict with values that are needed in the module'
    912
     13# TODO:
     14# might want to save the last displayed screen with some objects to make sure
     15# the commands are executed in a sensible order
     16
     17# Problem: checks on Logging not set properly (still!)
     18
    1019debug = True
    11 
    12 # TODO:
    13 ### Note: no provinance info for histogram instrument parameters: need to remove insVal etc.
    14 
    1520#===========================================================================
    1621# objects for logging variables
     
    2328    return s
    2429
     30# Define logging objects. These store information on events in a manner that can be
     31# pickled and saved -- direct references to wx objects is not allowed.
     32# each object should define:
     33#     __init__: stores the information needed to log & later recreate the action
     34#     __str__ : shows a nice ASCII string for each action
     35#     Replay:   recreates the action when the log is played
     36# optional
     37#     Repaint:  redisplays the current window
     38
    2539class VarLogEntry(object):
    2640    'object that tracks changes to a variable'
     
    3751            treeList[1] = 'Phase #'+str(treeList[1]+1)
    3852        return 'Variable change: Key(s)= '+_l2s(self.indexRefs)+' to value='+str(self.value)
     53    def Replay(self):
     54        'Perform a Variable Change action, when read from the log'
     55        parentId = LogInfo['Tree'].root
     56        for i,treeitem in enumerate(self.treeRefs):
     57            if i == 0 and type(treeitem) is tuple:
     58                treeitem = LogInfo['Tree'].ConvertRelativeHistNum(*treeitem)
     59            item, cookie = LogInfo['Tree'].GetFirstChild(parentId)
     60            while item:
     61                if LogInfo['Tree'].GetItemText(item) == treeitem:
     62                    parentId = item
     63                    break
     64                else:
     65                    item, cookie = LogInfo['Tree'].GetNextChild(parentId, cookie)
     66            else:
     67                raise Exception("Tree item not found for "+str(self))
     68        # get the inner most data array
     69        data = LogInfo['Tree'].GetItemPyData(item)
     70        for item in self.indexRefs[:-1]:
     71            data = data[item]
     72        # set the value
     73        data[self.indexRefs[-1]] = self.value
    3974
    4075class MenuLogEntry(object):
     
    4984                if l: l += ' -> '
    5085                l += item
    51         if debug: print 'Logging menu command: '+l
     86            print 'Logging menu command: '+l
    5287    def __str__(self):
    5388        return 'Menu press: From '+_l2s(self.menulabellist,'/')
     89    def Replay(self):
     90        'Perform a Menu item action when read from the log'
     91        key = ''
     92        for item in self.menulabellist:
     93            if key: key += '+'
     94            key += item
     95        if MenuBindingLookup.get(key):
     96            handler,id,menuobj = MenuBindingLookup[key]
     97            MyEvent = wx.CommandEvent(wx.EVT_MENU.typeId, id)
     98            MyEvent.SetEventObject(menuobj)
     99            handler(MyEvent)
     100        else:
     101            raise Exception('No binding for menu item '+key)       
    54102           
    55103class TabLogEntry(object):
     
    61109    def __str__(self):
    62110        return 'Tab press: Tab='+_l2s([self.tablabel])+' on window labeled '+str(self.wintitle)
     111    def Repaint(self):
     112        if debug: print 'Repaint'
     113        saveval = LogInfo['LastPaintAction']
     114        self.Replay()
     115        LogInfo['LastPaintAction'] = saveval
     116    def Replay(self):
     117        'Perform a Tab press action when read from the log'
     118        wintitle = self.wintitle
     119        tabname = self.tablabel
     120        LogInfo['LastPaintAction'] = self
     121        if LogInfo['Tree'].G2frame.dataFrame.GetTitle() != wintitle:
     122            print LogInfo['Tree'].G2frame.dataFrame.GetTitle(),' != ',wintitle
     123            raise Exception('tab in wrong window')
     124        for PageNum in range(LogInfo['Tree'].G2frame.dataDisplay.GetPageCount()):
     125            if tabname == LogInfo['Tree'].G2frame.dataDisplay.GetPageText(PageNum):
     126                LogInfo['Tree'].G2frame.dataDisplay.SetSelection(PageNum)
     127                return
     128        else:
     129            print tabname,'not in',[
     130                LogInfo['Tree'].G2frame.dataDisplay.GetPageText(PageNum) for
     131                PageNum in range(LogInfo['Tree'].G2frame.dataDisplay.GetPageCount())]
     132            raise Exception('tab not found')
    63133
    64134class TreeLogEntry(object):
     
    74144            treeList[1] = 'Phase #'+str(treeList[1]+1)
    75145        return 'Tree item pressed: '+_l2s(treeList)
     146    def Repaint(self):
     147        if debug: print 'Repaint'
     148        saveval = LogInfo['LastPaintAction']
     149        LogInfo['Tree'].SelectItem(LogInfo['Tree'].root) # need to select something else
     150        wx.Yield()
     151        self.Replay()
     152        LogInfo['LastPaintAction'] = saveval
     153    def Replay(self):
     154        'Perform a Tree press action when read from the log'
     155        LogInfo['LastPaintAction'] = self
     156        parent = LogInfo['Tree'].root
     157        for i,txt in enumerate(self.treeItemList):
     158            if i == 0 and type(txt) is tuple:
     159                txt = LogInfo['Tree'].ConvertRelativeHistNum(*txt)
     160            elif i == 1 and type(txt) is int and self.treeItemList[0] == "Phases":
     161                txt = LogInfo['Tree'].ConvertRelativePhaseNum(txt)
     162            item = G2gd.GetPatternTreeItemId(LogInfo['Tree'].G2frame,parent,txt)
     163            if not item:
     164                print 'Not found',txt
     165                return
     166            else:
     167                parent = item
     168        else:
     169            LogInfo['Tree'].SelectItem(item)
     170
     171class ButtonLogEntry(object):
     172    'Object to track button press'
     173    def __init__(self,locationcode,label):
     174        self.locationcode = locationcode
     175        self.label = label
     176        if debug: print 'Logging '+label+' button press in '+locationcode
     177    def __str__(self):
     178        return 'Press of '+self.label+' button in '+self.locationcode
     179    def Replay(self):
     180        key = self.locationcode + '+' + self.label
     181        if ButtonBindingLookup.get(key):
     182            btn = ButtonBindingLookup[key]
     183            clickEvent = wx.CommandEvent(wx.EVT_BUTTON.typeId, btn.GetId())
     184            clickEvent.SetEventObject(btn)
     185            #btn.GetEventHandler().ProcessEvent(clickEvent)
     186            btn.handler(clickEvent)
    76187           
    77188def _wrapper(func):
     
    166277        return self.obj.__str__() + " : " + str(self.treeRefs) + ',' + str(self.indexRefs)
    167278
    168 #===========================================================================
    169 class G2TreeCtrl(wx.TreeCtrl):
    170     '''Create a wrapper around the standard TreeCtrl so we can "wrap"
    171     various events.
    172    
    173     This logs when a tree item is selected (in :meth:`onSelectionChanged`)
    174 
    175     This also wraps lists and dicts pulled out of the tree to track where
    176     they were retrieved from.
    177     '''
    178     def __init__(self,parent=None,*args,**kwargs):
    179         super(self.__class__,self).__init__(parent=parent,*args,**kwargs)
    180         LogInfo['G2frame'] = self.G2frame = parent.GetParent()
    181         self.root = self.AddRoot('Loaded Data: ')
    182         self.SelectionChanged = None
    183         self.repaintAction = None
    184         LogInfo['Tree'] = self
    185 
    186     def _getTreeItemsList(self,item):
    187         '''Get the full tree hierarchy from a reference to a tree item.
    188         Note that this effectively hard-codes phase and histogram names in the
    189         returned list. We may want to make these names relative in the future.
    190         '''
    191         textlist = [self.GetItemText(item)]
    192         parent = self.GetItemParent(item)
    193         while parent:
    194             if parent == self.root: break
    195             textlist.insert(0,self.GetItemText(parent))
    196             parent = self.GetItemParent(parent)
    197         return textlist
    198 
    199     def onSelectionChanged(self,event):
    200         '''Log each press on a tree item here.
    201         '''
    202         if self.SelectionChanged:
    203             textlist = self._getTreeItemsList(event.GetItem())
    204             if LogInfo['Logging'] and event.GetItem() != self.root:
    205                 textlist[0] = self.GetRelativeHistNum(textlist[0])
    206                 if textlist[0] == "Phases" and len(textlist) > 1:
    207                     textlist[1] = self.GetRelativePhaseNum(textlist[1])
    208                 G2logList.append(TreeLogEntry(textlist))
    209             self.SelectionChanged(event)
    210 
    211     def Bind(self,eventtype,handler,*args,**kwargs):
    212         '''Override the Bind() function so that page change events can be trapped
    213         '''
    214         if eventtype == wx.EVT_TREE_SEL_CHANGED:
    215             self.SelectionChanged = handler
    216             wx.TreeCtrl.Bind(self,eventtype,self.onSelectionChanged)
    217             return
    218         wx.TreeCtrl.Bind(self,eventtype,handler,*args,**kwargs)
    219 
    220     def GetItemPyData(self,*args,**kwargs):
    221         '''Override the standard method to wrap the contents
    222         so that the source can be tracked
    223         '''
    224         data = super(self.__class__,self).GetItemPyData(*args,**kwargs)
    225         textlist = self._getTreeItemsList(args[0])
    226         if type(data) is dict:
    227             return dictLogged(data,textlist)
    228         if type(data) is list:
    229             return listLogged(data,textlist)
    230         if type(data) is tuple: #N.B. tuples get converted to lists
    231             return listLogged(list(data),textlist)
    232         return data
    233 
    234     def ClearDataRepaint(self):
    235         self.repaintAction = None
    236 
    237     def GetRelativeHistNum(self,histname):
    238         '''Returns list with a histogram type and a relative number for that
    239         histogram, or the original string if not a histogram
    240         '''
    241         histtype = histname.split()[0]
    242         if histtype != histtype.upper(): # histograms (only) have a keyword all in caps
    243             return histname
    244         item, cookie = self.GetFirstChild(self.root)
    245         i = 0
    246         while item:
    247             itemtext = self.GetItemText(item)
    248             if itemtext == histname:
    249                 return histtype,i
    250             elif itemtext.split()[0] == histtype:
    251                 i += 1
    252             item, cookie = self.GetNextChild(self.root, cookie)
    253         else:
    254             raise Exception("Histogram not found: "+histname)
    255 
    256     def ConvertRelativeHistNum(self,histtype,histnum):
    257         '''Converts a histogram type and relative histogram number to a
    258         histogram name in the current project
    259         '''
    260         item, cookie = self.GetFirstChild(self.root)
    261         i = 0
    262         while item:
    263             itemtext = self.GetItemText(item)
    264             if itemtext.split()[0] == histtype:
    265                 if i == histnum: return itemtext
    266                 i += 1
    267             item, cookie = self.GetNextChild(self.root, cookie)
    268         else:
    269             raise Exception("Histogram #'+str(histnum)+' of type "+histtype+' not found')
    270        
    271     def GetRelativePhaseNum(self,phasename):
    272         '''Returns a phase number if the string matches a phase name
    273         or else returns the original string
    274         '''
    275         item, cookie = self.GetFirstChild(self.root)
    276         while item:
    277             itemtext = self.GetItemText(item)
    278             if itemtext == "Phases":
    279                 parent = item
    280                 item, cookie = self.GetFirstChild(parent)
    281                 i = 0
    282                 while item:
    283                     itemtext = self.GetItemText(item)
    284                     if itemtext == phasename:
    285                         return i
    286                     item, cookie = self.GetNextChild(parent, cookie)
    287                     i += 1
    288                 else:
    289                     return phasename # not a phase name
    290             item, cookie = self.GetNextChild(self.root, cookie)
    291         else:
    292             raise Exception("No phases found ")
    293 
    294     def ConvertRelativePhaseNum(self,phasenum):
    295         '''Converts relative phase number to a phase name in
    296         the current project
    297         '''
    298         item, cookie = self.GetFirstChild(self.root)
    299         while item:
    300             itemtext = self.GetItemText(item)
    301             if itemtext == "Phases":
    302                 parent = item
    303                 item, cookie = self.GetFirstChild(parent)
    304                 i = 0
    305                 while item:
    306                     if i == phasenum:
    307                         return self.GetItemText(item)
    308                     item, cookie = self.GetNextChild(parent, cookie)
    309                     i += 1
    310                 else:
    311                     raise Exception("Phase "+str(phasenum)+" not found")
    312             item, cookie = self.GetNextChild(self.root, cookie)
    313         else:
    314             raise Exception("No phases found ")
    315                
    316     def RepaintDataWindow(self):
    317         item = self.repaintAction
    318         if isinstance(item,TreeLogEntry):
    319             self.SelectItem(self.root) # need to select something else
    320             self.ReplayTreePress(item)
    321         elif isinstance(item,TabLogEntry):
    322             self.ReplayTabPress(item)
    323            
    324     def ReplayLogItem(self,item):
    325         'Execute an action taken from a log file entry'
    326         if isinstance(item,MenuLogEntry):
    327             self.ReplayMenuCommand(item)
    328         elif isinstance(item,TreeLogEntry):
    329             self.ReplayTreePress(item)
    330             self.repaintAction = item
    331         elif isinstance(item,VarLogEntry):
    332             self.ReplayVariableChange(item)
    333         elif isinstance(item,TabLogEntry):
    334             self.ReplayTabPress(item)
    335             self.repaintAction = item
    336         else:
    337             raise Exception("Unknown object in log: "+str(type(item))+": "
    338                             +str(item))
    339        
    340     def ReplayTreePress(self,logitem):
    341         'Perform a Tree press action when read from the log'
    342         parent = self.root
    343         for i,txt in enumerate(logitem.treeItemList):
    344             if i == 0 and type(txt) is tuple:
    345                 txt = self.ConvertRelativeHistNum(*txt)
    346             elif i == 1 and type(txt) is int and logitem.treeItemList[0] == "Phases":
    347                 txt = self.ConvertRelativePhaseNum(txt)
    348             item = G2gd.GetPatternTreeItemId(self.G2frame,parent,txt)
    349             if not item:
    350                 print 'Not found',txt
    351                 return
    352             else:
    353                 parent = item
    354         else:
    355             self.SelectItem(item)
    356                
    357     def ReplayTabPress(self,logitem):
    358         'Perform a Tab press action when read from the log'
    359         wintitle = logitem.wintitle
    360         tabname = logitem.tablabel
    361         if self.G2frame.dataFrame.GetTitle() != wintitle:
    362             print self.G2frame.dataFrame.GetTitle(),' != ',wintitle
    363             raise Exception('tab in wrong window')
    364         for PageNum in range(self.G2frame.dataDisplay.GetPageCount()):
    365             if tabname == self.G2frame.dataDisplay.GetPageText(PageNum):
    366                 self.G2frame.dataDisplay.SetSelection(PageNum)
    367                 return
    368         else:
    369             print tabname,'not in',[
    370                 self.G2frame.dataDisplay.GetPageText(PageNum) for
    371                 PageNum in range(self.G2frame.dataDisplay.GetPageCount())]
    372             raise Exception('tab not found')
    373     def ReplayVariableChange(self,logitem):
    374         'Perform a Variable Change action, when read from the log'
    375         parentId = self.root
    376         for i,treeitem in enumerate(logitem.treeRefs):
    377             if i == 0 and type(treeitem) is tuple:
    378                 treeitem = self.ConvertRelativeHistNum(*treeitem)
    379             item, cookie = self.GetFirstChild(parentId)
    380             while item:
    381                 if self.GetItemText(item) == treeitem:
    382                     parentId = item
    383                     break
    384                 else:
    385                     item, cookie = self.GetNextChild(parentId, cookie)
    386             else:
    387                 raise Exception("Tree item not found for "+str(logitem))
    388         # get the inner most data array
    389         data = super(self.__class__,self).GetItemPyData(item)
    390         for item in logitem.indexRefs[:-1]:
    391             data = data[item]
    392         # set the value
    393         data[logitem.indexRefs[-1]] = logitem.value
    394     def ReplayMenuCommand(self,logitem):
    395         'Perform a Menu item action when read from the log'
    396         key = ''
    397         for item in logitem.menulabellist:
    398             if key: key += '+'
    399             key += item
    400         if MenuBindingLookup.get(key):
    401             MenuBindingLookup[key](None)
    402         else:
    403             raise Exception('No binding for menu item '+key)       
    404        
    405279#===========================================================================
    406280# variable tracking
     
    446320           |->itemlabel                 |-> sublabel(s)               |-> menulabel
    447321           
    448     :returns: a list containing all the labels (or None)           
     322    :returns: a list containing all the labels and the menuitem object
     323       or None if the menu object will not be cataloged.
    449324    '''
    450325    # don't worry about help menuitems
     
    488363        #raise Exception('debug2: error tracing menuitem')
    489364        return
    490     return menuLabelList
     365    return menuLabelList,menuitem
    491366
    492367def SaveMenuCommand(id,G2frame,handler):
    493368    '''Creates a table of menu items and their pseudo-bindings
    494369    '''
    495     menuLabelList = _getmenuinfo(id,G2frame,handler)
    496     if not menuLabelList: return
     370    menuinfo = _getmenuinfo(id,G2frame,handler)
     371    if not menuinfo: return
     372    menuLabelList,menuobj = menuinfo
    497373    key = ''
    498374    for item in menuLabelList:
    499375        if key: key += '+'
    500376        key += item
    501     MenuBindingLookup[key] = handler
     377    MenuBindingLookup[key] = [handler,id,menuobj]
    502378    return menuLabelList
    503379
     
    515391        if LogInfo['Logging']:
    516392            G2logList.append(MenuLogEntry(menuLabelList))
    517         MenuBindingLookup[key](event)
     393        handler = MenuBindingLookup[key][0]
     394        handler(event)
    518395    else:
    519396        print 'Error no binding for menu command',menuLabelList,'id=',id
     
    536413    return LogInfo['Logging']
    537414
     415def OnReplayPress(event):
     416    'execute one or more commands when the replay button is pressed'
     417    clb = LogInfo['clb']
     418    dlg = clb.GetTopLevelParent()
     419    sels = sorted(clb.GetSelections())
     420    if not sels:
     421        dlg1 = wx.MessageDialog(dlg,
     422            'Select one or more items in the list box to replay',
     423            'No selection actions',
     424            wx.OK)
     425        dlg1.CenterOnParent()
     426        dlg1.ShowModal()
     427        dlg1.Destroy()
     428        return
     429    logstat = ShowLogStatus()
     430    if logstat: LogOff()
     431    if debug: print 70*'='
     432    for i in sels:
     433        i += 1
     434        item = G2logList[i]
     435        if debug: print 'replaying',item
     436        item.Replay()
     437        wx.Yield()
     438    if i >= len(G2logList)-1:
     439         dlg.EndModal(wx.ID_OK)
     440    else:
     441        clb.DeselectAll()
     442        clb.SetSelection(i)
     443        if logstat: LogOn()
     444    if debug: print 70*'='
     445    # if the last command did not display a window, repaint it in
     446    # case something on that window changed.
     447    if item != LogInfo['LastPaintAction'] and hasattr(LogInfo['LastPaintAction'],'Repaint'):
     448        LogInfo['LastPaintAction'].Repaint()
     449     
    538450def ReplayLog(event):
    539     'replay the logged actions (needs to be a wx.widget)'
    540    
    541     LogInfo['G2frame'].OnMacroRecordStatus(None,False) # turn off recording
    542     LogInfo['Tree'].ClearDataRepaint()
    543     print 70*'='
    544     print 'Performing logged actions:'
     451    'replay the logged actions'
     452    LogInfo['LastPaintAction'] = None # clear the pointed to the last data window
     453    # is this really needed? -- probably not.
     454    commandList = []
    545455    for item in G2logList:
    546456        if item: # skip over 1st item in list (None)
    547             print 'replaying',item
    548             LogInfo['Tree'].ReplayLogItem(item)
    549             wx.Yield()
    550     # do repaint here
    551     LogInfo['Tree'].RepaintDataWindow()
    552     print 70*'='
    553    
    554    
    555    
     457            commandList.append(str(item))
     458    if not commandList:
     459        dlg = wx.MessageDialog(LogInfo['Tree'],
     460            'No actions found in log to replay',
     461            'Empty Log',
     462            wx.OK)
     463        dlg.CenterOnParent()
     464        dlg.ShowModal()
     465        dlg.Destroy()
     466        return
     467    dlg = wx.Dialog(LogInfo['Tree'],wx.ID_ANY,'Replay actions from log',
     468        style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.CENTRE)
     469    mainSizer = wx.BoxSizer(wx.VERTICAL)
     470    mainSizer.Add((5,5))
     471    clb = wx.ListBox(dlg, wx.ID_ANY, (30,100), wx.DefaultSize, commandList,
     472                     style=wx.LB_EXTENDED)
     473    LogInfo['clb'] = clb
     474    mainSizer.Add(clb,1,wx.EXPAND,1)
     475    mainSizer.Add((5,5))
     476    btn = wx.Button(dlg, wx.ID_ANY,'Replay selected')
     477    btn.Bind(wx.EVT_BUTTON,OnReplayPress)
     478    mainSizer.Add(btn,0,wx.ALIGN_CENTER,0)
     479    btnsizer = wx.StdDialogButtonSizer()
     480    OKbtn = wx.Button(dlg, wx.ID_OK,'Close')
     481    #OKbtn = wx.Button(dlg, wx.ID_CLOSE)
     482    OKbtn.SetDefault()
     483    OKbtn.Bind(wx.EVT_BUTTON,lambda event: dlg.EndModal(wx.ID_OK))
     484    btnsizer.AddButton(OKbtn)
     485    btnsizer.Realize()
     486    mainSizer.Add((-1,5),1,wx.EXPAND,1)
     487    mainSizer.Add(btnsizer,0,wx.ALIGN_CENTER,0)
     488    mainSizer.Add((-1,5))
     489    dlg.SetSizer(mainSizer)
     490    dlg.CenterOnParent()
     491    clb.SetSelection(0)
     492    dlg.ShowModal()
     493    dlg.Destroy()
     494    return
     495
    556496LogOn() # for debug
Note: See TracChangeset for help on using the changeset viewer.