laurent@366: import wx
laurent@366: import os
laurent@366: import modules
laurent@366: from plugger import PlugTemplate, opjimg
laurent@654: from PLCControler import UndoBuffer
laurent@657: from PythonEditor import PythonEditor
laurent@366: 
laurent@366: from xml.dom import minidom
laurent@366: from xmlclass import *
laurent@366: import cPickle
laurent@366: 
laurent@366: PythonClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "python_xsd.xsd")) 
laurent@366: 
laurent@366: class PythonCodeTemplate:
laurent@366:     
laurent@657:     EditorType = PythonEditor
laurent@657:     
laurent@366:     def __init__(self):
laurent@366:         
laurent@366:         self.PluginMethods.insert(0, 
laurent@366:                 {"bitmap" : opjimg("editPYTHONcode"),
laurent@366:                  "name" : _("Edit Python File"), 
laurent@366:                  "tooltip" : _("Edit Python File"),
laurent@366:                  "method" : "_OpenView"},
laurent@366:         )
laurent@366: 
laurent@366:         filepath = self.PythonFileName()
laurent@366:         
laurent@366:         self.PythonCode = PythonClasses["Python"]()
laurent@366:         if os.path.isfile(filepath):
laurent@366:             xmlfile = open(filepath, 'r')
laurent@366:             tree = minidom.parse(xmlfile)
laurent@366:             xmlfile.close()
laurent@366:             
laurent@366:             for child in tree.childNodes:
laurent@366:                 if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "Python":
laurent@366:                     self.PythonCode.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"])
laurent@657:                     self.CreatePythonBuffer(True)
laurent@366:         else:
laurent@657:             self.CreatePythonBuffer(False)
laurent@366:             self.OnPlugSave()
laurent@366: 
laurent@366:     def PluginPath(self):
laurent@366:         return os.path.join(self.PlugParent.PluginPath(), "modules", self.PlugType)
laurent@366: 
laurent@366:     def PythonFileName(self):
laurent@366:         return os.path.join(self.PlugPath(), "python.xml")
laurent@366: 
laurent@366:     def GetFilename(self):
laurent@366:         if self.PythonBuffer.IsCurrentSaved():
laurent@366:             return "python"
laurent@366:         else:
laurent@366:             return "~python~"
laurent@366: 
laurent@366:     def SetPythonCode(self, text):
laurent@366:         self.PythonCode.settext(text)
laurent@366:         
laurent@366:     def GetPythonCode(self):
laurent@366:         return self.PythonCode.gettext()
laurent@366:     
laurent@657:     def PlugTestModified(self):
laurent@657:         return self.ChangesToSave or not self.PythonIsSaved()
laurent@366:     
laurent@366:     def OnPlugSave(self):
laurent@366:         filepath = self.PythonFileName()
laurent@366:         
laurent@366:         text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
laurent@366:         extras = {"xmlns":"http://www.w3.org/2001/XMLSchema",
laurent@366:                   "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
laurent@366:                   "xsi:schemaLocation" : "python_xsd.xsd"}
laurent@366:         text += self.PythonCode.generateXMLText("Python", 0, extras)
laurent@366: 
laurent@366:         xmlfile = open(filepath,"w")
laurent@430:         xmlfile.write(text.encode("utf-8"))
laurent@366:         xmlfile.close()
laurent@366:         
laurent@657:         self.MarkPythonAsSaved()
laurent@366:         return True
laurent@366:         
laurent@366: #-------------------------------------------------------------------------------
laurent@366: #                      Current Buffering Management Functions
laurent@366: #-------------------------------------------------------------------------------
laurent@366: 
laurent@366:     """
laurent@366:     Return a copy of the project
laurent@366:     """
laurent@366:     def Copy(self, model):
laurent@366:         return cPickle.loads(cPickle.dumps(model))
laurent@366: 
laurent@657:     def CreatePythonBuffer(self, saved):
laurent@657:         self.Buffering = False
laurent@657:         self.PythonBuffer = UndoBuffer(cPickle.dumps(self.PythonCode), saved)
laurent@657: 
laurent@366:     def BufferPython(self):
laurent@657:         self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode))
laurent@366:     
laurent@366:     def StartBuffering(self):
laurent@366:         self.Buffering = True
laurent@366:         
laurent@366:     def EndBuffering(self):
laurent@366:         if self.Buffering:
laurent@657:             self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode))
laurent@366:             self.Buffering = False
laurent@366:     
laurent@657:     def MarkPythonAsSaved(self):
laurent@657:         self.EndBuffering()
laurent@657:         self.PythonBuffer.CurrentSaved()
laurent@657:     
laurent@657:     def PythonIsSaved(self):
laurent@657:         return self.PythonBuffer.IsCurrentSaved() and not self.Buffering
laurent@657:         
laurent@366:     def LoadPrevious(self):
laurent@657:         self.EndBuffering()
laurent@657:         self.PythonCode = cPickle.loads(self.PythonBuffer.Previous())
laurent@366:     
laurent@366:     def LoadNext(self):
laurent@657:         self.PythonCode = cPickle.loads(self.PythonBuffer.Next())
laurent@366:     
laurent@366:     def GetBufferState(self):
laurent@657:         first = self.PythonBuffer.IsFirst() and not self.Buffering
laurent@366:         last = self.PythonBuffer.IsLast()
laurent@366:         return not first, not last
laurent@366: 
laurent@366: def _GetClassFunction(name):
laurent@366:     def GetRootClass():
laurent@366:         __import__("plugins.python.modules." + name)
laurent@366:         return getattr(modules, name).RootClass
laurent@366:     return GetRootClass
laurent@366: 
laurent@366: class RootClass(PythonCodeTemplate):
laurent@366: 
laurent@366:     # For root object, available Childs Types are modules of the modules packages.
laurent@366:     PlugChildsTypes = [(name, _GetClassFunction(name), help) for name, help in zip(modules.__all__,modules.helps)]
laurent@366:     
laurent@366:     def PluginPath(self):
laurent@366:         return os.path.join(self.PlugParent.PluginPath(), self.PlugType)
laurent@366:     
laurent@366:     def PlugGenerate_C(self, buildpath, locations):
laurent@366:         """
laurent@366:         Generate C code
laurent@366:         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
laurent@366:         @param locations: List of complete variables locations \
laurent@366:             [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
laurent@366:             "NAME" : name of the variable (generally "__IW0_1_2" style)
laurent@366:             "DIR" : direction "Q","I" or "M"
laurent@366:             "SIZE" : size "X", "B", "W", "D", "L"
laurent@366:             "LOC" : tuple of interger for IEC location (0,1,2,...)
laurent@366:             }, ...]
laurent@366:         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
laurent@366:         """
laurent@366:         current_location = self.GetCurrentLocation()
laurent@366:         # define a unique name for the generated C file
laurent@366:         location_str = "_".join(map(lambda x:str(x), current_location))
laurent@366:         
laurent@366:         plugin_root = self.GetPlugRoot()
laurent@366:         plugin_root.GetIECProgramsAndVariables()
laurent@366:         
laurent@366:         plc_python_filepath = os.path.join(os.path.split(__file__)[0], "plc_python.c")
laurent@366:         plc_python_file = open(plc_python_filepath, 'r')
laurent@366:         plc_python_code = plc_python_file.read()
laurent@366:         plc_python_file.close()
laurent@366:         python_eval_fb_list = []
laurent@367:         for v in plugin_root._VariablesList:
laurent@366:             if v["vartype"] == "FB" and v["type"] in ["PYTHON_EVAL","PYTHON_POLL"]:
laurent@366:                 python_eval_fb_list.append(v)
laurent@366:         python_eval_fb_count = max(1, len(python_eval_fb_list))
laurent@366:         
laurent@366:         # prepare python code
laurent@366:         plc_python_code = plc_python_code % {
laurent@366:            "python_eval_fb_count": python_eval_fb_count,
laurent@366:            "location": location_str}
laurent@366:         
laurent@366:         Gen_Pythonfile_path = os.path.join(buildpath, "python_%s.c"%location_str)
laurent@366:         pythonfile = open(Gen_Pythonfile_path,'w')
laurent@366:         pythonfile.write(plc_python_code)
laurent@366:         pythonfile.close()
laurent@366:         
laurent@366:         runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
laurent@366:         runtimefile = open(runtimefile_path, 'w')
laurent@366:         runtimefile.write(self.GetPythonCode())
laurent@366:         runtimefile.close()
laurent@366:         
greg@418:         matiec_flags = '"-I%s"'%os.path.abspath(self.GetPlugRoot().GetIECLibPath())
laurent@366:         
laurent@366:         return [(Gen_Pythonfile_path, matiec_flags)], "", True, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb"))