Package pyforms :: Package web :: Module PyFormsStateMachine
[hide private]
[frames] | no frames]

Source Code for Module pyforms.web.PyFormsStateMachine

  1  import sys, glob, os 
  2  from PyQt4 import uic 
  3  from PyQt4 import QtGui, QtCore 
  4  import pyforms.Utils.tools as tools, time 
  5  import settings 
  6   
  7   
  8  from pyforms.web.BaseWidget import BaseWidget 
  9  from pyforms.web.Controls.ControlPlayer import ControlPlayer 
 10  from pyforms.web.Controls.ControlButton import ControlButton 
 11   
 12  from pyStateMachine.States.State import State, EndState 
 13  from pyStateMachine.StateMachineControllers.StatesController import StatesController 
14 15 16 -def gotoAppState(true=None, false=None, trueParms={}, falseParms={}):
17 def go2decorator(func): 18 def func_wrapper(self, inVar): return func(self, inVar) 19 20 func_wrapper.trueParms = trueParms 21 func_wrapper.falseParms = falseParms 22 func_wrapper.go2StateTrue = true 23 func_wrapper.go2StateFalse = false 24 func_wrapper.label = func.__name__ if func.__doc__==None else '\n'.join([x for x in func.__doc__.replace('\t','').split('\n') if len(x)>0]) 25 return func_wrapper
26 return go2decorator 27
28 29 30 -class PyFormsState(State):
31
32 - def init(self): pass
33
34 - def enter(self, inVar, currentState={}): return inVar
35
36 - def leave(self, inVar, currentState={}): return inVar
37
38 - def execute(self):
39 if self.app!=None and hasattr(self.app, 'execute'): self.app.execute()
40 41 42 @property
43 - def app(self): return self._app if hasattr(self, '_app') else None
44 45 @app.setter
46 - def app(self, value): self._app = value
47 48
49 - def initForm(self):
50 if hasattr(self, 'app') and self.app: self.app.initForm();
51 52 @property
53 - def form(self): return self.app.form if self.app else None
54
55 56 57 58 -class PyFormsStateMachine(StatesController, BaseWidget):
59
60 - def __init__(self, title):
61 BaseWidget.__init__(self, title) 62 StatesController.__init__(self, self.STATES) 63 64 for stateName, state in self.states.items(): 65 if hasattr(state, 'init'): 66 state.init() 67 if hasattr(state, 'app') and state.app: 68 state.app._controlsPrefix = stateName 69 70 self._html = '' 71 self._js = '' 72 73 self._currentIteration = 0
74 75
76 - def initForm(self):
77 image = os.path.join( settings.MEDIA_ROOT, 'statesmachines', '{0}.png'.format( self.__class__.__name__) ) 78 self.exportGraph(image) 79 80 self._controls = [] 81 self._html = '<h3>Application workflow states</h3><br/>' 82 83 # Load the applications 84 for fromStateName, state in reversed( self.states.items() ): 85 if hasattr(state, 'app') and state.app: 86 # Add the instance of the application to the State machine node 87 formset = state.app.formControls.keys() if state.app._formset==None else state.app._formset 88 89 self._html += '<h4 class="statemachine-toggleButton" state="{0}" >{0} <small>({1})</small></h4>'.format(fromStateName, state.app.title) 90 self._html += '<div id="statemachine-{0}-form" style="display:none;" >'.format( fromStateName ) 91 self._html += state.app.generatePanel(formset) 92 self._html += '</div><hr/>' 93 self._controls += state.app._controls 94 95 self._html += '<br/><br/><h3>Application workflow diagram</h3>' 96 self._html += '<img src="/load/{0}/statemachine/diagram/" >'.format(self.__class__.__name__) 97 self._formLoaded = True 98 99 self._js = "\n".join( self._controls ) 100 return { 'title': self._title }
101 102 #def submit(self) 103 104
105 - def iterateStates(self):
106 """ 107 Iterate states - each call go to another level 108 """ 109 if len(self._waitingStates)>0: 110 statesOutputs = [] 111 print self._waitingStates 112 113 #First run all the pending states 114 for fromStateName, toStateName, inputParam in self._waitingStates: 115 state = self._states[toStateName] 116 copyOfCurrentState = dict(self._currentState) 117 118 if isinstance(state, EndState): executionDetails = (toStateName, state, inputParam ) 119 else: 120 p = state.enter(inputParam, copyOfCurrentState) 121 state.execute() 122 outParam = state.leave(p, copyOfCurrentState) 123 executionDetails = (toStateName, state, outParam ) 124 125 statesOutputs.append( executionDetails ) 126 127 #Check the events of each exectuted state: 128 for stateName, state, output in statesOutputs: 129 #Remove the exectued state from the waiting queue 130 self._waitingStates.pop(0) 131 #Check each event 132 for e in state.events: 133 #Select the next state to go 134 go2State = e.go2StateTrue if e(state, output) else e.go2StateFalse 135 #In case the state is None, it stops the state execution 136 if go2State!=None: self._waitingStates.append( [stateName, go2State, output] ) 137 else: self._waitingStates.append( [stateName, 'EndState', output] ) 138 139 "Save the currentState of the iteration" 140 self._currentState = self.__returnCurrentStatesValues() 141 else: 142 print("State machine ended") 143 144 self._currentIteration += 1
145 146 147
148 - def execute(self):
149 # Initiate the parameters set by the user 150 self._currentState = self.returnCurrentStatesValues() 151 152 # Iterate the states execution 153 while not self.ended: self.iterateStates()
154 155
156 - def loadSerializedForm(self, params):
157 158 self._currentIteration = params.get('currentIteration', 0) 159 160 for key, value in params.items(): 161 tmp = key.split('-') 162 if len(tmp)>1: 163 stateName, controlName = tmp 164 self.states[stateName].app.formControls[controlName].value = value 165 elif key in self.formControls: 166 control = self.formControls[key] 167 control.value = value 168 169 if 'event' in params.keys(): 170 tmp = params['event']['control'].split('-') 171 if len(tmp)>1: 172 stateName, controlName = tmp 173 control = self.states[stateName].app.formControls[controlName] 174 func = getattr(control, params['event']['event']) 175 func() 176 else: 177 for key, item in self.formControls.items(): 178 if key==params['event']['control']: 179 func = getattr(item, params['event']['event']) 180 func()
181 182
183 - def serializeForm(self):
184 res = {} 185 for stateName, state in reversed( self.states.items() ): 186 if hasattr(state, 'app') and state.app!=None: 187 res.update( state.app.serializeForm() ) 188 189 for key, item in self.formControls.items(): 190 if isinstance(item, ControlPlayer ): 191 res[item._name] = item.value 192 if item._value!=None and item._value!='': item._value.release() #release any open video 193 elif isinstance(item, ControlButton ): 194 pass 195 else: 196 res[item._name] = item.value 197 198 res['currentIteration'] = self._currentIteration 199 return res
200
201 - def returnCurrentStatesValues(self):
202 """ 203 Iterate all the states and save the values of their controls 204 """ 205 currentState = {} 206 for stateName, state in reversed( self.states.items() ): 207 appState = {} 208 #The state has an application associated to it 209 if hasattr(state, 'app') and state.app: 210 for controlName, control in state.app.formControls.items(): 211 appState[controlName] = control.value 212 currentState[stateName] = appState 213 return currentState
214 215 @property
216 - def currentIteration(self): return self._currentIteration
217
218 219 220 221 222 223 224 225 226 227 228 -def startApp(states):
229 app = QtGui.QApplication(sys.argv) 230 container = Container(states) 231 app.exec_()
232