ProjectController.py
changeset 738 413946c04c87
parent 737 7b421e080636
child 740 cee825fbe9b3
equal deleted inserted replaced
737:7b421e080636 738:413946c04c87
    14 
    14 
    15 import targets
    15 import targets
    16 import connectors
    16 import connectors
    17 from util import MiniTextControler, opjimg, CheckPathPerm, GetClassImporter
    17 from util import MiniTextControler, opjimg, CheckPathPerm, GetClassImporter
    18 from util.ProcessLogger import ProcessLogger
    18 from util.ProcessLogger import ProcessLogger
    19 from PLCControler import PLCControler 
    19 from PLCControler import PLCControler
    20 from PLCOpenEditor import ProjectDialog
    20 from PLCOpenEditor import CWD
    21 from TextViewer import TextViewer
    21 from TextViewer import TextViewer
    22 from plcopen.structures import IEC_KEYWORDS
    22 from plcopen.structures import IEC_KEYWORDS
    23 from targets.typemapping import DebugTypesSize
    23 from targets.typemapping import DebugTypesSize
    24 from util.discovery import DiscoveryDialog
    24 from util.discovery import DiscoveryDialog
    25 from ConfigTreeNode import ConfigTreeNode
    25 from ConfigTreeNode import ConfigTreeNode
       
    26 from ProjectNodeEditor import ProjectNodeEditor
    26 
    27 
    27 base_folder = os.path.split(sys.path[0])[0]
    28 base_folder = os.path.split(sys.path[0])[0]
    28 
    29 
    29 MATIEC_ERROR_MODEL = re.compile(".*\.st:(\d+)-(\d+)\.\.(\d+)-(\d+): error : (.*)$")
    30 MATIEC_ERROR_MODEL = re.compile(".*\.st:(\d+)-(\d+)\.\.(\d+)-(\d+): error : (.*)$")
    30 
    31 
    31 DEBUG_RETRIES_WARN = 3
    32 DEBUG_RETRIES_WARN = 3
    32 DEBUG_RETRIES_REREGISTER = 4
    33 DEBUG_RETRIES_REREGISTER = 4
       
    34 
       
    35 ITEM_CONFNODE = 25
    33 
    36 
    34 class ProjectController(ConfigTreeNode, PLCControler):
    37 class ProjectController(ConfigTreeNode, PLCControler):
    35     """
    38     """
    36     This class define Root object of the confnode tree. 
    39     This class define Root object of the confnode tree. 
    37     It is responsible of :
    40     It is responsible of :
    71           <xsd:attribute name="Disable_Extensions" type="xsd:boolean" use="optional" default="false"/>
    74           <xsd:attribute name="Disable_Extensions" type="xsd:boolean" use="optional" default="false"/>
    72         </xsd:complexType>
    75         </xsd:complexType>
    73       </xsd:element>
    76       </xsd:element>
    74     </xsd:schema>
    77     </xsd:schema>
    75     """
    78     """
    76 
    79     EditorType = ProjectNodeEditor
       
    80     
    77     def __init__(self, frame, logger):
    81     def __init__(self, frame, logger):
    78         PLCControler.__init__(self)
    82         PLCControler.__init__(self)
    79 
    83 
    80         self.MandatoryParams = None
    84         self.MandatoryParams = None
    81         self.SetAppFrame(frame, logger)
    85         self.SetAppFrame(frame, logger)
    97         # root have no parent
   101         # root have no parent
    98         self.CTNParent = None
   102         self.CTNParent = None
    99         # Keep track of the confnode type name
   103         # Keep track of the confnode type name
   100         self.CTNType = "Beremiz"
   104         self.CTNType = "Beremiz"
   101         self.Children = {}
   105         self.Children = {}
       
   106         self._View = None
   102         # After __init__ root confnode is not valid
   107         # After __init__ root confnode is not valid
   103         self.ProjectPath = None
   108         self.ProjectPath = None
   104         self._setBuildPath(None)
   109         self._setBuildPath(None)
   105         self.DebugThread = None
   110         self.DebugThread = None
   106         self.debug_break = False
   111         self.debug_break = False
   119 
   124 
   120     def __del__(self):
   125     def __del__(self):
   121         if self.DebugTimer:
   126         if self.DebugTimer:
   122             self.DebugTimer.cancel()
   127             self.DebugTimer.cancel()
   123         self.KillDebugThread()
   128         self.KillDebugThread()
   124 
   129     
   125     def SetAppFrame(self, frame, logger):
   130     def SetAppFrame(self, frame, logger):
   126         self.AppFrame = frame
   131         self.AppFrame = frame
   127         self.logger = logger
   132         self.logger = logger
   128         self.StatusTimer = None
   133         self.StatusTimer = None
   129         
   134         
   141             self.StatusTimer = None
   146             self.StatusTimer = None
   142             self.AppFrame = None
   147             self.AppFrame = None
   143         
   148         
   144         self.logger = logger
   149         self.logger = logger
   145 
   150 
       
   151     def CTNName(self):
       
   152         return "Project"
       
   153 
   146     def CTNTestModified(self):
   154     def CTNTestModified(self):
   147          return self.ChangesToSave or not self.ProjectIsSaved()
   155          return self.ChangesToSave or not self.ProjectIsSaved()
   148 
   156 
   149     def CTNFullName(self):
   157     def CTNFullName(self):
   150         return ""
   158         return ""
   170     def GetProjectPath(self):
   178     def GetProjectPath(self):
   171         return self.ProjectPath
   179         return self.ProjectPath
   172 
   180 
   173     def GetProjectName(self):
   181     def GetProjectName(self):
   174         return os.path.split(self.ProjectPath)[1]
   182         return os.path.split(self.ProjectPath)[1]
       
   183     
       
   184     def GetIconPath(self):
       
   185         return os.path.join(CWD, "Images", "PROJECT.png")
   175     
   186     
   176     def GetDefaultTargetName(self):
   187     def GetDefaultTargetName(self):
   177         if wx.Platform == '__WXMSW__':
   188         if wx.Platform == '__WXMSW__':
   178             return "Win32"
   189             return "Win32"
   179         else:
   190         else:
   210                     wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
   221                     wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
   211         answer = dialog.ShowModal()
   222         answer = dialog.ShowModal()
   212         dialog.Destroy()
   223         dialog.Destroy()
   213         if answer == wx.ID_YES:
   224         if answer == wx.ID_YES:
   214             if self.SaveProjectAs():
   225             if self.SaveProjectAs():
   215                 self.AppFrame.RefreshAll()
       
   216                 self.AppFrame.RefreshTitle()
   226                 self.AppFrame.RefreshTitle()
   217                 self.AppFrame.RefreshFileMenu()
   227                 self.AppFrame.RefreshFileMenu()
       
   228                 self.AppFrame.RefreshPageTitles()
   218                 return True
   229                 return True
   219         return False
   230         return False
   220     
   231     
   221     def NewProject(self, ProjectPath, BuildPath=None):
   232     def NewProject(self, ProjectPath, BuildPath=None):
   222         """
   233         """
   226         """
   237         """
   227         # Verify that chosen folder is empty
   238         # Verify that chosen folder is empty
   228         if not os.path.isdir(ProjectPath) or len(os.listdir(ProjectPath)) > 0:
   239         if not os.path.isdir(ProjectPath) or len(os.listdir(ProjectPath)) > 0:
   229             return _("Chosen folder isn't empty. You can't use it for a new project!")
   240             return _("Chosen folder isn't empty. You can't use it for a new project!")
   230         
   241         
   231         dialog = ProjectDialog(self.AppFrame)
       
   232         if dialog.ShowModal() == wx.ID_OK:
       
   233             values = dialog.GetValues()
       
   234             values["creationDateTime"] = datetime(*localtime()[:6])
       
   235             dialog.Destroy()
       
   236         else:
       
   237             dialog.Destroy()
       
   238             return _("Project not created")
       
   239         
       
   240         # Create PLCOpen program
   242         # Create PLCOpen program
   241         self.CreateNewProject(values)
   243         self.CreateNewProject(
       
   244             {"projectName": _("Unnamed"),
       
   245              "productName": _("Unnamed"),
       
   246              "productVersion": _("1"),
       
   247              "companyName": _("Unknown"),
       
   248              "creationDateTime": datetime(*localtime()[:6])})
       
   249         self.ProjectAddConfiguration("config")
       
   250         self.ProjectAddConfigurationResource("config", "resource1")
       
   251         
   242         # Change XSD into class members
   252         # Change XSD into class members
   243         self._AddParamsMembers()
   253         self._AddParamsMembers()
   244         self.Children = {}
   254         self.Children = {}
   245         # Keep track of the root confnode (i.e. project path)
   255         # Keep track of the root confnode (i.e. project path)
   246         self.ProjectPath = ProjectPath
   256         self.ProjectPath = ProjectPath
   287 
   297 
   288         if os.path.isfile(self._getIECrawcodepath()):
   298         if os.path.isfile(self._getIECrawcodepath()):
   289             self.ShowMethod("_showIECcode", True)
   299             self.ShowMethod("_showIECcode", True)
   290 
   300 
   291         return None
   301         return None
       
   302     
       
   303     def RecursiveConfNodeInfos(self, confnode):
       
   304         values = []
       
   305         for CTNChild in confnode.IECSortedChildren():
       
   306             values.append(
       
   307                 {"name": "%s: %s" % (CTNChild.GetFullIEC_Channel(),
       
   308                                      CTNChild.CTNName()), 
       
   309                  "type": ITEM_CONFNODE, 
       
   310                  "confnode": CTNChild,
       
   311                  "icon": CTNChild.GetIconPath(),
       
   312                  "values": self.RecursiveConfNodeInfos(CTNChild)})
       
   313         return values
       
   314     
       
   315     def GetProjectInfos(self):
       
   316         infos = PLCControler.GetProjectInfos(self)
       
   317         configurations = infos["values"].pop(-1)
       
   318         resources = None
       
   319         for config_infos in configurations["values"]:
       
   320             if resources is None:
       
   321                 resources = config_infos["values"][0]
       
   322             else:
       
   323                 resources["values"].extend(config_infos["values"][0]["values"])
       
   324         if resources is not None:
       
   325             infos["values"].append(resources)
       
   326         infos["values"].extend(self.RecursiveConfNodeInfos(self))
       
   327         return infos
   292     
   328     
   293     def CloseProject(self):
   329     def CloseProject(self):
   294         self.ClearChildren()
   330         self.ClearChildren()
   295         self.ResetAppFrame(None)
   331         self.ResetAppFrame(None)
   296         
   332         
   904             self.AppFrame.EditProjectElement(IEC_code_viewer, name)
   940             self.AppFrame.EditProjectElement(IEC_code_viewer, name)
   905             
   941             
   906             return IEC_code_viewer
   942             return IEC_code_viewer
   907         
   943         
   908         elif name == "IEC raw code":
   944         elif name == "IEC raw code":
   909             controler = MiniTextControler(self._getIECrawcodepath())
   945             controler = MiniTextControler.MiniTextControler(self._getIECrawcodepath())
   910             IEC_raw_code_viewer = TextViewer(self.AppFrame.TabsOpened, "", None, controler, instancepath=name)
   946             IEC_raw_code_viewer = TextViewer(self.AppFrame.TabsOpened, "", None, controler, instancepath=name)
   911             #IEC_raw_code_viewer.Enable(False)
   947             #IEC_raw_code_viewer.Enable(False)
   912             IEC_raw_code_viewer.SetTextSyntax("ALL")
   948             IEC_raw_code_viewer.SetTextSyntax("ALL")
   913             IEC_raw_code_viewer.SetKeywords(IEC_KEYWORDS)
   949             IEC_raw_code_viewer.SetKeywords(IEC_KEYWORDS)
   914             IEC_raw_code_viewer.RefreshView()
   950             IEC_raw_code_viewer.RefreshView()
   916                 
   952                 
   917             self.AppFrame.EditProjectElement(IEC_raw_code_viewer, name)
   953             self.AppFrame.EditProjectElement(IEC_raw_code_viewer, name)
   918 
   954 
   919             return IEC_raw_code_viewer
   955             return IEC_raw_code_viewer
   920         
   956         
   921         return None
   957         else:
       
   958             return ConfigTreeNode._OpenView(self, name)
   922 
   959 
   923     def _Clean(self):
   960     def _Clean(self):
   924         if os.path.isdir(os.path.join(self._getBuildPath())):
   961         if os.path.isdir(os.path.join(self._getBuildPath())):
   925             self.logger.write(_("Cleaning the build directory\n"))
   962             self.logger.write(_("Cleaning the build directory\n"))
   926             shutil.rmtree(os.path.join(self._getBuildPath()))
   963             shutil.rmtree(os.path.join(self._getBuildPath()))
   969             
  1006             
   970             status = _(self.previous_plcstate)
  1007             status = _(self.previous_plcstate)
   971             {"Broken": self.logger.write_error,
  1008             {"Broken": self.logger.write_error,
   972              None: lambda x: None}.get(
  1009              None: lambda x: None}.get(
   973                 self.previous_plcstate, self.logger.write)(_("PLC is %s\n")%status)
  1010                 self.previous_plcstate, self.logger.write)(_("PLC is %s\n")%status)
   974             self.AppFrame.RefreshAll()
  1011             self.AppFrame.RefreshStatusToolBar()
   975         
  1012         
   976     def RegisterDebugVarToConnector(self):
  1013     def RegisterDebugVarToConnector(self):
   977         self.DebugTimer=None
  1014         self.DebugTimer=None
   978         Idxs = []
  1015         Idxs = []
   979         self.TracedIECPath = []
  1016         self.TracedIECPath = []
  1337             else:
  1374             else:
  1338                 self.logger.write_error(_("No PLC to transfer (did build succeed ?)\n"))
  1375                 self.logger.write_error(_("No PLC to transfer (did build succeed ?)\n"))
  1339 
  1376 
  1340         wx.CallAfter(self.UpdateMethodsFromPLCStatus)
  1377         wx.CallAfter(self.UpdateMethodsFromPLCStatus)
  1341 
  1378 
  1342     ConfNodeMethods = [
  1379     StatusMethods = [
  1343         {"bitmap" : "Build",
  1380         {"bitmap" : "Build",
  1344          "name" : _("Build"),
  1381          "name" : _("Build"),
  1345          "tooltip" : _("Build project into build folder"),
  1382          "tooltip" : _("Build project into build folder"),
  1346          "method" : "_Build"},
  1383          "method" : "_Build"},
  1347         {"bitmap" : "Clean",
  1384         {"bitmap" : "Clean",
  1376         {"bitmap" : "ShowIECcode",
  1413         {"bitmap" : "ShowIECcode",
  1377          "name" : _("Show code"),
  1414          "name" : _("Show code"),
  1378          "shown" : False,
  1415          "shown" : False,
  1379          "tooltip" : _("Show IEC code generated by PLCGenerator"),
  1416          "tooltip" : _("Show IEC code generated by PLCGenerator"),
  1380          "method" : "_showIECcode"},
  1417          "method" : "_showIECcode"},
       
  1418     ]
       
  1419 
       
  1420     ConfNodeMethods = [
  1381         {"bitmap" : "editIECrawcode",
  1421         {"bitmap" : "editIECrawcode",
  1382          "name" : _("Raw IEC code"),
  1422          "name" : _("Raw IEC code"),
  1383          "tooltip" : _("Edit raw IEC code added to code generated by PLCGenerator"),
  1423          "tooltip" : _("Edit raw IEC code added to code generated by PLCGenerator"),
  1384          "method" : "_editIECrawcode"},
  1424          "method" : "_editIECrawcode"},
  1385     ]
  1425     ]
       
  1426 
       
  1427 
       
  1428     def EnableMethod(self, method, value):
       
  1429         for d in self.StatusMethods:
       
  1430             if d["method"]==method:
       
  1431                 d["enabled"]=value
       
  1432                 return True
       
  1433         return False
       
  1434 
       
  1435     def ShowMethod(self, method, value):
       
  1436         for d in self.StatusMethods:
       
  1437             if d["method"]==method:
       
  1438                 d["shown"]=value
       
  1439                 return True
       
  1440         return False
       
  1441 
       
  1442     def CallMethod(self, method):
       
  1443         for d in self.StatusMethods:
       
  1444             if d["method"]==method and d.get("enabled", True) and d.get("shown", True):
       
  1445                 getattr(self, method)()