wxglade_hmi/wxglade_hmi.py
author Andrey Skvortsov <andrej.skvortzov@gmail.com>
Mon, 18 Apr 2016 18:56:51 +0300
changeset 1478 69fe0b81e951
parent 1256 02a710c7b5ed
child 1511 91538d0c242c
permissions -rw-r--r--
make attribute CFLAGS and LDFLAGS optional and add default empty value

Actually CFLAGS and LDFLAGS are not required and can be empty.
Without default empty value if target platform in project settings was
set to "Linux" CFLAGS and LDFLAGS was initialized with NoneType.
The result was broken build and it wasn't to save/load project with
such settings.

Traceback (most recent call last):
File "/home/developer/WorkData/PLC/beremiz/beremiz/ProjectController.py", line 956, in _Build
if not builder.build() :
File "/home/developer/WorkData/PLC/beremiz/beremiz/targets/toolchain_gcc.py", line 96, in build
Builder_CFLAGS = ' '.join(self.getBuilderCFLAGS())
TypeError: sequence item 0: expected string, NoneType found
import wx
import os, sys, shutil
from xml.dom import minidom

from py_ext import PythonFileCTNMixin

class WxGladeHMI(PythonFileCTNMixin):

    ConfNodeMethods = [
        {"bitmap" : "editWXGLADE",
         "name" : _("WXGLADE GUI"),
         "tooltip" : _("Edit a WxWidgets GUI with WXGlade"),
         "method" : "_editWXGLADE"},
    ]

    def GetIconName(self):
        return "wxGlade"

    def ConfNodePath(self):
        return os.path.join(os.path.dirname(__file__))

    def _getWXGLADEpath(self, project_path=None):
        if project_path is None:
            project_path = self.CTNPath()
        # define name for wxGlade gui file
        return os.path.join(project_path, "hmi.wxg")

    def launch_wxglade(self, options, wait=False):
        from wxglade import __file__ as fileName
        path = os.path.dirname(fileName)
        glade = os.path.join(path, 'wxglade.py')
        if wx.Platform == '__WXMSW__':
            glade = "\"%s\""%glade
        mode = {False:os.P_NOWAIT, True:os.P_WAIT}[wait]
        os.spawnv(mode, sys.executable, ["\"%s\""%sys.executable] + [glade] + options)

    def OnCTNSave(self, from_project_path=None):
        if from_project_path is not None:
            shutil.copyfile(self._getWXGLADEpath(from_project_path),
                            self._getWXGLADEpath())
        return PythonFileCTNMixin.OnCTNSave(self, from_project_path)

    def CTNGenerate_C(self, buildpath, locations):
        
        hmi_frames = []
        
        wxgfile_path=self._getWXGLADEpath()
        if os.path.exists(wxgfile_path):
            wxgfile = open(wxgfile_path, 'r')
            wxgtree = minidom.parse(wxgfile)
            wxgfile.close()
            
            for node in wxgtree.childNodes[1].childNodes:
                if node.nodeType == wxgtree.ELEMENT_NODE:
                    hmi_frames.append({
                        "name" : node.getAttribute("name"),
                        "class" : node.getAttribute("class"),
                        "handlers" : [
                            hnode.firstChild.data for hnode in 
                            node.getElementsByTagName("handler")]})
                    
            hmipyfile_path=os.path.join(self._getBuildPath(), "hmi.py")
            if wx.Platform == '__WXMSW__':
                wxgfile_path = "\"%s\""%wxgfile_path
                wxghmipyfile_path = "\"%s\""%hmipyfile_path
            else:
                wxghmipyfile_path = hmipyfile_path
            self.launch_wxglade(['-o', wxghmipyfile_path, '-g', 'python', wxgfile_path], wait=True)
            
            hmipyfile = open(hmipyfile_path, 'r')
            define_hmi = hmipyfile.read().decode('utf-8')
            hmipyfile.close()
        
        else:
            define_hmi = ""
        
        declare_hmi = "\n".join(["%(name)s = None\n" % x + 
                          "\n".join(["%(class)s.%(h)s = %(h)s"%
                            dict(x,h=h) for h in x['handlers']])
                                for x in hmi_frames])
        global_hmi = ("global %s\n"%",".join(
                         [x["name"] for x in hmi_frames]) 
                      if len(hmi_frames) > 0 else "")
        init_hmi = "\n".join(["""\
def OnCloseFrame(evt):
    wx.MessageBox(_("Please stop PLC to close"))

%(name)s = %(class)s(None)
%(name)s.Bind(wx.EVT_CLOSE, OnCloseFrame)
%(name)s.Show()
""" % x for x in hmi_frames])
        cleanup_hmi = "\n".join(
            ["if %(name)s is not None: %(name)s.Destroy()" % x 
                for x in hmi_frames])
        
        self.PreSectionsTexts = {
            "globals":define_hmi,
            "start":global_hmi,
            "stop":global_hmi + cleanup_hmi
        }
        self.PostSectionsTexts = {
            "globals":declare_hmi,
            "start":init_hmi,
        }

        return PythonFileCTNMixin.CTNGenerate_C(self, buildpath, locations)

    def _editWXGLADE(self):
        wxg_filename = self._getWXGLADEpath()
        open_wxglade = True
        if not self.GetCTRoot().CheckProjectPathPerm():
            dialog = wx.MessageDialog(self.GetCTRoot().AppFrame,
                                      _("You don't have write permissions.\nOpen wxGlade anyway ?"),
                                      _("Open wxGlade"),
                                      wx.YES_NO|wx.ICON_QUESTION)
            open_wxglade = dialog.ShowModal() == wx.ID_YES
            dialog.Destroy()
        if open_wxglade:
            if not os.path.exists(wxg_filename):
                hmi_name = self.BaseParams.getName()
                open(wxg_filename,"w").write("""<?xml version="1.0"?>
    <application path="" name="" class="" option="0" language="python" top_window="%(name)s" encoding="UTF-8" use_gettext="0" overwrite="0" use_new_namespace="1" for_version="2.8" is_template="0">
        <object class="%(class)s" name="%(name)s" base="EditFrame">
            <style>wxDEFAULT_FRAME_STYLE</style>
            <title>frame_1</title>
            <object class="wxBoxSizer" name="sizer_1" base="EditBoxSizer">
                <orient>wxVERTICAL</orient>
            <object class="sizerslot" />
        </object>
        </object>
    </application>
    """ % {"name": hmi_name, "class": "Class_%s" % hmi_name})
            if wx.Platform == '__WXMSW__':
                wxg_filename = "\"%s\""%wxg_filename
            self.launch_wxglade([wxg_filename])