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 |
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)() |