plugger.py
changeset 427 7ac746c07ff2
parent 423 4d7ac355701d
child 428 ea09f33ce717
equal deleted inserted replaced
426:3f285782ac9b 427:7ac746c07ff2
    72         pass
    72         pass
    73 
    73 
    74 # helper func to get path to images
    74 # helper func to get path to images
    75 def opjimg(imgname):
    75 def opjimg(imgname):
    76     return os.path.join("images",imgname)
    76     return os.path.join("images",imgname)
    77 
    77     
       
    78 # helper func to check path write permission
       
    79 def CheckPathPerm(path):
       
    80     if path is None or not os.path.isdir(path):
       
    81         return False
       
    82     for root, dirs, files in os.walk(path):
       
    83          for name in files:
       
    84              if os.access(root, os.W_OK) is not True or os.access(os.path.join(root, name), os.W_OK) is not True:
       
    85                  return False
       
    86     return True
       
    87     
    78 class PlugTemplate:
    88 class PlugTemplate:
    79     """
    89     """
    80     This class is the one that define plugins.
    90     This class is the one that define plugins.
    81     """
    91     """
    82 
    92 
   179 
   189 
   180     def PlugMakeDir(self):
   190     def PlugMakeDir(self):
   181         os.mkdir(self.PlugPath())
   191         os.mkdir(self.PlugPath())
   182 
   192 
   183     def PlugRequestSave(self):
   193     def PlugRequestSave(self):
   184         # If plugin do not have corresponding directory
   194         if self.GetPlugRoot().CheckProjectPathPerm(False):
   185         plugpath = self.PlugPath()
   195             # If plugin do not have corresponding directory
   186         if not os.path.isdir(plugpath):
   196             plugpath = self.PlugPath()
   187             # Create it
   197             if not os.path.isdir(plugpath):
   188             os.mkdir(plugpath)
   198                 # Create it
   189 
   199                 os.mkdir(plugpath)
   190         # generate XML for base XML parameters controller of the plugin
   200     
   191         if self.MandatoryParams:
   201             # generate XML for base XML parameters controller of the plugin
   192             BaseXMLFile = open(self.PluginBaseXmlFilePath(),'w')
   202             if self.MandatoryParams:
   193             BaseXMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
   203                 BaseXMLFile = open(self.PluginBaseXmlFilePath(),'w')
   194             BaseXMLFile.write(self.MandatoryParams[1].generateXMLText(self.MandatoryParams[0], 0))
   204                 BaseXMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
   195             BaseXMLFile.close()
   205                 BaseXMLFile.write(self.MandatoryParams[1].generateXMLText(self.MandatoryParams[0], 0))
   196         
   206                 BaseXMLFile.close()
   197         # generate XML for XML parameters controller of the plugin
   207             
   198         if self.PlugParams:
   208             # generate XML for XML parameters controller of the plugin
   199             XMLFile = open(self.PluginXmlFilePath(),'w')
   209             if self.PlugParams:
   200             XMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
   210                 XMLFile = open(self.PluginXmlFilePath(),'w')
   201             XMLFile.write(self.PlugParams[1].generateXMLText(self.PlugParams[0], 0))
   211                 XMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
   202             XMLFile.close()
   212                 XMLFile.write(self.PlugParams[1].generateXMLText(self.PlugParams[0], 0))
   203         
   213                 XMLFile.close()
   204         # Call the plugin specific OnPlugSave method
   214             
   205         result = self.OnPlugSave()
   215             # Call the plugin specific OnPlugSave method
   206         if not result:
   216             result = self.OnPlugSave()
   207             return _("Error while saving \"%s\"\n")%self.PlugPath()
   217             if not result:
   208 
   218                 return _("Error while saving \"%s\"\n")%self.PlugPath()
   209         # mark plugin as saved
   219     
   210         self.ChangesToSave = False        
   220             # mark plugin as saved
   211         # go through all childs and do the same
   221             self.ChangesToSave = False
   212         for PlugChild in self.IterChilds():
   222             # go through all childs and do the same
   213             result = PlugChild.PlugRequestSave()
   223             for PlugChild in self.IterChilds():
   214             if result:
   224                 result = PlugChild.PlugRequestSave()
   215                 return result
   225                 if result:
       
   226                     return result
   216         return None
   227         return None
   217     
   228     
   218     def PlugImport(self, src_PlugPath):
   229     def PlugImport(self, src_PlugPath):
   219         shutil.copytree(src_PlugPath, self.PlugPath)
   230         shutil.copytree(src_PlugPath, self.PlugPath)
   220         return True
   231         return True
   688                    "LWORD" :      8,
   699                    "LWORD" :      8,
   689                    "REAL" :       4,
   700                    "REAL" :       4,
   690                    "LREAL" :      8,
   701                    "LREAL" :      8,
   691                   } 
   702                   } 
   692 
   703 
   693 import re
   704 import re, tempfile
   694 import targets
   705 import targets
   695 import connectors
   706 import connectors
   696 from discovery import DiscoveryDialog
   707 from discovery import DiscoveryDialog
   697 from weakref import WeakKeyDictionary
   708 from weakref import WeakKeyDictionary
   698 
   709 
   762         self.PlugParent = None
   773         self.PlugParent = None
   763         # Keep track of the plugin type name
   774         # Keep track of the plugin type name
   764         self.PlugType = "Beremiz"
   775         self.PlugType = "Beremiz"
   765         # After __init__ root plugin is not valid
   776         # After __init__ root plugin is not valid
   766         self.ProjectPath = None
   777         self.ProjectPath = None
   767         self.BuildPath = None
   778         self._setBuildPath(None)
   768         self.DebugThread = None
   779         self.DebugThread = None
   769         self.debug_break = False
   780         self.debug_break = False
   770         self.previous_plcstate = None
   781         self.previous_plcstate = None
   771         self.StatusPrint = {"Broken": self.logger.write_error,
   782         self.StatusPrint = {"Broken": self.logger.write_error,
   772                             None: lambda x: None}
   783                             None: lambda x: None}
   850         
   861         
   851     def SetParamsAttribute(self, path, value):
   862     def SetParamsAttribute(self, path, value):
   852         if path.startswith("BeremizRoot.TargetType.") and self.BeremizRoot.getTargetType().getcontent() is None:
   863         if path.startswith("BeremizRoot.TargetType.") and self.BeremizRoot.getTargetType().getcontent() is None:
   853             self.BeremizRoot.setTargetType(self.GetDefaultTarget())
   864             self.BeremizRoot.setTargetType(self.GetDefaultTarget())
   854         return PlugTemplate.SetParamsAttribute(self, path, value)
   865         return PlugTemplate.SetParamsAttribute(self, path, value)
       
   866         
       
   867     # helper func to check project path write permission
       
   868     def CheckProjectPathPerm(self, dosave=True):
       
   869         if CheckPathPerm(self.ProjectPath):
       
   870             return True
       
   871         dialog = wx.MessageDialog(self.AppFrame, 
       
   872                     _('You must have write permission to work on the project\nWork on a project copy ?'),
       
   873                     _('Error'), 
       
   874                     wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
       
   875         answer = dialog.ShowModal()
       
   876         dialog.Destroy()
       
   877         if answer == wx.ID_YES:
       
   878             if self.SaveProjectAs():
       
   879                 self.AppFrame.RefreshAll()
       
   880                 self.AppFrame.RefreshTitle()
       
   881                 return True
       
   882         return False
   855     
   883     
   856     def NewProject(self, ProjectPath, BuildPath=None):
   884     def NewProject(self, ProjectPath, BuildPath=None):
   857         """
   885         """
   858         Create a new project in an empty folder
   886         Create a new project in an empty folder
   859         @param ProjectPath: path of the folder where project have to be created
   887         @param ProjectPath: path of the folder where project have to be created
   877         # Change XSD into class members
   905         # Change XSD into class members
   878         self._AddParamsMembers()
   906         self._AddParamsMembers()
   879         self.PluggedChilds = {}
   907         self.PluggedChilds = {}
   880         # Keep track of the root plugin (i.e. project path)
   908         # Keep track of the root plugin (i.e. project path)
   881         self.ProjectPath = ProjectPath
   909         self.ProjectPath = ProjectPath
   882         self.BuildPath = BuildPath
   910         self._setBuildPath(BuildPath)
   883         # get plugins bloclist (is that usefull at project creation?)
   911         # get plugins bloclist (is that usefull at project creation?)
   884         self.RefreshPluginsBlockLists()
   912         self.RefreshPluginsBlockLists()
   885         # this will create files base XML files
   913         # this will create files base XML files
   886         self.SaveProject()
   914         self.SaveProject()
   887         return None
   915         return None
   904         # Change XSD into class members
   932         # Change XSD into class members
   905         self._AddParamsMembers()
   933         self._AddParamsMembers()
   906         self.PluggedChilds = {}
   934         self.PluggedChilds = {}
   907         # Keep track of the root plugin (i.e. project path)
   935         # Keep track of the root plugin (i.e. project path)
   908         self.ProjectPath = ProjectPath
   936         self.ProjectPath = ProjectPath
   909         self.BuildPath = BuildPath
   937         self._setBuildPath(BuildPath)
   910         # If dir have already be made, and file exist
   938         # If dir have already be made, and file exist
   911         if os.path.isdir(self.PlugPath()) and os.path.isfile(self.PluginXmlFilePath()):
   939         if os.path.isdir(self.PlugPath()) and os.path.isfile(self.PluginXmlFilePath()):
   912             #Load the plugin.xml file into parameters members
   940             #Load the plugin.xml file into parameters members
   913             result = self.LoadXMLParams()
   941             result = self.LoadXMLParams()
   914             if result:
   942             if result:
   928     def CloseProject(self):
   956     def CloseProject(self):
   929         self.ClearPluggedChilds()
   957         self.ClearPluggedChilds()
   930         self.ResetAppFrame(None)
   958         self.ResetAppFrame(None)
   931         
   959         
   932     def SaveProject(self):
   960     def SaveProject(self):
   933         if not self.SaveXMLFile():
   961         if self.CheckProjectPathPerm(False):
   934             self.SaveXMLFile(os.path.join(self.ProjectPath, 'plc.xml'))
   962             self.SaveXMLFile(os.path.join(self.ProjectPath, 'plc.xml'))
   935         result = self.PlugRequestSave()
   963             result = self.PlugRequestSave()
   936         if result:
   964             if result:
   937             self.logger.write_error(result)
   965                 self.logger.write_error(result)
       
   966     
       
   967     def SaveProjectAs(self, dosave=True):
       
   968         # Ask user to choose a path with write permissions
       
   969         dirdialog = wx.DirDialog(self.AppFrame , _("Choose a directory to save project"), os.getenv("HOME"), wx.DD_NEW_DIR_BUTTON)
       
   970         answer = dirdialog.ShowModal()
       
   971         dirdialog.Destroy()
       
   972         if answer == wx.ID_OK:
       
   973             newprojectpath = dirdialog.GetPath()
       
   974             if os.path.isdir(newprojectpath):
       
   975                 self.ProjectPath = newprojectpath
       
   976                 if dosave:
       
   977                     self.SaveProject()
       
   978                 self._setBuildPath(self.BuildPath)
       
   979                 return True
       
   980         return False
   938     
   981     
   939     # Update PLCOpenEditor Plugin Block types from loaded plugins
   982     # Update PLCOpenEditor Plugin Block types from loaded plugins
   940     def RefreshPluginsBlockLists(self):
   983     def RefreshPluginsBlockLists(self):
   941         if getattr(self, "PluggedChilds", None) is not None:
   984         if getattr(self, "PluggedChilds", None) is not None:
   942             self.ClearPluginTypes()
   985             self.ClearPluginTypes()
   969         return os.path.join(self.PlugPath(PlugName), "beremiz.xml")
  1012         return os.path.join(self.PlugPath(PlugName), "beremiz.xml")
   970 
  1013 
   971     def ParentsBlockTypesFactory(self):
  1014     def ParentsBlockTypesFactory(self):
   972         return self.BlockTypesFactory()
  1015         return self.BlockTypesFactory()
   973 
  1016 
       
  1017     def _setBuildPath(self, buildpath):
       
  1018         if CheckPathPerm(buildpath):
       
  1019             self.BuildPath = buildpath
       
  1020         else:
       
  1021             self.BuildPath = None
       
  1022         self.BuildPath = buildpath
       
  1023         self.DefaultBuildPath = None
       
  1024         if self._builder is not None:
       
  1025             self._builder.SetBuildPath(self._getBuildPath())
       
  1026 
   974     def _getBuildPath(self):
  1027     def _getBuildPath(self):
   975         if self.BuildPath is None:
  1028         # BuildPath is defined by user
   976             return os.path.join(self.ProjectPath, "build")
  1029         if self.BuildPath is not None:
   977         return self.BuildPath
  1030             return self.BuildPath
       
  1031         # BuildPath isn't defined by user but already created by default
       
  1032         if self.DefaultBuildPath is not None:
       
  1033             return self.DefaultBuildPath
       
  1034         # Create a build path in project folder if user has permissions
       
  1035         if CheckPathPerm(self.ProjectPath):
       
  1036             self.DefaultBuildPath = os.path.join(self.ProjectPath, "build")
       
  1037         # Create a build path in temp folder
       
  1038         else:
       
  1039             self.DefaultBuildPath = os.path.join(tempfile.mkdtemp(), os.path.basename(self.ProjectPath), "build")
       
  1040             
       
  1041         if not os.path.exists(self.DefaultBuildPath):
       
  1042             os.makedirs(self.DefaultBuildPath)
       
  1043         return self.DefaultBuildPath
   978     
  1044     
   979     def _getExtraFilesPath(self):
  1045     def _getExtraFilesPath(self):
   980         return os.path.join(self._getBuildPath(), "extra_files")
  1046         return os.path.join(self._getBuildPath(), "extra_files")
   981 
  1047 
   982     def _getIECcodepath(self):
  1048     def _getIECcodepath(self):