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