laurent@367: import wx Laurent@1061: import os, sys, shutil laurent@367: from xml.dom import minidom laurent@367: Edouard@728: from py_ext import PythonFileCTNMixin laurent@367: Edouard@728: class WxGladeHMI(PythonFileCTNMixin): laurent@367: Edouard@717: ConfNodeMethods = [ Edouard@734: {"bitmap" : "editWXGLADE", laurent@367: "name" : _("WXGLADE GUI"), laurent@367: "tooltip" : _("Edit a WxWidgets GUI with WXGlade"), laurent@367: "method" : "_editWXGLADE"}, laurent@367: ] laurent@367: Edouard@728: def ConfNodePath(self): Edouard@728: return os.path.join(os.path.dirname(__file__)) Edouard@728: Laurent@1061: def _getWXGLADEpath(self, project_path=None): Laurent@1061: if project_path is None: Laurent@1061: project_path = self.CTNPath() Laurent@1061: # define name for wxGlade gui file Laurent@1061: return os.path.join(project_path, "hmi.wxg") laurent@367: laurent@367: def launch_wxglade(self, options, wait=False): laurent@367: from wxglade import __file__ as fileName laurent@367: path = os.path.dirname(fileName) laurent@367: glade = os.path.join(path, 'wxglade.py') laurent@367: if wx.Platform == '__WXMSW__': laurent@367: glade = "\"%s\""%glade laurent@367: mode = {False:os.P_NOWAIT, True:os.P_WAIT}[wait] laurent@367: os.spawnv(mode, sys.executable, ["\"%s\""%sys.executable] + [glade] + options) laurent@367: Laurent@1061: def OnCTNSave(self, from_project_path=None): Laurent@1061: if from_project_path is not None: Laurent@1061: shutil.copyfile(self._getWXGLADEpath(from_project_path), Laurent@1061: self._getWXGLADEpath()) Laurent@1061: return PythonFileCTNMixin.OnCTNSave(self, from_project_path) laurent@367: Edouard@718: def CTNGenerate_C(self, buildpath, locations): laurent@367: """ laurent@367: Return C code generated by iec2c compiler laurent@367: when _generate_softPLC have been called laurent@367: @param locations: ignored laurent@367: @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND laurent@367: """ laurent@367: laurent@367: current_location = self.GetCurrentLocation() laurent@367: # define a unique name for the generated C file laurent@367: location_str = "_".join(map(lambda x:str(x), current_location)) laurent@367: laurent@367: runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str) laurent@367: runtimefile = open(runtimefile_path, 'w') laurent@367: laurent@367: hmi_frames = {} laurent@367: laurent@367: wxgfile_path=self._getWXGLADEpath() laurent@367: if os.path.exists(wxgfile_path): laurent@367: wxgfile = open(wxgfile_path, 'r') laurent@367: wxgtree = minidom.parse(wxgfile) laurent@367: wxgfile.close() laurent@367: laurent@367: for node in wxgtree.childNodes[1].childNodes: laurent@367: if node.nodeType == wxgtree.ELEMENT_NODE: laurent@367: hmi_frames[node._attrs["name"].value] = node._attrs["class"].value laurent@367: laurent@367: hmipyfile_path=os.path.join(self._getBuildPath(), "hmi.py") laurent@367: if wx.Platform == '__WXMSW__': laurent@367: wxgfile_path = "\"%s\""%wxgfile_path laurent@384: wxghmipyfile_path = "\"%s\""%hmipyfile_path laurent@384: else: laurent@384: wxghmipyfile_path = hmipyfile_path laurent@384: self.launch_wxglade(['-o', wxghmipyfile_path, '-g', 'python', wxgfile_path], wait=True) laurent@367: laurent@367: hmipyfile = open(hmipyfile_path, 'r') laurent@367: runtimefile.write(hmipyfile.read()) laurent@367: hmipyfile.close() laurent@367: laurent@367: runtimefile.write(self.GetPythonCode()) laurent@367: runtimefile.write(""" laurent@367: %(declare)s laurent@367: Edouard@1014: def _runtime_%(location)s_start(): laurent@367: global %(global)s laurent@367: laurent@367: def OnCloseFrame(evt): laurent@367: wx.MessageBox(_("Please stop PLC to close")) laurent@367: laurent@367: %(init)s laurent@367: Edouard@1014: def _runtime_%(location)s_stop(): laurent@367: global %(global)s laurent@367: laurent@367: %(cleanup)s laurent@367: laurent@367: """ % {"location": location_str, laurent@367: "declare": "\n".join(map(lambda x:"%s = None" % x, hmi_frames.keys())), laurent@367: "global": ",".join(hmi_frames.keys()), laurent@367: "init": "\n".join(map(lambda x: """ laurent@367: %(name)s = %(class)s(None) laurent@367: %(name)s.Bind(wx.EVT_CLOSE, OnCloseFrame) laurent@367: %(name)s.Show() laurent@367: """ % {"name": x[0], "class": x[1]}, laurent@367: hmi_frames.items())), Edouard@1053: "cleanup": "\n ".join(map(lambda x:"if %s is not None: %s.Destroy()" % (x,x), hmi_frames.keys()))}) laurent@367: runtimefile.close() laurent@367: laurent@367: return [], "", False, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb")) laurent@367: laurent@367: def _editWXGLADE(self): laurent@367: wxg_filename = self._getWXGLADEpath() greg@427: open_wxglade = True Edouard@718: if not self.GetCTRoot().CheckProjectPathPerm(): Edouard@718: dialog = wx.MessageDialog(self.GetCTRoot().AppFrame, greg@427: _("You don't have write permissions.\nOpen wxGlade anyway ?"), greg@427: _("Open wxGlade"), greg@427: wx.YES_NO|wx.ICON_QUESTION) greg@427: open_wxglade = dialog.ShowModal() == wx.ID_YES greg@427: dialog.Destroy() greg@427: if open_wxglade: greg@427: if not os.path.exists(wxg_filename): greg@427: hmi_name = self.BaseParams.getName() greg@427: open(wxg_filename,"w").write(""" greg@427: greg@427: greg@427: greg@427: frame_1 laurent@834: laurent@834: wxVERTICAL laurent@834: laurent@834: greg@427: greg@427: greg@427: """ % {"name": hmi_name, "class": "Class_%s" % hmi_name}) greg@427: if wx.Platform == '__WXMSW__': greg@427: wxg_filename = "\"%s\""%wxg_filename greg@427: self.launch_wxglade([wxg_filename]) Laurent@1061: