# HG changeset patch
# User Edouard Tisserant
# Date 1336409249 -7200
# Node ID 1c23952dbde1d9f366432c4253f593e15a4234c7
# Parent 180e4a7d945ce442f31394959521c1adb878d9f4
refactoring
diff -r 180e4a7d945c -r 1c23952dbde1 Beremiz.py
--- a/Beremiz.py Thu May 03 19:02:34 2012 +0200
+++ b/Beremiz.py Mon May 07 18:47:29 2012 +0200
@@ -146,13 +146,13 @@
import TextCtrlAutoComplete, cPickle
from BrowseValuesLibraryDialog import BrowseValuesLibraryDialog
import types, time, re, platform, time, traceback, commands
-from plugger import PluginsRoot, MiniTextControler, MATIEC_ERROR_MODEL
+from ConfigTree import ConfigTreeRoot, MiniTextControler, MATIEC_ERROR_MODEL
from wxPopen import ProcessLogger
from docutils import *
from PLCOpenEditor import IDEFrame, AppendMenu, TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, TYPESTREE, INSTANCESTREE, LIBRARYTREE, SCALING, PAGETITLES, USE_AUI
from PLCOpenEditor import EditorPanel, Viewer, TextViewer, GraphicViewer, ResourceEditor, ConfigurationEditor, DataTypeEditor
-from PLCControler import LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
+from PLCControler import LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
SCROLLBAR_UNIT = 10
WINDOW_COLOUR = wx.Colour(240,240,240)
@@ -378,18 +378,18 @@
[ID_FILEMENURECENTPROJECTS,
] = [wx.NewId() for _init_ctrls in range(1)]
-PLUGINMENU_POSITION = 3
+CONFNODEMENU_POSITION = 3
class Beremiz(IDEFrame):
def _init_coll_MenuBar_Menus(self, parent):
IDEFrame._init_coll_MenuBar_Menus(self, parent)
- parent.Insert(pos=PLUGINMENU_POSITION,
- menu=self.PluginMenu, title=_(u'&Plugin'))
+ parent.Insert(pos=CONFNODEMENU_POSITION,
+ menu=self.ConfNodeMenu, title=_(u'&ConfNode'))
def _init_utils(self):
- self.PluginMenu = wx.Menu(title='')
+ self.ConfNodeMenu = wx.Menu(title='')
self.RecentProjectsMenu = wx.Menu(title='')
IDEFrame._init_utils(self)
@@ -451,25 +451,25 @@
def _init_coll_PLCConfigMainSizer_Items(self, parent):
parent.AddSizer(self.PLCParamsSizer, 0, border=10, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
- parent.AddSizer(self.PluginTreeSizer, 0, border=10, flag=wx.BOTTOM|wx.LEFT|wx.RIGHT)
+ parent.AddSizer(self.ConfNodeTreeSizer, 0, border=10, flag=wx.BOTTOM|wx.LEFT|wx.RIGHT)
def _init_coll_PLCConfigMainSizer_Growables(self, parent):
parent.AddGrowableCol(0)
parent.AddGrowableRow(1)
- def _init_coll_PluginTreeSizer_Growables(self, parent):
+ def _init_coll_ConfNodeTreeSizer_Growables(self, parent):
parent.AddGrowableCol(0)
parent.AddGrowableCol(1)
def _init_beremiz_sizers(self):
self.PLCConfigMainSizer = wx.FlexGridSizer(cols=1, hgap=2, rows=2, vgap=2)
self.PLCParamsSizer = wx.BoxSizer(wx.VERTICAL)
- #self.PluginTreeSizer = wx.FlexGridSizer(cols=3, hgap=0, rows=0, vgap=2)
- self.PluginTreeSizer = wx.FlexGridSizer(cols=2, hgap=0, rows=0, vgap=2)
+ #self.ConfNodeTreeSizer = wx.FlexGridSizer(cols=3, hgap=0, rows=0, vgap=2)
+ self.ConfNodeTreeSizer = wx.FlexGridSizer(cols=2, hgap=0, rows=0, vgap=2)
self._init_coll_PLCConfigMainSizer_Items(self.PLCConfigMainSizer)
self._init_coll_PLCConfigMainSizer_Growables(self.PLCConfigMainSizer)
- self._init_coll_PluginTreeSizer_Growables(self.PluginTreeSizer)
+ self._init_coll_ConfNodeTreeSizer_Growables(self.ConfNodeTreeSizer)
self.PLCConfig.SetSizer(self.PLCConfigMainSizer)
@@ -485,8 +485,8 @@
("Build", wx.WXK_F11)]:
def OnMethodGen(obj,meth):
def OnMethod(evt):
- if obj.PluginRoot is not None:
- obj.PluginRoot.CallMethod('_'+meth)
+ if obj.CTR is not None:
+ obj.CTR.CallMethod('_'+meth)
wx.CallAfter(self.RefreshAll)
return OnMethod
newid = wx.NewId()
@@ -516,7 +516,7 @@
self._init_beremiz_sizers()
- def __init__(self, parent, projectOpen=None, buildpath=None, plugin_root=None, debug=True):
+ def __init__(self, parent, projectOpen=None, buildpath=None, ctr=None, debug=True):
IDEFrame.__init__(self, parent, debug)
self.Log = LogPseudoFile(self.LogConsole,self.RiseLogConsole)
@@ -530,7 +530,7 @@
self.LastPanelSelected = None
- self.PluginInfos = {}
+ self.ConfNodeInfos = {}
# Define Tree item icon list
self.LocationImageList = wx.ImageList(16, 16)
@@ -538,7 +538,7 @@
# Icons for location items
for imgname, itemtype in [
- ("CONFIGURATION", LOCATION_PLUGIN),
+ ("CONFIGURATION", LOCATION_CONFNODE),
("RESOURCE", LOCATION_MODULE),
("PROGRAM", LOCATION_GROUP),
("VAR_INPUT", LOCATION_VAR_INPUT),
@@ -555,9 +555,9 @@
projectOpen = None
if projectOpen is not None and os.path.isdir(projectOpen):
- self.PluginRoot = PluginsRoot(self, self.Log)
- self.Controler = self.PluginRoot
- result = self.PluginRoot.LoadProject(projectOpen, buildpath)
+ self.CTR = ConfigTreeRoot(self, self.Log)
+ self.Controler = self.CTR
+ result = self.CTR.LoadProject(projectOpen, buildpath)
if not result:
self.LibraryPanel.SetControler(self.Controler)
self.RefreshConfigRecentProjects(os.path.abspath(projectOpen))
@@ -567,19 +567,19 @@
self.ResetView()
self.ShowErrorMessage(result)
else:
- self.PluginRoot = plugin_root
- self.Controler = plugin_root
- if plugin_root is not None:
+ self.CTR = ctr
+ self.Controler = ctr
+ if ctr is not None:
self.LibraryPanel.SetControler(self.Controler)
self._Refresh(TYPESTREE, INSTANCESTREE, LIBRARYTREE)
self.RefreshAll()
if self.EnableDebug:
- self.DebugVariablePanel.SetDataProducer(self.PluginRoot)
+ self.DebugVariablePanel.SetDataProducer(self.CTR)
self.Bind(wx.EVT_CLOSE, self.OnCloseFrame)
self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU)
- self.RefreshPluginMenu()
+ self.RefreshConfNodeMenu()
self.LogConsole.SetFocus()
def RiseLogConsole(self):
@@ -587,9 +587,9 @@
def RefreshTitle(self):
name = _("Beremiz")
- if self.PluginRoot is not None:
- projectname = self.PluginRoot.GetProjectName()
- if self.PluginRoot.ProjectTestModified():
+ if self.CTR is not None:
+ projectname = self.CTR.GetProjectName()
+ if self.CTR.ProjectTestModified():
projectname = "~%s~" % projectname
self.SetTitle("%s - %s" % (name, projectname))
else:
@@ -640,20 +640,20 @@
event.Skip()
def SearchLineForError(self):
- if self.PluginRoot is not None:
+ if self.CTR is not None:
text = self.LogConsole.GetRange(0, self.LogConsole.GetInsertionPoint())
line = self.LogConsole.GetLineText(len(text.splitlines()) - 1)
result = MATIEC_ERROR_MODEL.match(line)
if result is not None:
first_line, first_column, last_line, last_column, error = result.groups()
- infos = self.PluginRoot.ShowError(self.Log,
+ infos = self.CTR.ShowError(self.Log,
(int(first_line), int(first_column)),
(int(last_line), int(last_column)))
## Function displaying an Error dialog in PLCOpenEditor.
# @return False if closing cancelled.
def CheckSaveBeforeClosing(self, title=_("Close Project")):
- if self.PluginRoot.ProjectTestModified():
+ if self.CTR.ProjectTestModified():
dialog = wx.MessageDialog(self,
_("There are changes, do you want to save?"),
title,
@@ -661,7 +661,7 @@
answer = dialog.ShowModal()
dialog.Destroy()
if answer == wx.ID_YES:
- self.PluginRoot.SaveProject()
+ self.CTR.SaveProject()
elif answer == wx.ID_CANCEL:
return False
return True
@@ -674,33 +674,33 @@
ResourceEditor,
ConfigurationEditor,
DataTypeEditor))):
- return ("plugin", tab.Controler.PlugFullName())
+ return ("confnode", tab.Controler.PlugFullName())
elif (isinstance(tab, TextViewer) and
(tab.Controler is None or isinstance(tab.Controler, MiniTextControler))):
- return ("plugin", None, tab.GetInstancePath())
+ return ("confnode", None, tab.GetInstancePath())
else:
return IDEFrame.GetTabInfos(self, tab)
def LoadTab(self, notebook, page_infos):
- if page_infos[0] == "plugin":
+ if page_infos[0] == "confnode":
if page_infos[1] is None:
- plugin = self.PluginRoot
+ confnode = self.CTR
else:
- plugin = self.PluginRoot.GetChildByName(page_infos[1])
- return notebook.GetPageIndex(plugin._OpenView(*page_infos[2:]))
+ confnode = self.CTR.GetChildByName(page_infos[1])
+ return notebook.GetPageIndex(confnode._OpenView(*page_infos[2:]))
else:
return IDEFrame.LoadTab(self, notebook, page_infos)
def OnCloseFrame(self, event):
- if self.PluginRoot is None or self.CheckSaveBeforeClosing(_("Close Application")):
- if self.PluginRoot is not None:
- self.PluginRoot.KillDebugThread()
+ if self.CTR is None or self.CheckSaveBeforeClosing(_("Close Application")):
+ if self.CTR is not None:
+ self.CTR.KillDebugThread()
self.KillLocalRuntime()
self.SaveLastState()
- if self.PluginRoot is not None:
- project_path = os.path.realpath(self.PluginRoot.GetProjectPath())
+ if self.CTR is not None:
+ project_path = os.path.realpath(self.CTR.GetProjectPath())
else:
project_path = ""
self.Config.Write("currenteditedproject", project_path)
@@ -732,7 +732,7 @@
self.RefreshRecentProjectsMenu()
MenuToolBar = self.Panes["MenuToolBar"]
- if self.PluginRoot is not None:
+ if self.CTR is not None:
selected = self.TabsOpened.GetSelection()
if selected >= 0:
graphic_viewer = isinstance(self.TabsOpened.GetPage(selected), Viewer)
@@ -754,7 +754,7 @@
self.FileMenu.Enable(wx.ID_PRINT, False)
MenuToolBar.EnableTool(wx.ID_PRINT, False)
self.FileMenu.Enable(wx.ID_PAGE_SETUP, True)
- project_modified = self.PluginRoot.ProjectTestModified()
+ project_modified = self.CTR.ProjectTestModified()
self.FileMenu.Enable(wx.ID_SAVE, project_modified)
MenuToolBar.EnableTool(wx.ID_SAVE, project_modified)
self.FileMenu.Enable(wx.ID_SAVEAS, True)
@@ -789,7 +789,7 @@
def GenerateOpenRecentProjectFunction(self, projectpath):
def OpenRecentProject(event):
- if self.PluginRoot is not None and not self.CheckSaveBeforeClosing():
+ if self.CTR is not None and not self.CheckSaveBeforeClosing():
return
self.OpenProject(projectpath)
@@ -810,28 +810,28 @@
if callback is not None:
self.Bind(wx.EVT_MENU, callback, id=id)
- def RefreshPluginMenu(self):
- if self.PluginRoot is not None:
+ def RefreshConfNodeMenu(self):
+ if self.CTR is not None:
selected = self.TabsOpened.GetSelection()
if selected >= 0:
panel = self.TabsOpened.GetPage(selected)
else:
panel = None
if panel != self.LastPanelSelected:
- for i in xrange(self.PluginMenu.GetMenuItemCount()):
- item = self.PluginMenu.FindItemByPosition(0)
- self.PluginMenu.Delete(item.GetId())
+ for i in xrange(self.ConfNodeMenu.GetMenuItemCount()):
+ item = self.ConfNodeMenu.FindItemByPosition(0)
+ self.ConfNodeMenu.Delete(item.GetId())
self.LastPanelSelected = panel
if panel is not None:
- items = panel.GetPluginMenuItems()
+ items = panel.GetConfNodeMenuItems()
else:
items = []
- self.MenuBar.EnableTop(PLUGINMENU_POSITION, len(items) > 0)
- self.GenerateMenuRecursive(items, self.PluginMenu)
+ self.MenuBar.EnableTop(CONFNODEMENU_POSITION, len(items) > 0)
+ self.GenerateMenuRecursive(items, self.ConfNodeMenu)
if panel is not None:
- panel.RefreshPluginMenu(self.PluginMenu)
- else:
- self.MenuBar.EnableTop(PLUGINMENU_POSITION, False)
+ panel.RefreshConfNodeMenu(self.ConfNodeMenu)
+ else:
+ self.MenuBar.EnableTop(CONFNODEMENU_POSITION, False)
self.MenuBar.UpdateMenus()
def RefreshScrollBars(self):
@@ -850,15 +850,15 @@
self.Freeze()
self.ClearSizer(self.PLCParamsSizer)
- if self.PluginRoot is not None:
+ if self.CTR is not None:
plcwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1))
- if self.PluginRoot.PlugTestModified():
+ if self.CTR.PlugTestModified():
bkgdclr = CHANGED_TITLE_COLOUR
else:
bkgdclr = TITLE_COLOUR
- if self.PluginRoot not in self.PluginInfos:
- self.PluginInfos[self.PluginRoot] = {"right_visible" : False}
+ if self.CTR not in self.ConfNodeInfos:
+ self.ConfNodeInfos[self.CTR] = {"right_visible" : False}
plcwindow.SetBackgroundColour(TITLE_COLOUR)
plcwindow.Bind(wx.EVT_LEFT_DOWN, self.OnPanelLeftDown)
@@ -869,15 +869,15 @@
st = wx.StaticText(plcwindow, -1)
st.SetFont(wx.Font(faces["size"], wx.DEFAULT, wx.NORMAL, wx.BOLD, faceName = faces["helv"]))
- st.SetLabel(self.PluginRoot.GetProjectName())
+ st.SetLabel(self.CTR.GetProjectName())
plcwindowsizer.AddWindow(st, 0, border=5, flag=wx.ALL|wx.ALIGN_CENTER)
addbutton_id = wx.NewId()
addbutton = wx.lib.buttons.GenBitmapButton(id=addbutton_id, bitmap=wx.Bitmap(Bpath( 'images', 'Add.png')),
- name='AddPluginButton', parent=plcwindow, pos=wx.Point(0, 0),
+ name='AddConfNodeButton', parent=plcwindow, pos=wx.Point(0, 0),
size=wx.Size(16, 16), style=wx.NO_BORDER)
- addbutton.SetToolTipString(_("Add a sub plugin"))
- addbutton.Bind(wx.EVT_BUTTON, self.Gen_AddPluginMenu(self.PluginRoot), id=addbutton_id)
+ addbutton.SetToolTipString(_("Add a sub confnode"))
+ addbutton.Bind(wx.EVT_BUTTON, self.Gen_AddConfNodeMenu(self.CTR), id=addbutton_id)
plcwindowsizer.AddWindow(addbutton, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER)
plcwindowmainsizer = wx.BoxSizer(wx.VERTICAL)
@@ -886,7 +886,7 @@
plcwindowbuttonsizer = wx.BoxSizer(wx.HORIZONTAL)
plcwindowmainsizer.AddSizer(plcwindowbuttonsizer, 0, border=0, flag=wx.ALIGN_CENTER)
- msizer = self.GenerateMethodButtonSizer(self.PluginRoot, plcwindow, not self.PluginInfos[self.PluginRoot]["right_visible"])
+ msizer = self.GenerateMethodButtonSizer(self.CTR, plcwindow, not self.ConfNodeInfos[self.CTR]["right_visible"])
plcwindowbuttonsizer.AddSizer(msizer, 0, border=0, flag=wx.GROW)
paramswindow = wx.Panel(plcwindow, -1, size=wx.Size(-1, -1), style=wx.TAB_TRAVERSAL)
@@ -897,10 +897,10 @@
psizer = wx.BoxSizer(wx.HORIZONTAL)
paramswindow.SetSizer(psizer)
- plugin_infos = self.PluginRoot.GetParamsAttributes()
- self.RefreshSizerElement(paramswindow, psizer, self.PluginRoot, plugin_infos, None, False)
-
- if not self.PluginInfos[self.PluginRoot]["right_visible"]:
+ confnode_infos = self.CTR.GetParamsAttributes()
+ self.RefreshSizerElement(paramswindow, psizer, self.CTR, confnode_infos, None, False)
+
+ if not self.ConfNodeInfos[self.CTR]["right_visible"]:
paramswindow.Hide()
minimizebutton_id = wx.NewId()
@@ -909,7 +909,7 @@
size=wx.Size(24, 24), style=wx.NO_BORDER)
make_genbitmaptogglebutton_flat(minimizebutton)
minimizebutton.SetBitmapSelected(wx.Bitmap(Bpath( 'images', 'Minimize.png')))
- minimizebutton.SetToggle(self.PluginInfos[self.PluginRoot]["right_visible"])
+ minimizebutton.SetToggle(self.ConfNodeInfos[self.CTR]["right_visible"])
plcwindowbuttonsizer.AddWindow(minimizebutton, 0, border=5, flag=wx.ALL)
def togglewindow(event):
@@ -918,32 +918,32 @@
msizer.SetCols(1)
else:
paramswindow.Hide()
- msizer.SetCols(len(self.PluginRoot.PluginMethods))
- self.PluginInfos[self.PluginRoot]["right_visible"] = minimizebutton.GetToggle()
+ msizer.SetCols(len(self.CTR.ConfNodeMethods))
+ self.ConfNodeInfos[self.CTR]["right_visible"] = minimizebutton.GetToggle()
self.PLCConfigMainSizer.Layout()
self.RefreshScrollBars()
event.Skip()
minimizebutton.Bind(wx.EVT_BUTTON, togglewindow, id=minimizebutton_id)
- self.PluginInfos[self.PluginRoot]["main"] = plcwindow
- self.PluginInfos[self.PluginRoot]["params"] = paramswindow
+ self.ConfNodeInfos[self.CTR]["main"] = plcwindow
+ self.ConfNodeInfos[self.CTR]["params"] = paramswindow
self.PLCConfigMainSizer.Layout()
self.RefreshScrollBars()
self.Thaw()
- def GenerateEnableButton(self, parent, sizer, plugin):
- enabled = plugin.PlugEnabled()
+ def GenerateEnableButton(self, parent, sizer, confnode):
+ enabled = confnode.PlugEnabled()
if enabled is not None:
enablebutton_id = wx.NewId()
enablebutton = wx.lib.buttons.GenBitmapToggleButton(id=enablebutton_id, bitmap=wx.Bitmap(Bpath( 'images', 'Disabled.png')),
name='EnableButton', parent=parent, size=wx.Size(16, 16), pos=wx.Point(0, 0), style=0)#wx.NO_BORDER)
- enablebutton.SetToolTipString(_("Enable/Disable this plugin"))
+ enablebutton.SetToolTipString(_("Enable/Disable this confnode"))
make_genbitmaptogglebutton_flat(enablebutton)
enablebutton.SetBitmapSelected(wx.Bitmap(Bpath( 'images', 'Enabled.png')))
enablebutton.SetToggle(enabled)
def toggleenablebutton(event):
- res = self.SetPluginParamsAttribute(plugin, "BaseParams.Enabled", enablebutton.GetToggle())
+ res = self.SetConfNodeParamsAttribute(confnode, "BaseParams.Enabled", enablebutton.GetToggle())
enablebutton.SetToggle(res)
event.Skip()
enablebutton.Bind(wx.EVT_BUTTON, toggleenablebutton, id=enablebutton_id)
@@ -951,23 +951,23 @@
else:
sizer.AddSpacer(wx.Size(16, 16))
- def GenerateMethodButtonSizer(self, plugin, parent, horizontal = True):
+ def GenerateMethodButtonSizer(self, confnode, parent, horizontal = True):
normal_bt_font=wx.Font(faces["size"] / 3, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = faces["helv"])
mouseover_bt_font=wx.Font(faces["size"] / 3, wx.DEFAULT, wx.NORMAL, wx.NORMAL, underline=True, faceName = faces["helv"])
if horizontal:
- msizer = wx.FlexGridSizer(cols=len(plugin.PluginMethods))
+ msizer = wx.FlexGridSizer(cols=len(confnode.ConfNodeMethods))
else:
msizer = wx.FlexGridSizer(cols=1)
- for plugin_method in plugin.PluginMethods:
- if "method" in plugin_method and plugin_method.get("shown",True):
+ for confnode_method in confnode.ConfNodeMethods:
+ if "method" in confnode_method and confnode_method.get("shown",True):
id = wx.NewId()
- label = plugin_method["name"]
+ label = confnode_method["name"]
button = GenBitmapTextButton(id=id, parent=parent,
- bitmap=wx.Bitmap(Bpath( "%s.png"%plugin_method.get("bitmap", os.path.join("images", "Unknown")))), label=label,
+ bitmap=wx.Bitmap(Bpath( "%s.png"%confnode_method.get("bitmap", os.path.join("images", "Unknown")))), label=label,
name=label, pos=wx.DefaultPosition, style=wx.NO_BORDER)
button.SetFont(normal_bt_font)
- button.SetToolTipString(plugin_method["tooltip"])
- button.Bind(wx.EVT_BUTTON, self.GetButtonCallBackFunction(plugin, plugin_method["method"]), id=id)
+ button.SetToolTipString(confnode_method["tooltip"])
+ button.Bind(wx.EVT_BUTTON, self.GetButtonCallBackFunction(confnode, confnode_method["method"]), id=id)
# a fancy underline on mouseover
def setFontStyle(b, s):
def fn(event):
@@ -978,12 +978,12 @@
button.Bind(wx.EVT_ENTER_WINDOW, setFontStyle(button, mouseover_bt_font))
button.Bind(wx.EVT_LEAVE_WINDOW, setFontStyle(button, normal_bt_font))
#hack to force size to mini
- if not plugin_method.get("enabled",True):
+ if not confnode_method.get("enabled",True):
button.Disable()
msizer.AddWindow(button, 0, border=0, flag=wx.ALIGN_CENTER)
return msizer
- def GenerateParamsPanel(self, plugin, bkgdclr, top_offset=0):
+ def GenerateParamsPanel(self, confnode, bkgdclr, top_offset=0):
rightwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1))
rightwindow.SetBackgroundColour(bkgdclr)
@@ -995,7 +995,7 @@
rightwindowsizer.AddGrowableRow(0)
rightwindowmainsizer.AddSizer(rightwindowsizer, 0, border=0, flag=wx.GROW)
- msizer = self.GenerateMethodButtonSizer(plugin, rightwindow, not self.PluginInfos[plugin]["right_visible"])
+ msizer = self.GenerateMethodButtonSizer(confnode, rightwindow, not self.ConfNodeInfos[confnode]["right_visible"])
rightwindowsizer.AddSizer(msizer, 0, border=top_offset, flag=wx.TOP|wx.GROW)
rightparamssizer = wx.BoxSizer(wx.HORIZONTAL)
@@ -1006,15 +1006,15 @@
psizer = wx.BoxSizer(wx.VERTICAL)
paramswindow.SetSizer(psizer)
- self.PluginInfos[plugin]["params"] = paramswindow
+ self.ConfNodeInfos[confnode]["params"] = paramswindow
rightparamssizer.AddWindow(paramswindow, 0, border=5, flag=wx.ALL)
- plugin_infos = plugin.GetParamsAttributes()
- if len(plugin_infos) > 0:
- self.RefreshSizerElement(paramswindow, psizer, plugin, plugin_infos, None, False)
-
- if not self.PluginInfos[plugin]["right_visible"]:
+ confnode_infos = confnode.GetParamsAttributes()
+ if len(confnode_infos) > 0:
+ self.RefreshSizerElement(paramswindow, psizer, confnode, confnode_infos, None, False)
+
+ if not self.ConfNodeInfos[confnode]["right_visible"]:
paramswindow.Hide()
rightminimizebutton_id = wx.NewId()
@@ -1023,7 +1023,7 @@
size=wx.Size(24, 24), style=wx.NO_BORDER)
make_genbitmaptogglebutton_flat(rightminimizebutton)
rightminimizebutton.SetBitmapSelected(wx.Bitmap(Bpath( 'images', 'Minimize.png')))
- rightminimizebutton.SetToggle(self.PluginInfos[plugin]["right_visible"])
+ rightminimizebutton.SetToggle(self.ConfNodeInfos[confnode]["right_visible"])
rightparamssizer.AddWindow(rightminimizebutton, 0, border=5, flag=wx.ALL)
def togglerightwindow(event):
@@ -1032,8 +1032,8 @@
msizer.SetCols(1)
else:
rightparamssizer.Hide(0)
- msizer.SetCols(len(plugin.PluginMethods))
- self.PluginInfos[plugin]["right_visible"] = rightminimizebutton.GetToggle()
+ msizer.SetCols(len(confnode.ConfNodeMethods))
+ self.ConfNodeInfos[confnode]["right_visible"] = rightminimizebutton.GetToggle()
self.PLCConfigMainSizer.Layout()
self.RefreshScrollBars()
event.Skip()
@@ -1042,58 +1042,58 @@
return rightwindow
- def RefreshPluginTree(self):
+ def RefreshConfNodeTree(self):
self.Freeze()
- self.ClearSizer(self.PluginTreeSizer)
- if self.PluginRoot is not None:
- for child in self.PluginRoot.IECSortedChilds():
+ self.ClearSizer(self.ConfNodeTreeSizer)
+ if self.CTR is not None:
+ for child in self.CTR.IECSortedChilds():
self.GenerateTreeBranch(child)
- if not self.PluginInfos[child]["expanded"]:
- self.CollapsePlugin(child)
+ if not self.ConfNodeInfos[child]["expanded"]:
+ self.CollapseConfNode(child)
self.PLCConfigMainSizer.Layout()
self.RefreshScrollBars()
self.Thaw()
- def SetPluginParamsAttribute(self, plugin, *args, **kwargs):
- res, StructChanged = plugin.SetParamsAttribute(*args, **kwargs)
+ def SetConfNodeParamsAttribute(self, confnode, *args, **kwargs):
+ res, StructChanged = confnode.SetParamsAttribute(*args, **kwargs)
if StructChanged:
- wx.CallAfter(self.RefreshPluginTree)
- else:
- if plugin == self.PluginRoot:
+ wx.CallAfter(self.RefreshConfNodeTree)
+ else:
+ if confnode == self.CTR:
bkgdclr = CHANGED_TITLE_COLOUR
items = ["main", "params"]
else:
bkgdclr = CHANGED_WINDOW_COLOUR
items = ["left", "right", "params"]
for i in items:
- self.PluginInfos[plugin][i].SetBackgroundColour(bkgdclr)
- self.PluginInfos[plugin][i].Refresh()
+ self.ConfNodeInfos[confnode][i].SetBackgroundColour(bkgdclr)
+ self.ConfNodeInfos[confnode][i].Refresh()
self._Refresh(TITLE, FILEMENU)
return res
- def ExpandPlugin(self, plugin, force = False):
- for child in self.PluginInfos[plugin]["children"]:
- self.PluginInfos[child]["left"].Show()
- self.PluginInfos[child]["right"].Show()
- if force or self.PluginInfos[child]["expanded"]:
- self.ExpandPlugin(child, force)
+ def ExpandConfNode(self, confnode, force = False):
+ for child in self.ConfNodeInfos[confnode]["children"]:
+ self.ConfNodeInfos[child]["left"].Show()
+ self.ConfNodeInfos[child]["right"].Show()
+ if force or self.ConfNodeInfos[child]["expanded"]:
+ self.ExpandConfNode(child, force)
if force:
- self.PluginInfos[child]["expanded"] = True
- locations_infos = self.PluginInfos[plugin].get("locations_infos", None)
+ self.ConfNodeInfos[child]["expanded"] = True
+ locations_infos = self.ConfNodeInfos[confnode].get("locations_infos", None)
if locations_infos is not None:
if force or locations_infos["root"]["expanded"]:
self.ExpandLocation(locations_infos, "root", force)
if force:
locations_infos["root"]["expanded"] = True
- def CollapsePlugin(self, plugin, force = False):
- for child in self.PluginInfos[plugin]["children"]:
- self.PluginInfos[child]["left"].Hide()
- self.PluginInfos[child]["right"].Hide()
- self.CollapsePlugin(child, force)
+ def CollapseConfNode(self, confnode, force = False):
+ for child in self.ConfNodeInfos[confnode]["children"]:
+ self.ConfNodeInfos[child]["left"].Hide()
+ self.ConfNodeInfos[child]["right"].Hide()
+ self.CollapseConfNode(child, force)
if force:
- self.PluginInfos[child]["expanded"] = False
- locations_infos = self.PluginInfos[plugin].get("locations_infos", None)
+ self.ConfNodeInfos[child]["expanded"] = False
+ locations_infos = self.ConfNodeInfos[confnode].get("locations_infos", None)
if locations_infos is not None:
self.CollapseLocation(locations_infos, "root", force)
if force:
@@ -1129,30 +1129,30 @@
if locations_infos["root"]["left"] is not None and refresh_size:
self.RefreshTreeCtrlSize(locations_infos["root"]["left"])
- def GenerateTreeBranch(self, plugin):
+ def GenerateTreeBranch(self, confnode):
leftwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1))
- if plugin.PlugTestModified():
+ if confnode.PlugTestModified():
bkgdclr=CHANGED_WINDOW_COLOUR
else:
bkgdclr=WINDOW_COLOUR
leftwindow.SetBackgroundColour(bkgdclr)
- if not self.PluginInfos.has_key(plugin):
- self.PluginInfos[plugin] = {"expanded" : False, "right_visible" : False}
-
- self.PluginInfos[plugin]["children"] = plugin.IECSortedChilds()
- plugin_locations = []
- if len(self.PluginInfos[plugin]["children"]) == 0:
- plugin_locations = plugin.GetVariableLocationTree()["children"]
- if not self.PluginInfos[plugin].has_key("locations_infos"):
- self.PluginInfos[plugin]["locations_infos"] = {"root": {"expanded" : False}}
-
- self.PluginInfos[plugin]["locations_infos"]["root"]["left"] = None
- self.PluginInfos[plugin]["locations_infos"]["root"]["right"] = None
- self.PluginInfos[plugin]["locations_infos"]["root"]["children"] = []
-
- self.PluginTreeSizer.AddWindow(leftwindow, 0, border=0, flag=wx.GROW)
+ if not self.ConfNodeInfos.has_key(confnode):
+ self.ConfNodeInfos[confnode] = {"expanded" : False, "right_visible" : False}
+
+ self.ConfNodeInfos[confnode]["children"] = confnode.IECSortedChilds()
+ confnode_locations = []
+ if len(self.ConfNodeInfos[confnode]["children"]) == 0:
+ confnode_locations = confnode.GetVariableLocationTree()["children"]
+ if not self.ConfNodeInfos[confnode].has_key("locations_infos"):
+ self.ConfNodeInfos[confnode]["locations_infos"] = {"root": {"expanded" : False}}
+
+ self.ConfNodeInfos[confnode]["locations_infos"]["root"]["left"] = None
+ self.ConfNodeInfos[confnode]["locations_infos"]["root"]["right"] = None
+ self.ConfNodeInfos[confnode]["locations_infos"]["root"]["children"] = []
+
+ self.ConfNodeTreeSizer.AddWindow(leftwindow, 0, border=0, flag=wx.GROW)
leftwindowsizer = wx.FlexGridSizer(cols=1, rows=2)
leftwindowsizer.AddGrowableCol(0)
@@ -1171,38 +1171,38 @@
rolesizer = wx.BoxSizer(wx.HORIZONTAL)
leftsizer.AddSizer(rolesizer, 0, border=0, flag=wx.GROW|wx.RIGHT)
- #self.GenerateEnableButton(leftwindow, rolesizer, plugin)
+ #self.GenerateEnableButton(leftwindow, rolesizer, confnode)
roletext = wx.StaticText(leftwindow, -1)
- roletext.SetLabel(plugin.PlugHelp)
+ roletext.SetLabel(confnode.PlugHelp)
rolesizer.AddWindow(roletext, 0, border=5, flag=wx.RIGHT|wx.ALIGN_LEFT)
- plugin_IECChannel = plugin.BaseParams.getIEC_Channel()
+ confnode_IECChannel = confnode.BaseParams.getIEC_Channel()
iecsizer = wx.BoxSizer(wx.HORIZONTAL)
leftsizer.AddSizer(iecsizer, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL)
st = wx.StaticText(leftwindow, -1)
st.SetFont(wx.Font(faces["size"], wx.DEFAULT, wx.NORMAL, wx.BOLD, faceName = faces["helv"]))
- st.SetLabel(plugin.GetFullIEC_Channel())
+ st.SetLabel(confnode.GetFullIEC_Channel())
iecsizer.AddWindow(st, 0, border=0, flag=0)
updownsizer = wx.BoxSizer(wx.VERTICAL)
iecsizer.AddSizer(updownsizer, 0, border=5, flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL)
- if plugin_IECChannel > 0:
+ if confnode_IECChannel > 0:
ieccdownbutton_id = wx.NewId()
ieccdownbutton = wx.lib.buttons.GenBitmapButton(id=ieccdownbutton_id, bitmap=wx.Bitmap(Bpath( 'images', 'IECCDown.png')),
name='IECCDownButton', parent=leftwindow, pos=wx.Point(0, 0),
size=wx.Size(16, 16), style=wx.NO_BORDER)
- ieccdownbutton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(plugin, plugin_IECChannel - 1), id=ieccdownbutton_id)
+ ieccdownbutton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(confnode, confnode_IECChannel - 1), id=ieccdownbutton_id)
updownsizer.AddWindow(ieccdownbutton, 0, border=0, flag=wx.ALIGN_LEFT)
ieccupbutton_id = wx.NewId()
ieccupbutton = wx.lib.buttons.GenBitmapTextButton(id=ieccupbutton_id, bitmap=wx.Bitmap(Bpath( 'images', 'IECCUp.png')),
name='IECCUpButton', parent=leftwindow, pos=wx.Point(0, 0),
size=wx.Size(16, 16), style=wx.NO_BORDER)
- ieccupbutton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(plugin, plugin_IECChannel + 1), id=ieccupbutton_id)
+ ieccupbutton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(confnode, confnode_IECChannel + 1), id=ieccupbutton_id)
updownsizer.AddWindow(ieccupbutton, 0, border=0, flag=wx.ALIGN_LEFT)
adddeletesizer = wx.BoxSizer(wx.VERTICAL)
@@ -1210,19 +1210,19 @@
deletebutton_id = wx.NewId()
deletebutton = wx.lib.buttons.GenBitmapButton(id=deletebutton_id, bitmap=wx.Bitmap(Bpath( 'images', 'Delete.png')),
- name='DeletePluginButton', parent=leftwindow, pos=wx.Point(0, 0),
+ name='DeleteConfNodeButton', parent=leftwindow, pos=wx.Point(0, 0),
size=wx.Size(16, 16), style=wx.NO_BORDER)
- deletebutton.SetToolTipString(_("Delete this plugin"))
- deletebutton.Bind(wx.EVT_BUTTON, self.GetDeleteButtonFunction(plugin), id=deletebutton_id)
+ deletebutton.SetToolTipString(_("Delete this confnode"))
+ deletebutton.Bind(wx.EVT_BUTTON, self.GetDeleteButtonFunction(confnode), id=deletebutton_id)
adddeletesizer.AddWindow(deletebutton, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER)
- if len(plugin.PlugChildsTypes) > 0:
+ if len(confnode.PlugChildsTypes) > 0:
addbutton_id = wx.NewId()
addbutton = wx.lib.buttons.GenBitmapButton(id=addbutton_id, bitmap=wx.Bitmap(Bpath( 'images', 'Add.png')),
- name='AddPluginButton', parent=leftwindow, pos=wx.Point(0, 0),
+ name='AddConfNodeButton', parent=leftwindow, pos=wx.Point(0, 0),
size=wx.Size(16, 16), style=wx.NO_BORDER)
- addbutton.SetToolTipString(_("Add a sub plugin"))
- addbutton.Bind(wx.EVT_BUTTON, self.Gen_AddPluginMenu(plugin), id=addbutton_id)
+ addbutton.SetToolTipString(_("Add a sub confnode"))
+ addbutton.Bind(wx.EVT_BUTTON, self.Gen_AddConfNodeMenu(confnode), id=addbutton_id)
adddeletesizer.AddWindow(addbutton, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER)
expandbutton_id = wx.NewId()
@@ -1234,27 +1234,27 @@
expandbutton.SetUseFocusIndicator(False)
expandbutton.SetBitmapSelected(wx.Bitmap(Bpath( 'images', 'minus.png')))
- if len(self.PluginInfos[plugin]["children"]) > 0:
- expandbutton.SetToggle(self.PluginInfos[plugin]["expanded"])
+ if len(self.ConfNodeInfos[confnode]["children"]) > 0:
+ expandbutton.SetToggle(self.ConfNodeInfos[confnode]["expanded"])
def togglebutton(event):
if expandbutton.GetToggle():
- self.ExpandPlugin(plugin)
+ self.ExpandConfNode(confnode)
else:
- self.CollapsePlugin(plugin)
- self.PluginInfos[plugin]["expanded"] = expandbutton.GetToggle()
+ self.CollapseConfNode(confnode)
+ self.ConfNodeInfos[confnode]["expanded"] = expandbutton.GetToggle()
self.PLCConfigMainSizer.Layout()
self.RefreshScrollBars()
event.Skip()
expandbutton.Bind(wx.EVT_BUTTON, togglebutton, id=expandbutton_id)
- elif len(plugin_locations) > 0:
- locations_infos = self.PluginInfos[plugin]["locations_infos"]
+ elif len(confnode_locations) > 0:
+ locations_infos = self.ConfNodeInfos[confnode]["locations_infos"]
expandbutton.SetToggle(locations_infos["root"]["expanded"])
def togglebutton(event):
if expandbutton.GetToggle():
self.ExpandLocation(locations_infos, "root")
else:
self.CollapseLocation(locations_infos, "root")
- self.PluginInfos[plugin]["expanded"] = expandbutton.GetToggle()
+ self.ConfNodeInfos[confnode]["expanded"] = expandbutton.GetToggle()
locations_infos["root"]["expanded"] = expandbutton.GetToggle()
self.PLCConfigMainSizer.Layout()
self.RefreshScrollBars()
@@ -1267,22 +1267,22 @@
tc_id = wx.NewId()
tc = wx.TextCtrl(leftwindow, tc_id, size=wx.Size(150, 25), style=wx.NO_BORDER)
tc.SetFont(wx.Font(faces["size"] * 0.75, wx.DEFAULT, wx.NORMAL, wx.BOLD, faceName = faces["helv"]))
- tc.ChangeValue(plugin.MandatoryParams[1].getName())
- tc.Bind(wx.EVT_TEXT, self.GetTextCtrlCallBackFunction(tc, plugin, "BaseParams.Name"), id=tc_id)
+ tc.ChangeValue(confnode.MandatoryParams[1].getName())
+ tc.Bind(wx.EVT_TEXT, self.GetTextCtrlCallBackFunction(tc, confnode, "BaseParams.Name"), id=tc_id)
iecsizer.AddWindow(tc, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL)
- rightwindow = self.GenerateParamsPanel(plugin, bkgdclr, 8)
- self.PluginTreeSizer.AddWindow(rightwindow, 0, border=0, flag=wx.GROW)
-
- self.PluginInfos[plugin]["left"] = leftwindow
- self.PluginInfos[plugin]["right"] = rightwindow
- for child in self.PluginInfos[plugin]["children"]:
+ rightwindow = self.GenerateParamsPanel(confnode, bkgdclr, 8)
+ self.ConfNodeTreeSizer.AddWindow(rightwindow, 0, border=0, flag=wx.GROW)
+
+ self.ConfNodeInfos[confnode]["left"] = leftwindow
+ self.ConfNodeInfos[confnode]["right"] = rightwindow
+ for child in self.ConfNodeInfos[confnode]["children"]:
self.GenerateTreeBranch(child)
- if not self.PluginInfos[child]["expanded"]:
- self.CollapsePlugin(child)
-
- if len(plugin_locations) > 0:
- locations_infos = self.PluginInfos[plugin]["locations_infos"]
+ if not self.ConfNodeInfos[child]["expanded"]:
+ self.CollapseConfNode(child)
+
+ if len(confnode_locations) > 0:
+ locations_infos = self.ConfNodeInfos[confnode]["locations_infos"]
treectrl = wx.TreeCtrl(self.PLCConfig, -1, size=wx.DefaultSize,
style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.NO_BORDER|wx.TR_HIDE_ROOT|wx.TR_NO_LINES|wx.TR_LINES_AT_ROOT)
treectrl.SetImageList(self.LocationImageList)
@@ -1292,19 +1292,19 @@
treectrl.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheelTreeCtrl)
treectrl.AddRoot("")
- self.PluginTreeSizer.AddWindow(treectrl, 0, border=0, flag=0)
+ self.ConfNodeTreeSizer.AddWindow(treectrl, 0, border=0, flag=0)
rightwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1))
rightwindow.SetBackgroundColour(wx.WHITE)
- self.PluginTreeSizer.AddWindow(rightwindow, 0, border=0, flag=wx.GROW)
+ self.ConfNodeTreeSizer.AddWindow(rightwindow, 0, border=0, flag=wx.GROW)
locations_infos["root"]["left"] = treectrl
locations_infos["root"]["right"] = rightwindow
- for location in plugin_locations:
+ for location in confnode_locations:
locations_infos["root"]["children"].append("root.%s" % location["name"])
self.GenerateLocationTreeBranch(treectrl, treectrl.GetRootItem(), locations_infos, "root", location)
if locations_infos["root"]["expanded"]:
- self.PluginTreeSizer.Layout()
+ self.ConfNodeTreeSizer.Layout()
self.ExpandLocation(locations_infos, "root")
else:
self.RefreshTreeCtrlSize(treectrl)
@@ -1399,38 +1399,38 @@
def RefreshAll(self):
self.RefreshPLCParams()
- self.RefreshPluginTree()
-
- def GetItemChannelChangedFunction(self, plugin, value):
- def OnPluginTreeItemChannelChanged(event):
- res = self.SetPluginParamsAttribute(plugin, "BaseParams.IEC_Channel", value)
+ self.RefreshConfNodeTree()
+
+ def GetItemChannelChangedFunction(self, confnode, value):
+ def OnConfNodeTreeItemChannelChanged(event):
+ res = self.SetConfNodeParamsAttribute(confnode, "BaseParams.IEC_Channel", value)
event.Skip()
- return OnPluginTreeItemChannelChanged
-
- def _GetAddPluginFunction(self, name, plugin):
- def OnPluginMenu(event):
- wx.CallAfter(self.AddPlugin, name, plugin)
- return OnPluginMenu
-
- def Gen_AddPluginMenu(self, plugin):
- def AddPluginMenu(event):
+ return OnConfNodeTreeItemChannelChanged
+
+ def _GetAddConfNodeFunction(self, name, confnode):
+ def OnConfNodeMenu(event):
+ wx.CallAfter(self.AddConfNode, name, confnode)
+ return OnConfNodeMenu
+
+ def Gen_AddConfNodeMenu(self, confnode):
+ def AddConfNodeMenu(event):
main_menu = wx.Menu(title='')
- if len(plugin.PlugChildsTypes) > 0:
- for name, XSDClass, help in plugin.PlugChildsTypes:
+ if len(confnode.PlugChildsTypes) > 0:
+ for name, XSDClass, help in confnode.PlugChildsTypes:
new_id = wx.NewId()
main_menu.Append(help=help, id=new_id, kind=wx.ITEM_NORMAL, text=_("Append ")+help)
- self.Bind(wx.EVT_MENU, self._GetAddPluginFunction(name, plugin), id=new_id)
+ self.Bind(wx.EVT_MENU, self._GetAddConfNodeFunction(name, confnode), id=new_id)
self.PopupMenuXY(main_menu)
main_menu.Destroy()
- return AddPluginMenu
-
- def GetButtonCallBackFunction(self, plugin, method):
- """ Generate the callbackfunc for a given plugin method"""
+ return AddConfNodeMenu
+
+ def GetButtonCallBackFunction(self, confnode, method):
+ """ Generate the callbackfunc for a given confnode method"""
def OnButtonClick(event):
# Disable button to prevent re-entrant call
event.GetEventObject().Disable()
# Call
- getattr(plugin,method)()
+ getattr(confnode,method)()
# Re-enable button
event.GetEventObject().Enable()
# Trigger refresh on Idle
@@ -1438,20 +1438,20 @@
event.Skip()
return OnButtonClick
- def GetChoiceCallBackFunction(self, choicectrl, plugin, path):
+ def GetChoiceCallBackFunction(self, choicectrl, confnode, path):
def OnChoiceChanged(event):
- res = self.SetPluginParamsAttribute(plugin, path, choicectrl.GetStringSelection())
+ res = self.SetConfNodeParamsAttribute(confnode, path, choicectrl.GetStringSelection())
choicectrl.SetStringSelection(res)
event.Skip()
return OnChoiceChanged
- def GetChoiceContentCallBackFunction(self, choicectrl, staticboxsizer, plugin, path):
+ def GetChoiceContentCallBackFunction(self, choicectrl, staticboxsizer, confnode, path):
def OnChoiceContentChanged(event):
- res = self.SetPluginParamsAttribute(plugin, path, choicectrl.GetStringSelection())
+ res = self.SetConfNodeParamsAttribute(confnode, path, choicectrl.GetStringSelection())
if wx.VERSION < (2, 8, 0):
self.ParamsPanel.Freeze()
choicectrl.SetStringSelection(res)
- infos = self.PluginRoot.GetParamsAttributes(path)
+ infos = self.CTR.GetParamsAttributes(path)
staticbox = staticboxsizer.GetStaticBox()
staticbox.SetLabel("%(name)s - %(value)s"%infos)
self.RefreshSizerElement(self.ParamsPanel, staticboxsizer, infos["children"], "%s.%s"%(path, infos["name"]), selected=selected)
@@ -1463,27 +1463,27 @@
event.Skip()
return OnChoiceContentChanged
- def GetTextCtrlCallBackFunction(self, textctrl, plugin, path):
+ def GetTextCtrlCallBackFunction(self, textctrl, confnode, path):
def OnTextCtrlChanged(event):
- res = self.SetPluginParamsAttribute(plugin, path, textctrl.GetValue())
+ res = self.SetConfNodeParamsAttribute(confnode, path, textctrl.GetValue())
if res != textctrl.GetValue():
textctrl.ChangeValue(res)
event.Skip()
return OnTextCtrlChanged
- def GetCheckBoxCallBackFunction(self, chkbx, plugin, path):
+ def GetCheckBoxCallBackFunction(self, chkbx, confnode, path):
def OnCheckBoxChanged(event):
- res = self.SetPluginParamsAttribute(plugin, path, chkbx.IsChecked())
+ res = self.SetConfNodeParamsAttribute(confnode, path, chkbx.IsChecked())
chkbx.SetValue(res)
event.Skip()
return OnCheckBoxChanged
- def GetBrowseCallBackFunction(self, name, textctrl, library, value_infos, plugin, path):
+ def GetBrowseCallBackFunction(self, name, textctrl, library, value_infos, confnode, path):
infos = [value_infos]
def OnBrowseButton(event):
dialog = BrowseValuesLibraryDialog(self, name, library, infos[0])
if dialog.ShowModal() == wx.ID_OK:
- value, value_infos = self.SetPluginParamsAttribute(plugin, path, dialog.GetValueInfos())
+ value, value_infos = self.SetConfNodeParamsAttribute(confnode, path, dialog.GetValueInfos())
textctrl.ChangeValue(value)
infos[0] = value_infos
dialog.Destroy()
@@ -1502,7 +1502,7 @@
for staticbox in staticboxes:
staticbox.Destroy()
- def RefreshSizerElement(self, parent, sizer, plugin, elements, path, clean = True):
+ def RefreshSizerElement(self, parent, sizer, confnode, elements, path, clean = True):
if clean:
if wx.VERSION < (2, 8, 0):
self.ClearSizer(sizer)
@@ -1524,7 +1524,7 @@
sizer.AddSizer(staticboxsizer, 0, border=0, flag=wx.GROW|wx.TOP)
else:
sizer.AddSizer(staticboxsizer, 0, border=0, flag=wx.GROW)
- self.RefreshSizerElement(parent, staticboxsizer, plugin, element_infos["children"], element_path)
+ self.RefreshSizerElement(parent, staticboxsizer, confnode, element_infos["children"], element_path)
else:
boxsizer = wx.FlexGridSizer(cols=3, rows=1)
boxsizer.AddGrowableCol(1)
@@ -1561,7 +1561,7 @@
browse_boxsizer.AddWindow(button, 0, border=0, flag=0)
button.Bind(wx.EVT_BUTTON,
self.GetBrowseCallBackFunction(element_infos["name"], textctrl, element_infos["type"],
- value_infos, plugin, element_path),
+ value_infos, confnode, element_path),
id=button_id)
else:
combobox = wx.ComboBox(id=id, name=element_infos["name"], parent=parent,
@@ -1579,12 +1579,12 @@
pos=wx.Point(0, 0), size=wx.Size(10, 0), style=0)
staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL)
sizer.AddSizer(staticboxsizer, 0, border=5, flag=wx.GROW|wx.BOTTOM)
- self.RefreshSizerElement(parent, staticboxsizer, plugin, element_infos["children"], element_path)
- callback = self.GetChoiceContentCallBackFunction(combobox, staticboxsizer, plugin, element_path)
+ self.RefreshSizerElement(parent, staticboxsizer, confnode, element_infos["children"], element_path)
+ callback = self.GetChoiceContentCallBackFunction(combobox, staticboxsizer, confnode, element_path)
else:
for choice in element_infos["type"]:
combobox.Append(choice)
- callback = self.GetChoiceCallBackFunction(combobox, plugin, element_path)
+ callback = self.GetChoiceCallBackFunction(combobox, confnode, element_path)
if element_infos["value"] is None:
combobox.SetStringSelection("")
else:
@@ -1603,7 +1603,7 @@
boxsizer.AddWindow(spinctrl, 0, border=0, flag=0)
if element_infos["value"] is not None:
spinctrl.SetValue(element_infos["value"])
- spinctrl.Bind(wx.EVT_SPINCTRL, self.GetTextCtrlCallBackFunction(spinctrl, plugin, element_path), id=id)
+ spinctrl.Bind(wx.EVT_SPINCTRL, self.GetTextCtrlCallBackFunction(spinctrl, confnode, element_path), id=id)
else:
if element_infos["type"] == "boolean":
checkbox = wx.CheckBox(id=id, name=element_infos["name"], parent=parent,
@@ -1611,7 +1611,7 @@
boxsizer.AddWindow(checkbox, 0, border=0, flag=0)
if element_infos["value"] is not None:
checkbox.SetValue(element_infos["value"])
- checkbox.Bind(wx.EVT_CHECKBOX, self.GetCheckBoxCallBackFunction(checkbox, plugin, element_path), id=id)
+ checkbox.Bind(wx.EVT_CHECKBOX, self.GetCheckBoxCallBackFunction(checkbox, confnode, element_path), id=id)
elif element_infos["type"] in ["unsignedLong", "long","integer"]:
if element_infos["type"].startswith("unsigned"):
scmin = 0
@@ -1624,7 +1624,7 @@
boxsizer.AddWindow(spinctrl, 0, border=0, flag=0)
if element_infos["value"] is not None:
spinctrl.SetValue(element_infos["value"])
- spinctrl.Bind(wx.EVT_SPINCTRL, self.GetTextCtrlCallBackFunction(spinctrl, plugin, element_path), id=id)
+ spinctrl.Bind(wx.EVT_SPINCTRL, self.GetTextCtrlCallBackFunction(spinctrl, confnode, element_path), id=id)
else:
choices = cPickle.loads(str(self.Config.Read(element_path, cPickle.dumps([""]))))
textctrl = TextCtrlAutoComplete.TextCtrlAutoComplete(id=id,
@@ -1640,15 +1640,15 @@
boxsizer.AddWindow(textctrl, 0, border=0, flag=0)
if element_infos["value"] is not None:
textctrl.ChangeValue(str(element_infos["value"]))
- textctrl.Bind(wx.EVT_TEXT, self.GetTextCtrlCallBackFunction(textctrl, plugin, element_path))
+ textctrl.Bind(wx.EVT_TEXT, self.GetTextCtrlCallBackFunction(textctrl, confnode, element_path))
first = False
def ResetView(self):
IDEFrame.ResetView(self)
- self.PluginInfos = {}
- if self.PluginRoot is not None:
- self.PluginRoot.CloseProject()
- self.PluginRoot = None
+ self.ConfNodeInfos = {}
+ if self.CTR is not None:
+ self.CTR.CloseProject()
+ self.CTR = None
self.Log.flush()
if self.EnableDebug:
self.DebugVariablePanel.SetDataProducer(None)
@@ -1662,7 +1662,7 @@
self.Config.Flush()
def OnNewProjectMenu(self, event):
- if self.PluginRoot is not None and not self.CheckSaveBeforeClosing():
+ if self.CTR is not None and not self.CheckSaveBeforeClosing():
return
if not self.Config.HasEntry("lastopenedfolder"):
@@ -1676,15 +1676,15 @@
self.Config.Write("lastopenedfolder", os.path.dirname(projectpath))
self.Config.Flush()
self.ResetView()
- plugin_root = PluginsRoot(self, self.Log)
- result = plugin_root.NewProject(projectpath)
+ ctr = ConfigTreeRoot(self, self.Log)
+ result = ctr.NewProject(projectpath)
if not result:
- self.PluginRoot = plugin_root
- self.Controler = self.PluginRoot
+ self.CTR = ctr
+ self.Controler = self.CTR
self.LibraryPanel.SetControler(self.Controler)
self.RefreshConfigRecentProjects(projectpath)
if self.EnableDebug:
- self.DebugVariablePanel.SetDataProducer(self.PluginRoot)
+ self.DebugVariablePanel.SetDataProducer(self.CTR)
self._Refresh(TYPESTREE, INSTANCESTREE, LIBRARYTREE)
self.RefreshAll()
else:
@@ -1694,7 +1694,7 @@
dialog.Destroy()
def OnOpenProjectMenu(self, event):
- if self.PluginRoot is not None and not self.CheckSaveBeforeClosing():
+ if self.CTR is not None and not self.CheckSaveBeforeClosing():
return
if not self.Config.HasEntry("lastopenedfolder"):
@@ -1712,14 +1712,14 @@
self.Config.Write("lastopenedfolder", os.path.dirname(projectpath))
self.Config.Flush()
self.ResetView()
- self.PluginRoot = PluginsRoot(self, self.Log)
- self.Controler = self.PluginRoot
- result = self.PluginRoot.LoadProject(projectpath)
+ self.CTR = ConfigTreeRoot(self, self.Log)
+ self.Controler = self.CTR
+ result = self.CTR.LoadProject(projectpath)
if not result:
self.LibraryPanel.SetControler(self.Controler)
self.RefreshConfigRecentProjects(projectpath)
if self.EnableDebug:
- self.DebugVariablePanel.SetDataProducer(self.PluginRoot)
+ self.DebugVariablePanel.SetDataProducer(self.CTR)
self.LoadProjectOrganization()
self._Refresh(TYPESTREE, INSTANCESTREE, LIBRARYTREE)
self.RefreshAll()
@@ -1731,7 +1731,7 @@
self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU)
def OnCloseProjectMenu(self, event):
- if self.PluginRoot is not None and not self.CheckSaveBeforeClosing():
+ if self.CTR is not None and not self.CheckSaveBeforeClosing():
return
self.SaveProjectOrganization()
@@ -1740,14 +1740,14 @@
self.RefreshAll()
def OnSaveProjectMenu(self, event):
- if self.PluginRoot is not None:
- self.PluginRoot.SaveProject()
+ if self.CTR is not None:
+ self.CTR.SaveProject()
self.RefreshAll()
self._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES)
def OnSaveProjectAsMenu(self, event):
- if self.PluginRoot is not None:
- self.PluginRoot.SaveProjectAs()
+ if self.CTR is not None:
+ self.CTR.SaveProjectAs()
self.RefreshAll()
self._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES)
event.Skip()
@@ -1765,53 +1765,53 @@
OpenHtmlFrame(self,_("About Beremiz"), Bpath("doc","about.html"), wx.Size(550, 500))
def OnPouSelectedChanged(self, event):
- wx.CallAfter(self.RefreshPluginMenu)
+ wx.CallAfter(self.RefreshConfNodeMenu)
IDEFrame.OnPouSelectedChanged(self, event)
def OnPageClose(self, event):
- wx.CallAfter(self.RefreshPluginMenu)
+ wx.CallAfter(self.RefreshConfNodeMenu)
IDEFrame.OnPageClose(self, event)
- def GetAddButtonFunction(self, plugin, window):
+ def GetAddButtonFunction(self, confnode, window):
def AddButtonFunction(event):
- if plugin and len(plugin.PlugChildsTypes) > 0:
- plugin_menu = wx.Menu(title='')
- for name, XSDClass, help in plugin.PlugChildsTypes:
+ if confnode and len(confnode.PlugChildsTypes) > 0:
+ confnode_menu = wx.Menu(title='')
+ for name, XSDClass, help in confnode.PlugChildsTypes:
new_id = wx.NewId()
- plugin_menu.Append(help=help, id=new_id, kind=wx.ITEM_NORMAL, text=name)
- self.Bind(wx.EVT_MENU, self._GetAddPluginFunction(name, plugin), id=new_id)
+ confnode_menu.Append(help=help, id=new_id, kind=wx.ITEM_NORMAL, text=name)
+ self.Bind(wx.EVT_MENU, self._GetAddConfNodeFunction(name, confnode), id=new_id)
window_pos = window.GetPosition()
- wx.CallAfter(self.PLCConfig.PopupMenu, plugin_menu)
+ wx.CallAfter(self.PLCConfig.PopupMenu, confnode_menu)
event.Skip()
return AddButtonFunction
- def GetDeleteButtonFunction(self, plugin):
+ def GetDeleteButtonFunction(self, confnode):
def DeleteButtonFunction(event):
- wx.CallAfter(self.DeletePlugin, plugin)
+ wx.CallAfter(self.DeleteConfNode, confnode)
event.Skip()
return DeleteButtonFunction
- def AddPlugin(self, PluginType, plugin):
- if self.PluginRoot.CheckProjectPathPerm():
- dialog = wx.TextEntryDialog(self, _("Please enter a name for plugin:"), _("Add Plugin"), "", wx.OK|wx.CANCEL)
+ def AddConfNode(self, ConfNodeType, confnode):
+ if self.CTR.CheckProjectPathPerm():
+ dialog = wx.TextEntryDialog(self, _("Please enter a name for confnode:"), _("Add ConfNode"), "", wx.OK|wx.CANCEL)
if dialog.ShowModal() == wx.ID_OK:
- PluginName = dialog.GetValue()
- plugin.PlugAddChild(PluginName, PluginType)
- self.PluginRoot.RefreshPluginsBlockLists()
+ ConfNodeName = dialog.GetValue()
+ confnode.PlugAddChild(ConfNodeName, ConfNodeType)
+ self.CTR.RefreshConfNodesBlockLists()
self._Refresh(TITLE, FILEMENU)
- self.RefreshPluginTree()
+ self.RefreshConfNodeTree()
dialog.Destroy()
- def DeletePlugin(self, plugin):
- if self.PluginRoot.CheckProjectPathPerm():
- dialog = wx.MessageDialog(self, _("Really delete plugin ?"), _("Remove plugin"), wx.YES_NO|wx.NO_DEFAULT)
+ def DeleteConfNode(self, confnode):
+ if self.CTR.CheckProjectPathPerm():
+ dialog = wx.MessageDialog(self, _("Really delete confnode ?"), _("Remove confnode"), wx.YES_NO|wx.NO_DEFAULT)
if dialog.ShowModal() == wx.ID_YES:
- self.PluginInfos.pop(plugin)
- plugin.PlugRemove()
- del plugin
- self.PluginRoot.RefreshPluginsBlockLists()
+ self.ConfNodeInfos.pop(confnode)
+ confnode.PlugRemove()
+ del confnode
+ self.CTR.RefreshConfNodesBlockLists()
self._Refresh(TITLE, FILEMENU)
- self.RefreshPluginTree()
+ self.RefreshConfNodeTree()
dialog.Destroy()
#-------------------------------------------------------------------------------
diff -r 180e4a7d945c -r 1c23952dbde1 ConfigTree.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ConfigTree.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2063 @@
+"""
+Base definitions for beremiz confnodes
+"""
+
+import os,sys,traceback
+import time
+import confnodes
+import types
+import shutil
+from xml.dom import minidom
+import wx
+
+#Quick hack to be able to find Beremiz IEC tools. Should be config params.
+base_folder = os.path.split(sys.path[0])[0]
+
+from xmlclass import GenerateClassesFromXSDstring
+from wxPopen import ProcessLogger
+
+from PLCControler import PLCControler, LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
+
+_BaseParamsClass = GenerateClassesFromXSDstring("""
+
+
+
+
+
+
+
+
+ """)["BaseParams"]
+
+NameTypeSeparator = '@'
+
+class MiniTextControler:
+
+ def __init__(self, filepath):
+ self.FilePath = filepath
+
+ def PlugFullName(self):
+ return ""
+
+ def SetEditedElementText(self, tagname, text):
+ file = open(self.FilePath, "w")
+ file.write(text)
+ file.close()
+
+ def GetEditedElementText(self, tagname, debug = False):
+ if os.path.isfile(self.FilePath):
+ file = open(self.FilePath, "r")
+ text = file.read()
+ file.close()
+ return text
+ return ""
+
+ def GetEditedElementInterfaceVars(self, tagname, debug = False):
+ return []
+
+ def GetEditedElementType(self, tagname, debug = False):
+ return "program"
+
+ def GetBlockTypes(self, tagname = "", debug = False):
+ return []
+
+ def GetDataTypes(self, tagname = "", basetypes = True, only_locatables = False, debug = False):
+ return []
+
+ def GetEnumeratedDataValues(self, debug = False):
+ return []
+
+ def StartBuffering(self):
+ pass
+
+ def EndBuffering(self):
+ pass
+
+ def BufferProject(self):
+ pass
+
+# helper func to get path to images
+def opjimg(imgname):
+ return os.path.join(base_folder, "beremiz", "images",imgname)
+
+# helper func to check path write permission
+def CheckPathPerm(path):
+ if path is None or not os.path.isdir(path):
+ return False
+ for root, dirs, files in os.walk(path):
+ for name in files:
+ if os.access(root, os.W_OK) is not True or os.access(os.path.join(root, name), os.W_OK) is not True:
+ return False
+ return True
+
+class ConfigTreeNode:
+ """
+ This class is the one that define confnodes.
+ """
+
+ XSD = None
+ PlugChildsTypes = []
+ PlugMaxCount = None
+ ConfNodeMethods = []
+ LibraryControler = None
+ EditorType = None
+
+ def _AddParamsMembers(self):
+ self.PlugParams = None
+ if self.XSD:
+ self.Classes = GenerateClassesFromXSDstring(self.XSD)
+ Classes = [(name, XSDclass) for name, XSDclass in self.Classes.items() if XSDclass.IsBaseClass]
+ if len(Classes) == 1:
+ name, XSDclass = Classes[0]
+ obj = XSDclass()
+ self.PlugParams = (name, obj)
+ setattr(self, name, obj)
+
+ def __init__(self):
+ # Create BaseParam
+ self.BaseParams = _BaseParamsClass()
+ self.MandatoryParams = ("BaseParams", self.BaseParams)
+ self._AddParamsMembers()
+ self.PluggedChilds = {}
+ self._View = None
+ # copy ConfNodeMethods so that it can be later customized
+ self.ConfNodeMethods = [dic.copy() for dic in self.ConfNodeMethods]
+ self.LoadSTLibrary()
+
+ def ConfNodeBaseXmlFilePath(self, PlugName=None):
+ return os.path.join(self.PlugPath(PlugName), "baseconfnode.xml")
+
+ def ConfNodeXmlFilePath(self, PlugName=None):
+ return os.path.join(self.PlugPath(PlugName), "confnode.xml")
+
+ def ConfNodeLibraryFilePath(self):
+ return os.path.join(self.ConfNodePath(), "pous.xml")
+
+ def ConfNodePath(self):
+ return os.path.join(self.PlugParent.ConfNodePath(), self.PlugType)
+
+ def PlugPath(self,PlugName=None):
+ if not PlugName:
+ PlugName = self.PlugName()
+ return os.path.join(self.PlugParent.PlugPath(),
+ PlugName + NameTypeSeparator + self.PlugType)
+
+ def PlugName(self):
+ return self.BaseParams.getName()
+
+ def PlugEnabled(self):
+ return self.BaseParams.getEnabled()
+
+ def PlugFullName(self):
+ parent = self.PlugParent.PlugFullName()
+ if parent != "":
+ return parent + "." + self.PlugName()
+ return self.BaseParams.getName()
+
+ def GetIconPath(self, name):
+ return opjimg(name)
+
+ def PlugTestModified(self):
+ return self.ChangesToSave
+
+ def ProjectTestModified(self):
+ """
+ recursively check modified status
+ """
+ if self.PlugTestModified():
+ return True
+
+ for PlugChild in self.IterChilds():
+ if PlugChild.ProjectTestModified():
+ return True
+
+ return False
+
+ def RemoteExec(self, script, **kwargs):
+ return self.PlugParent.RemoteExec(script, **kwargs)
+
+ def OnPlugSave(self):
+ #Default, do nothing and return success
+ return True
+
+ def GetParamsAttributes(self, path = None):
+ if path:
+ parts = path.split(".", 1)
+ if self.MandatoryParams and parts[0] == self.MandatoryParams[0]:
+ return self.MandatoryParams[1].getElementInfos(parts[0], parts[1])
+ elif self.PlugParams and parts[0] == self.PlugParams[0]:
+ return self.PlugParams[1].getElementInfos(parts[0], parts[1])
+ else:
+ params = []
+ if wx.VERSION < (2, 8, 0) and self.MandatoryParams:
+ params.append(self.MandatoryParams[1].getElementInfos(self.MandatoryParams[0]))
+ if self.PlugParams:
+ params.append(self.PlugParams[1].getElementInfos(self.PlugParams[0]))
+ return params
+
+ def SetParamsAttribute(self, path, value):
+ self.ChangesToSave = True
+ # Filter IEC_Channel and Name, that have specific behavior
+ if path == "BaseParams.IEC_Channel":
+ old_leading = ".".join(map(str, self.GetCurrentLocation()))
+ new_value = self.FindNewIEC_Channel(value)
+ new_leading = ".".join(map(str, self.PlugParent.GetCurrentLocation() + (new_value,)))
+ self.GetPlugRoot().UpdateProjectVariableLocation(old_leading, new_leading)
+ return new_value, True
+ elif path == "BaseParams.Name":
+ res = self.FindNewName(value)
+ self.PlugRequestSave()
+ return res, True
+
+ parts = path.split(".", 1)
+ if self.MandatoryParams and parts[0] == self.MandatoryParams[0]:
+ self.MandatoryParams[1].setElementValue(parts[1], value)
+ elif self.PlugParams and parts[0] == self.PlugParams[0]:
+ self.PlugParams[1].setElementValue(parts[1], value)
+ return value, False
+
+ def PlugMakeDir(self):
+ os.mkdir(self.PlugPath())
+
+ def PlugRequestSave(self):
+ if self.GetPlugRoot().CheckProjectPathPerm(False):
+ # If confnode do not have corresponding directory
+ plugpath = self.PlugPath()
+ if not os.path.isdir(plugpath):
+ # Create it
+ os.mkdir(plugpath)
+
+ # generate XML for base XML parameters controller of the confnode
+ if self.MandatoryParams:
+ BaseXMLFile = open(self.ConfNodeBaseXmlFilePath(),'w')
+ BaseXMLFile.write("\n")
+ BaseXMLFile.write(self.MandatoryParams[1].generateXMLText(self.MandatoryParams[0], 0).encode("utf-8"))
+ BaseXMLFile.close()
+
+ # generate XML for XML parameters controller of the confnode
+ if self.PlugParams:
+ XMLFile = open(self.ConfNodeXmlFilePath(),'w')
+ XMLFile.write("\n")
+ XMLFile.write(self.PlugParams[1].generateXMLText(self.PlugParams[0], 0).encode("utf-8"))
+ XMLFile.close()
+
+ # Call the confnode specific OnPlugSave method
+ result = self.OnPlugSave()
+ if not result:
+ return _("Error while saving \"%s\"\n")%self.PlugPath()
+
+ # mark confnode as saved
+ self.ChangesToSave = False
+ # go through all childs and do the same
+ for PlugChild in self.IterChilds():
+ result = PlugChild.PlugRequestSave()
+ if result:
+ return result
+ return None
+
+ def PlugImport(self, src_PlugPath):
+ shutil.copytree(src_PlugPath, self.PlugPath)
+ return True
+
+ def PlugGenerate_C(self, buildpath, locations):
+ """
+ Generate C code
+ @param locations: List of complete variables locations \
+ [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
+ "NAME" : name of the variable (generally "__IW0_1_2" style)
+ "DIR" : direction "Q","I" or "M"
+ "SIZE" : size "X", "B", "W", "D", "L"
+ "LOC" : tuple of interger for IEC location (0,1,2,...)
+ }, ...]
+ @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
+ """
+ self.GetPlugRoot().logger.write_warning(".".join(map(lambda x:str(x), self.GetCurrentLocation())) + " -> Nothing to do\n")
+ return [],"",False
+
+ def _Generate_C(self, buildpath, locations):
+ # Generate confnodes [(Cfiles, CFLAGS)], LDFLAGS, DoCalls, extra_files
+ # extra_files = [(fname,fobject), ...]
+ gen_result = self.PlugGenerate_C(buildpath, locations)
+ PlugCFilesAndCFLAGS, PlugLDFLAGS, DoCalls = gen_result[:3]
+ extra_files = gen_result[3:]
+ # if some files have been generated put them in the list with their location
+ if PlugCFilesAndCFLAGS:
+ LocationCFilesAndCFLAGS = [(self.GetCurrentLocation(), PlugCFilesAndCFLAGS, DoCalls)]
+ else:
+ LocationCFilesAndCFLAGS = []
+
+ # confnode asks for some LDFLAGS
+ if PlugLDFLAGS:
+ # LDFLAGS can be either string
+ if type(PlugLDFLAGS)==type(str()):
+ LDFLAGS=[PlugLDFLAGS]
+ #or list of strings
+ elif type(PlugLDFLAGS)==type(list()):
+ LDFLAGS=PlugLDFLAGS[:]
+ else:
+ LDFLAGS=[]
+
+ # recurse through all childs, and stack their results
+ for PlugChild in self.IECSortedChilds():
+ new_location = PlugChild.GetCurrentLocation()
+ # How deep are we in the tree ?
+ depth=len(new_location)
+ _LocationCFilesAndCFLAGS, _LDFLAGS, _extra_files = \
+ PlugChild._Generate_C(
+ #keep the same path
+ buildpath,
+ # filter locations that start with current IEC location
+ [loc for loc in locations if loc["LOC"][0:depth] == new_location ])
+ # stack the result
+ LocationCFilesAndCFLAGS += _LocationCFilesAndCFLAGS
+ LDFLAGS += _LDFLAGS
+ extra_files += _extra_files
+
+ return LocationCFilesAndCFLAGS, LDFLAGS, extra_files
+
+ def ConfNodeTypesFactory(self):
+ if self.LibraryControler is not None:
+ return [{"name" : self.PlugType, "types": self.LibraryControler.Project}]
+ return []
+
+ def ParentsTypesFactory(self):
+ return self.PlugParent.ParentsTypesFactory() + self.ConfNodeTypesFactory()
+
+ def ConfNodesTypesFactory(self):
+ list = self.ConfNodeTypesFactory()
+ for PlugChild in self.IterChilds():
+ list += PlugChild.ConfNodesTypesFactory()
+ return list
+
+ def STLibraryFactory(self):
+ if self.LibraryControler is not None:
+ program, errors, warnings = self.LibraryControler.GenerateProgram()
+ return program + "\n"
+ return ""
+
+ def ConfNodesSTLibraryFactory(self):
+ program = self.STLibraryFactory()
+ for PlugChild in self.IECSortedChilds():
+ program += PlugChild.ConfNodesSTLibraryFactory()
+ return program
+
+ def IterChilds(self):
+ for PlugType, PluggedChilds in self.PluggedChilds.items():
+ for PlugInstance in PluggedChilds:
+ yield PlugInstance
+
+ def IECSortedChilds(self):
+ # reorder childs by IEC_channels
+ ordered = [(chld.BaseParams.getIEC_Channel(),chld) for chld in self.IterChilds()]
+ if ordered:
+ ordered.sort()
+ return zip(*ordered)[1]
+ else:
+ return []
+
+ def _GetChildBySomething(self, something, toks):
+ for PlugInstance in self.IterChilds():
+ # if match component of the name
+ if getattr(PlugInstance.BaseParams, something) == toks[0]:
+ # if Name have other components
+ if len(toks) >= 2:
+ # Recurse in order to find the latest object
+ return PlugInstance._GetChildBySomething( something, toks[1:])
+ # No sub name -> found
+ return PlugInstance
+ # Not found
+ return None
+
+ def GetChildByName(self, Name):
+ if Name:
+ toks = Name.split('.')
+ return self._GetChildBySomething("Name", toks)
+ else:
+ return self
+
+ def GetChildByIECLocation(self, Location):
+ if Location:
+ return self._GetChildBySomething("IEC_Channel", Location)
+ else:
+ return self
+
+ def GetCurrentLocation(self):
+ """
+ @return: Tupple containing confnode IEC location of current confnode : %I0.0.4.5 => (0,0,4,5)
+ """
+ return self.PlugParent.GetCurrentLocation() + (self.BaseParams.getIEC_Channel(),)
+
+ def GetCurrentName(self):
+ """
+ @return: String "ParentParentName.ParentName.Name"
+ """
+ return self.PlugParent._GetCurrentName() + self.BaseParams.getName()
+
+ def _GetCurrentName(self):
+ """
+ @return: String "ParentParentName.ParentName.Name."
+ """
+ return self.PlugParent._GetCurrentName() + self.BaseParams.getName() + "."
+
+ def GetPlugRoot(self):
+ return self.PlugParent.GetPlugRoot()
+
+ def GetFullIEC_Channel(self):
+ return ".".join([str(i) for i in self.GetCurrentLocation()]) + ".x"
+
+ def GetLocations(self):
+ location = self.GetCurrentLocation()
+ return [loc for loc in self.PlugParent.GetLocations() if loc["LOC"][0:len(location)] == location]
+
+ def GetVariableLocationTree(self):
+ '''
+ This function is meant to be overridden by confnodes.
+
+ It should returns an list of dictionaries
+
+ - IEC_type is an IEC type like BOOL/BYTE/SINT/...
+ - location is a string of this variable's location, like "%IX0.0.0"
+ '''
+ children = []
+ for child in self.IECSortedChilds():
+ children.append(child.GetVariableLocationTree())
+ return {"name": self.BaseParams.getName(),
+ "type": LOCATION_CONFNODE,
+ "location": self.GetFullIEC_Channel(),
+ "children": children}
+
+ def FindNewName(self, DesiredName):
+ """
+ Changes Name to DesiredName if available, Name-N if not.
+ @param DesiredName: The desired Name (string)
+ """
+ # Get Current Name
+ CurrentName = self.BaseParams.getName()
+ # Do nothing if no change
+ #if CurrentName == DesiredName: return CurrentName
+ # Build a list of used Name out of parent's PluggedChilds
+ AllNames=[]
+ for PlugInstance in self.PlugParent.IterChilds():
+ if PlugInstance != self:
+ AllNames.append(PlugInstance.BaseParams.getName())
+
+ # Find a free name, eventually appending digit
+ res = DesiredName
+ suffix = 1
+ while res in AllNames:
+ res = "%s-%d"%(DesiredName, suffix)
+ suffix += 1
+
+ # Get old path
+ oldname = self.PlugPath()
+ # Check previous confnode existance
+ dontexist = self.BaseParams.getName() == "__unnamed__"
+ # Set the new name
+ self.BaseParams.setName(res)
+ # Rename confnode dir if exist
+ if not dontexist:
+ shutil.move(oldname, self.PlugPath())
+ # warn user he has two left hands
+ if DesiredName != res:
+ self.GetPlugRoot().logger.write_warning(_("A child names \"%s\" already exist -> \"%s\"\n")%(DesiredName,res))
+ return res
+
+ def GetAllChannels(self):
+ AllChannels=[]
+ for PlugInstance in self.PlugParent.IterChilds():
+ if PlugInstance != self:
+ AllChannels.append(PlugInstance.BaseParams.getIEC_Channel())
+ AllChannels.sort()
+ return AllChannels
+
+ def FindNewIEC_Channel(self, DesiredChannel):
+ """
+ Changes IEC Channel number to DesiredChannel if available, nearest available if not.
+ @param DesiredChannel: The desired IEC channel (int)
+ """
+ # Get Current IEC channel
+ CurrentChannel = self.BaseParams.getIEC_Channel()
+ # Do nothing if no change
+ #if CurrentChannel == DesiredChannel: return CurrentChannel
+ # Build a list of used Channels out of parent's PluggedChilds
+ AllChannels = self.GetAllChannels()
+
+ # Now, try to guess the nearest available channel
+ res = DesiredChannel
+ while res in AllChannels: # While channel not free
+ if res < CurrentChannel: # Want to go down ?
+ res -= 1 # Test for n-1
+ if res < 0 :
+ self.GetPlugRoot().logger.write_warning(_("Cannot find lower free IEC channel than %d\n")%CurrentChannel)
+ return CurrentChannel # Can't go bellow 0, do nothing
+ else : # Want to go up ?
+ res += 1 # Test for n-1
+ # Finally set IEC Channel
+ self.BaseParams.setIEC_Channel(res)
+ return res
+
+ def _OpenView(self, name=None):
+ if self.EditorType is not None and self._View is None:
+ app_frame = self.GetPlugRoot().AppFrame
+
+ self._View = self.EditorType(app_frame.TabsOpened, self, app_frame)
+
+ app_frame.EditProjectElement(self._View, self.PlugName())
+
+ return self._View
+ return None
+
+ def OnCloseEditor(self, view):
+ if self._View == view:
+ self._View = None
+
+ def OnPlugClose(self):
+ if self._View is not None:
+ app_frame = self.GetPlugRoot().AppFrame
+ if app_frame is not None:
+ app_frame.DeletePage(self._View)
+ return True
+
+ def _doRemoveChild(self, PlugInstance):
+ # Remove all childs of child
+ for SubPlugInstance in PlugInstance.IterChilds():
+ PlugInstance._doRemoveChild(SubPlugInstance)
+ # Call the OnCloseMethod
+ PlugInstance.OnPlugClose()
+ # Delete confnode dir
+ shutil.rmtree(PlugInstance.PlugPath())
+ # Remove child of PluggedChilds
+ self.PluggedChilds[PlugInstance.PlugType].remove(PlugInstance)
+ # Forget it... (View have to refresh)
+
+ def PlugRemove(self):
+ # Fetch the confnode
+ #PlugInstance = self.GetChildByName(PlugName)
+ # Ask to his parent to remove it
+ self.PlugParent._doRemoveChild(self)
+
+ def PlugAddChild(self, PlugName, PlugType, IEC_Channel=0):
+ """
+ Create the confnodes that may be added as child to this node self
+ @param PlugType: string desining the confnode class name (get name from PlugChildsTypes)
+ @param PlugName: string for the name of the confnode instance
+ """
+ # reorgabize self.PlugChildsTypes tuples from (name, PlugClass, Help)
+ # to ( name, (PlugClass, Help)), an make a dict
+ transpose = zip(*self.PlugChildsTypes)
+ PlugChildsTypes = dict(zip(transpose[0],zip(transpose[1],transpose[2])))
+ # Check that adding this confnode is allowed
+ try:
+ PlugClass, PlugHelp = PlugChildsTypes[PlugType]
+ except KeyError:
+ raise Exception, _("Cannot create child %s of type %s ")%(PlugName, PlugType)
+
+ # if PlugClass is a class factory, call it. (prevent unneeded imports)
+ if type(PlugClass) == types.FunctionType:
+ PlugClass = PlugClass()
+
+ # Eventualy Initialize child instance list for this class of confnode
+ PluggedChildsWithSameClass = self.PluggedChilds.setdefault(PlugType, list())
+ # Check count
+ if getattr(PlugClass, "PlugMaxCount", None) and len(PluggedChildsWithSameClass) >= PlugClass.PlugMaxCount:
+ raise Exception, _("Max count (%d) reached for this confnode of type %s ")%(PlugClass.PlugMaxCount, PlugType)
+
+ # create the final class, derived of provided confnode and template
+ class FinalPlugClass(PlugClass, ConfigTreeNode):
+ """
+ ConfNode class is derivated into FinalPlugClass before being instanciated
+ This way __init__ is overloaded to ensure ConfigTreeNode.__init__ is called
+ before PlugClass.__init__, and to do the file related stuff.
+ """
+ def __init__(_self):
+ # self is the parent
+ _self.PlugParent = self
+ # Keep track of the confnode type name
+ _self.PlugType = PlugType
+ # remind the help string, for more fancy display
+ _self.PlugHelp = PlugHelp
+ # Call the base confnode template init - change XSD into class members
+ ConfigTreeNode.__init__(_self)
+ # check name is unique
+ NewPlugName = _self.FindNewName(PlugName)
+ # If dir have already be made, and file exist
+ if os.path.isdir(_self.PlugPath(NewPlugName)): #and os.path.isfile(_self.ConfNodeXmlFilePath(PlugName)):
+ #Load the confnode.xml file into parameters members
+ _self.LoadXMLParams(NewPlugName)
+ # Basic check. Better to fail immediately.
+ if (_self.BaseParams.getName() != NewPlugName):
+ raise Exception, _("Project tree layout do not match confnode.xml %s!=%s ")%(NewPlugName, _self.BaseParams.getName())
+
+ # Now, self.PlugPath() should be OK
+
+ # Check that IEC_Channel is not already in use.
+ _self.FindNewIEC_Channel(_self.BaseParams.getIEC_Channel())
+ # Call the confnode real __init__
+ if getattr(PlugClass, "__init__", None):
+ PlugClass.__init__(_self)
+ #Load and init all the childs
+ _self.LoadChilds()
+ #just loaded, nothing to saved
+ _self.ChangesToSave = False
+ else:
+ # If confnode do not have corresponding file/dirs - they will be created on Save
+ _self.PlugMakeDir()
+ # Find an IEC number
+ _self.FindNewIEC_Channel(IEC_Channel)
+ # Call the confnode real __init__
+ if getattr(PlugClass, "__init__", None):
+ PlugClass.__init__(_self)
+ _self.PlugRequestSave()
+ #just created, must be saved
+ _self.ChangesToSave = True
+
+ def _getBuildPath(_self):
+ return self._getBuildPath()
+
+ # Create the object out of the resulting class
+ newConfNodeOpj = FinalPlugClass()
+ # Store it in PluggedChils
+ PluggedChildsWithSameClass.append(newConfNodeOpj)
+
+ return newConfNodeOpj
+
+ def ClearPluggedChilds(self):
+ for child in self.IterChilds():
+ child.ClearPluggedChilds()
+ self.PluggedChilds = {}
+
+ def LoadSTLibrary(self):
+ # Get library blocks if plcopen library exist
+ library_path = self.ConfNodeLibraryFilePath()
+ if os.path.isfile(library_path):
+ self.LibraryControler = PLCControler()
+ self.LibraryControler.OpenXMLFile(library_path)
+ self.LibraryControler.ClearConfNodeTypes()
+ self.LibraryControler.AddConfNodeTypesList(self.ParentsTypesFactory())
+
+ def LoadXMLParams(self, PlugName = None):
+ methode_name = os.path.join(self.PlugPath(PlugName), "methods.py")
+ if os.path.isfile(methode_name):
+ execfile(methode_name)
+
+ # Get the base xml tree
+ if self.MandatoryParams:
+ try:
+ basexmlfile = open(self.ConfNodeBaseXmlFilePath(PlugName), 'r')
+ basetree = minidom.parse(basexmlfile)
+ self.MandatoryParams[1].loadXMLTree(basetree.childNodes[0])
+ basexmlfile.close()
+ except Exception, exc:
+ self.GetPlugRoot().logger.write_error(_("Couldn't load confnode base parameters %s :\n %s") % (PlugName, str(exc)))
+ self.GetPlugRoot().logger.write_error(traceback.format_exc())
+
+ # Get the xml tree
+ if self.PlugParams:
+ try:
+ xmlfile = open(self.ConfNodeXmlFilePath(PlugName), 'r')
+ tree = minidom.parse(xmlfile)
+ self.PlugParams[1].loadXMLTree(tree.childNodes[0])
+ xmlfile.close()
+ except Exception, exc:
+ self.GetPlugRoot().logger.write_error(_("Couldn't load confnode parameters %s :\n %s") % (PlugName, str(exc)))
+ self.GetPlugRoot().logger.write_error(traceback.format_exc())
+
+ def LoadChilds(self):
+ # Iterate over all PlugName@PlugType in confnode directory, and try to open them
+ for PlugDir in os.listdir(self.PlugPath()):
+ if os.path.isdir(os.path.join(self.PlugPath(), PlugDir)) and \
+ PlugDir.count(NameTypeSeparator) == 1:
+ pname, ptype = PlugDir.split(NameTypeSeparator)
+ try:
+ self.PlugAddChild(pname, ptype)
+ except Exception, exc:
+ self.GetPlugRoot().logger.write_error(_("Could not add child \"%s\", type %s :\n%s\n")%(pname, ptype, str(exc)))
+ self.GetPlugRoot().logger.write_error(traceback.format_exc())
+
+ def EnableMethod(self, method, value):
+ for d in self.ConfNodeMethods:
+ if d["method"]==method:
+ d["enabled"]=value
+ return True
+ return False
+
+ def ShowMethod(self, method, value):
+ for d in self.ConfNodeMethods:
+ if d["method"]==method:
+ d["shown"]=value
+ return True
+ return False
+
+ def CallMethod(self, method):
+ for d in self.ConfNodeMethods:
+ if d["method"]==method and d.get("enabled", True) and d.get("shown", True):
+ getattr(self, method)()
+
+def _GetClassFunction(name):
+ def GetRootClass():
+ return getattr(__import__("confnodes." + name), name).RootClass
+ return GetRootClass
+
+
+####################################################################################
+####################################################################################
+####################################################################################
+################################### ROOT ######################################
+####################################################################################
+####################################################################################
+####################################################################################
+
+if wx.Platform == '__WXMSW__':
+ exe_ext=".exe"
+else:
+ exe_ext=""
+
+# import for project creation timestamping
+from threading import Timer, Lock, Thread, Semaphore
+from time import localtime
+from datetime import datetime
+# import necessary stuff from PLCOpenEditor
+from PLCOpenEditor import PLCOpenEditor, ProjectDialog
+from TextViewer import TextViewer
+from plcopen.structures import IEC_KEYWORDS, TypeHierarchy_list
+
+
+import re, tempfile
+import targets
+from targets.typemapping import DebugTypesSize
+
+import connectors
+from discovery import DiscoveryDialog
+from weakref import WeakKeyDictionary
+
+MATIEC_ERROR_MODEL = re.compile(".*\.st:(\d+)-(\d+)\.\.(\d+)-(\d+): error : (.*)$")
+
+DEBUG_RETRIES_WARN = 3
+DEBUG_RETRIES_REREGISTER = 4
+
+class ConfigTreeRoot(ConfigTreeNode, PLCControler):
+ """
+ This class define Root object of the confnode tree.
+ It is responsible of :
+ - Managing project directory
+ - Building project
+ - Handling PLCOpenEditor controler and view
+ - Loading user confnodes and instanciante them as childs
+ - ...
+
+ """
+
+ # For root object, available Childs Types are modules of the confnode packages.
+ PlugChildsTypes = [(name, _GetClassFunction(name), help) for name, help in zip(confnodes.__all__,confnodes.helps)]
+
+ XSD = """
+
+
+
+
+
+
+
+ """+targets.targetchoices+"""
+
+
+
+
+
+
+
+
+
+ """
+
+ def __init__(self, frame, logger):
+ PLCControler.__init__(self)
+
+ self.MandatoryParams = None
+ self.SetAppFrame(frame, logger)
+ self._builder = None
+ self._connector = None
+
+ self.iec2c_path = os.path.join(base_folder, "matiec", "iec2c"+exe_ext)
+ self.ieclib_path = os.path.join(base_folder, "matiec", "lib")
+
+ # Setup debug information
+ self.IECdebug_datas = {}
+ self.IECdebug_lock = Lock()
+
+ self.DebugTimer=None
+ self.ResetIECProgramsAndVariables()
+
+ #This method are not called here... but in NewProject and OpenProject
+ #self._AddParamsMembers()
+ #self.PluggedChilds = {}
+
+ # In both new or load scenario, no need to save
+ self.ChangesToSave = False
+ # root have no parent
+ self.PlugParent = None
+ # Keep track of the confnode type name
+ self.PlugType = "Beremiz"
+ self.PluggedChilds = {}
+ # After __init__ root confnode is not valid
+ self.ProjectPath = None
+ self._setBuildPath(None)
+ self.DebugThread = None
+ self.debug_break = False
+ self.previous_plcstate = None
+ # copy ConfNodeMethods so that it can be later customized
+ self.ConfNodeMethods = [dic.copy() for dic in self.ConfNodeMethods]
+ self.LoadSTLibrary()
+
+ def __del__(self):
+ if self.DebugTimer:
+ self.DebugTimer.cancel()
+ self.KillDebugThread()
+
+ def SetAppFrame(self, frame, logger):
+ self.AppFrame = frame
+ self.logger = logger
+ self.StatusTimer = None
+
+ if frame is not None:
+ # Timer to pull PLC status
+ ID_STATUSTIMER = wx.NewId()
+ self.StatusTimer = wx.Timer(self.AppFrame, ID_STATUSTIMER)
+ self.AppFrame.Bind(wx.EVT_TIMER, self.PullPLCStatusProc, self.StatusTimer)
+
+ self.RefreshConfNodesBlockLists()
+
+ def ResetAppFrame(self, logger):
+ if self.AppFrame is not None:
+ self.AppFrame.Unbind(wx.EVT_TIMER, self.StatusTimer)
+ self.StatusTimer = None
+ self.AppFrame = None
+
+ self.logger = logger
+
+ def ConfNodeLibraryFilePath(self):
+ return os.path.join(os.path.split(__file__)[0], "pous.xml")
+
+ def PlugTestModified(self):
+ return self.ChangesToSave or not self.ProjectIsSaved()
+
+ def PlugFullName(self):
+ return ""
+
+ def GetPlugRoot(self):
+ return self
+
+ def GetIECLibPath(self):
+ return self.ieclib_path
+
+ def GetIEC2cPath(self):
+ return self.iec2c_path
+
+ def GetCurrentLocation(self):
+ return ()
+
+ def GetCurrentName(self):
+ return ""
+
+ def _GetCurrentName(self):
+ return ""
+
+ def GetProjectPath(self):
+ return self.ProjectPath
+
+ def GetProjectName(self):
+ return os.path.split(self.ProjectPath)[1]
+
+ def GetDefaultTargetName(self):
+ if wx.Platform == '__WXMSW__':
+ return "Win32"
+ else:
+ return "Linux"
+
+ def GetTarget(self):
+ target = self.BeremizRoot.getTargetType()
+ if target.getcontent() is None:
+ target = self.Classes["BeremizRoot_TargetType"]()
+ target_name = self.GetDefaultTargetName()
+ target.setcontent({"name": target_name, "value": self.Classes["TargetType_%s"%target_name]()})
+ return target
+
+ def GetParamsAttributes(self, path = None):
+ params = ConfigTreeNode.GetParamsAttributes(self, path)
+ if params[0]["name"] == "BeremizRoot":
+ for child in params[0]["children"]:
+ if child["name"] == "TargetType" and child["value"] == '':
+ child.update(self.GetTarget().getElementInfos("TargetType"))
+ return params
+
+ def SetParamsAttribute(self, path, value):
+ if path.startswith("BeremizRoot.TargetType.") and self.BeremizRoot.getTargetType().getcontent() is None:
+ self.BeremizRoot.setTargetType(self.GetTarget())
+ return ConfigTreeNode.SetParamsAttribute(self, path, value)
+
+ # helper func to check project path write permission
+ def CheckProjectPathPerm(self, dosave=True):
+ if CheckPathPerm(self.ProjectPath):
+ return True
+ dialog = wx.MessageDialog(self.AppFrame,
+ _('You must have permission to work on the project\nWork on a project copy ?'),
+ _('Error'),
+ wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
+ answer = dialog.ShowModal()
+ dialog.Destroy()
+ if answer == wx.ID_YES:
+ if self.SaveProjectAs():
+ self.AppFrame.RefreshAll()
+ self.AppFrame.RefreshTitle()
+ self.AppFrame.RefreshFileMenu()
+ return True
+ return False
+
+ def NewProject(self, ProjectPath, BuildPath=None):
+ """
+ Create a new project in an empty folder
+ @param ProjectPath: path of the folder where project have to be created
+ @param PLCParams: properties of the PLCOpen program created
+ """
+ # Verify that chosen folder is empty
+ if not os.path.isdir(ProjectPath) or len(os.listdir(ProjectPath)) > 0:
+ return _("Chosen folder isn't empty. You can't use it for a new project!")
+
+ dialog = ProjectDialog(self.AppFrame)
+ if dialog.ShowModal() == wx.ID_OK:
+ values = dialog.GetValues()
+ values["creationDateTime"] = datetime(*localtime()[:6])
+ dialog.Destroy()
+ else:
+ dialog.Destroy()
+ return _("Project not created")
+
+ # Create PLCOpen program
+ self.CreateNewProject(values)
+ # Change XSD into class members
+ self._AddParamsMembers()
+ self.PluggedChilds = {}
+ # Keep track of the root confnode (i.e. project path)
+ self.ProjectPath = ProjectPath
+ self._setBuildPath(BuildPath)
+ # get confnodes bloclist (is that usefull at project creation?)
+ self.RefreshConfNodesBlockLists()
+ # this will create files base XML files
+ self.SaveProject()
+ return None
+
+ def LoadProject(self, ProjectPath, BuildPath=None):
+ """
+ Load a project contained in a folder
+ @param ProjectPath: path of the project folder
+ """
+ if os.path.basename(ProjectPath) == "":
+ ProjectPath = os.path.dirname(ProjectPath)
+ # Verify that project contains a PLCOpen program
+ plc_file = os.path.join(ProjectPath, "plc.xml")
+ if not os.path.isfile(plc_file):
+ return _("Chosen folder doesn't contain a program. It's not a valid project!")
+ # Load PLCOpen file
+ result = self.OpenXMLFile(plc_file)
+ if result:
+ return result
+ # Change XSD into class members
+ self._AddParamsMembers()
+ self.PluggedChilds = {}
+ # Keep track of the root confnode (i.e. project path)
+ self.ProjectPath = ProjectPath
+ self._setBuildPath(BuildPath)
+ # If dir have already be made, and file exist
+ if os.path.isdir(self.PlugPath()) and os.path.isfile(self.ConfNodeXmlFilePath()):
+ #Load the confnode.xml file into parameters members
+ result = self.LoadXMLParams()
+ if result:
+ return result
+ #Load and init all the childs
+ self.LoadChilds()
+ self.RefreshConfNodesBlockLists()
+
+ if os.path.exists(self._getBuildPath()):
+ self.EnableMethod("_Clean", True)
+
+ if os.path.isfile(self._getIECrawcodepath()):
+ self.ShowMethod("_showIECcode", True)
+
+ return None
+
+ def CloseProject(self):
+ self.ClearPluggedChilds()
+ self.ResetAppFrame(None)
+
+ def SaveProject(self):
+ if self.CheckProjectPathPerm(False):
+ self.SaveXMLFile(os.path.join(self.ProjectPath, 'plc.xml'))
+ result = self.PlugRequestSave()
+ if result:
+ self.logger.write_error(result)
+
+ def SaveProjectAs(self, dosave=True):
+ # Ask user to choose a path with write permissions
+ if wx.Platform == '__WXMSW__':
+ path = os.getenv("USERPROFILE")
+ else:
+ path = os.getenv("HOME")
+ dirdialog = wx.DirDialog(self.AppFrame , _("Choose a directory to save project"), path, wx.DD_NEW_DIR_BUTTON)
+ answer = dirdialog.ShowModal()
+ dirdialog.Destroy()
+ if answer == wx.ID_OK:
+ newprojectpath = dirdialog.GetPath()
+ if os.path.isdir(newprojectpath):
+ self.ProjectPath = newprojectpath
+ if dosave:
+ self.SaveProject()
+ self._setBuildPath(self.BuildPath)
+ return True
+ return False
+
+ # Update PLCOpenEditor ConfNode Block types from loaded confnodes
+ def RefreshConfNodesBlockLists(self):
+ if getattr(self, "PluggedChilds", None) is not None:
+ self.ClearConfNodeTypes()
+ self.AddConfNodeTypesList(self.ConfNodesTypesFactory())
+ if self.AppFrame is not None:
+ self.AppFrame.RefreshLibraryPanel()
+ self.AppFrame.RefreshEditor()
+
+ # Update a PLCOpenEditor Pou variable location
+ def UpdateProjectVariableLocation(self, old_leading, new_leading):
+ self.Project.updateElementAddress(old_leading, new_leading)
+ self.BufferProject()
+ if self.AppFrame is not None:
+ self.AppFrame.RefreshTitle()
+ self.AppFrame.RefreshInstancesTree()
+ self.AppFrame.RefreshFileMenu()
+ self.AppFrame.RefreshEditMenu()
+ self.AppFrame.RefreshEditor()
+
+ def GetVariableLocationTree(self):
+ '''
+ This function is meant to be overridden by confnodes.
+
+ It should returns an list of dictionaries
+
+ - IEC_type is an IEC type like BOOL/BYTE/SINT/...
+ - location is a string of this variable's location, like "%IX0.0.0"
+ '''
+ children = []
+ for child in self.IECSortedChilds():
+ children.append(child.GetVariableLocationTree())
+ return children
+
+ def ConfNodePath(self):
+ return os.path.join(os.path.split(__file__)[0], "confnodes")
+
+ def PlugPath(self, PlugName=None):
+ return self.ProjectPath
+
+ def ConfNodeXmlFilePath(self, PlugName=None):
+ return os.path.join(self.PlugPath(PlugName), "beremiz.xml")
+
+ def ParentsTypesFactory(self):
+ return self.ConfNodeTypesFactory()
+
+ def _setBuildPath(self, buildpath):
+ if CheckPathPerm(buildpath):
+ self.BuildPath = buildpath
+ else:
+ self.BuildPath = None
+ self.BuildPath = buildpath
+ self.DefaultBuildPath = None
+ if self._builder is not None:
+ self._builder.SetBuildPath(self._getBuildPath())
+
+ def _getBuildPath(self):
+ # BuildPath is defined by user
+ if self.BuildPath is not None:
+ return self.BuildPath
+ # BuildPath isn't defined by user but already created by default
+ if self.DefaultBuildPath is not None:
+ return self.DefaultBuildPath
+ # Create a build path in project folder if user has permissions
+ if CheckPathPerm(self.ProjectPath):
+ self.DefaultBuildPath = os.path.join(self.ProjectPath, "build")
+ # Create a build path in temp folder
+ else:
+ self.DefaultBuildPath = os.path.join(tempfile.mkdtemp(), os.path.basename(self.ProjectPath), "build")
+
+ if not os.path.exists(self.DefaultBuildPath):
+ os.makedirs(self.DefaultBuildPath)
+ return self.DefaultBuildPath
+
+ def _getExtraFilesPath(self):
+ return os.path.join(self._getBuildPath(), "extra_files")
+
+ def _getIECcodepath(self):
+ # define name for IEC code file
+ return os.path.join(self._getBuildPath(), "plc.st")
+
+ def _getIECgeneratedcodepath(self):
+ # define name for IEC generated code file
+ return os.path.join(self._getBuildPath(), "generated_plc.st")
+
+ def _getIECrawcodepath(self):
+ # define name for IEC raw code file
+ return os.path.join(self.PlugPath(), "raw_plc.st")
+
+ def GetLocations(self):
+ locations = []
+ filepath = os.path.join(self._getBuildPath(),"LOCATED_VARIABLES.h")
+ if os.path.isfile(filepath):
+ # IEC2C compiler generate a list of located variables : LOCATED_VARIABLES.h
+ location_file = open(os.path.join(self._getBuildPath(),"LOCATED_VARIABLES.h"))
+ # each line of LOCATED_VARIABLES.h declares a located variable
+ lines = [line.strip() for line in location_file.readlines()]
+ # This regular expression parses the lines genereated by IEC2C
+ LOCATED_MODEL = re.compile("__LOCATED_VAR\((?P[A-Z]*),(?P[_A-Za-z0-9]*),(?P[QMI])(?:,(?P[XBWDL]))?,(?P[,0-9]*)\)")
+ for line in lines:
+ # If line match RE,
+ result = LOCATED_MODEL.match(line)
+ if result:
+ # Get the resulting dict
+ resdict = result.groupdict()
+ # rewrite string for variadic location as a tuple of integers
+ resdict['LOC'] = tuple(map(int,resdict['LOC'].split(',')))
+ # set located size to 'X' if not given
+ if not resdict['SIZE']:
+ resdict['SIZE'] = 'X'
+ # finally store into located variable list
+ locations.append(resdict)
+ return locations
+
+ def _Generate_SoftPLC(self):
+ """
+ Generate SoftPLC ST/IL/SFC code out of PLCOpenEditor controller, and compile it with IEC2C
+ @param buildpath: path where files should be created
+ """
+
+ # Update PLCOpenEditor ConfNode Block types before generate ST code
+ self.RefreshConfNodesBlockLists()
+
+ self.logger.write(_("Generating SoftPLC IEC-61131 ST/IL/SFC code...\n"))
+ buildpath = self._getBuildPath()
+ # ask PLCOpenEditor controller to write ST/IL/SFC code file
+ program, errors, warnings = self.GenerateProgram(self._getIECgeneratedcodepath())
+ if len(warnings) > 0:
+ self.logger.write_warning(_("Warnings in ST/IL/SFC code generator :\n"))
+ for warning in warnings:
+ self.logger.write_warning("%s\n"%warning)
+ if len(errors) > 0:
+ # Failed !
+ self.logger.write_error(_("Error in ST/IL/SFC code generator :\n%s\n")%errors[0])
+ return False
+ plc_file = open(self._getIECcodepath(), "w")
+ # Add ST Library from confnodes
+ plc_file.write(self.ConfNodesSTLibraryFactory())
+ if os.path.isfile(self._getIECrawcodepath()):
+ plc_file.write(open(self._getIECrawcodepath(), "r").read())
+ plc_file.write("\n")
+ plc_file.close()
+ plc_file = open(self._getIECcodepath(), "r")
+ self.ProgramOffset = 0
+ for line in plc_file.xreadlines():
+ self.ProgramOffset += 1
+ plc_file.close()
+ plc_file = open(self._getIECcodepath(), "a")
+ plc_file.write(open(self._getIECgeneratedcodepath(), "r").read())
+ plc_file.close()
+
+ self.logger.write(_("Compiling IEC Program into C code...\n"))
+
+ # Now compile IEC code into many C files
+ # files are listed to stdout, and errors to stderr.
+ status, result, err_result = ProcessLogger(
+ self.logger,
+ "\"%s\" -f -I \"%s\" -T \"%s\" \"%s\""%(
+ self.iec2c_path,
+ self.ieclib_path,
+ buildpath,
+ self._getIECcodepath()),
+ no_stdout=True, no_stderr=True).spin()
+ if status:
+ # Failed !
+
+ # parse iec2c's error message. if it contains a line number,
+ # then print those lines from the generated IEC file.
+ for err_line in err_result.split('\n'):
+ self.logger.write_warning(err_line + "\n")
+
+ m_result = MATIEC_ERROR_MODEL.match(err_line)
+ if m_result is not None:
+ first_line, first_column, last_line, last_column, error = m_result.groups()
+ first_line, last_line = int(first_line), int(last_line)
+
+ last_section = None
+ f = open(self._getIECcodepath())
+
+ for i, line in enumerate(f.readlines()):
+ i = i + 1
+ if line[0] not in '\t \r\n':
+ last_section = line
+
+ if first_line <= i <= last_line:
+ if last_section is not None:
+ self.logger.write_warning("In section: " + last_section)
+ last_section = None # only write section once
+ self.logger.write_warning("%04d: %s" % (i, line))
+
+ f.close()
+
+ self.logger.write_error(_("Error : IEC to C compiler returned %d\n")%status)
+ return False
+
+ # Now extract C files of stdout
+ C_files = [ fname for fname in result.splitlines() if fname[-2:]==".c" or fname[-2:]==".C" ]
+ # remove those that are not to be compiled because included by others
+ C_files.remove("POUS.c")
+ if not C_files:
+ self.logger.write_error(_("Error : At least one configuration and one resource must be declared in PLC !\n"))
+ return False
+ # transform those base names to full names with path
+ C_files = map(lambda filename:os.path.join(buildpath, filename), C_files)
+ self.logger.write(_("Extracting Located Variables...\n"))
+ # Keep track of generated located variables for later use by self._Generate_C
+ self.PLCGeneratedLocatedVars = self.GetLocations()
+ # Keep track of generated C files for later use by self.PlugGenerate_C
+ self.PLCGeneratedCFiles = C_files
+ # compute CFLAGS for plc
+ self.plcCFLAGS = "\"-I"+self.ieclib_path+"\""
+ return True
+
+ def GetBuilder(self):
+ """
+ Return a Builder (compile C code into machine code)
+ """
+ # Get target, module and class name
+ targetname = self.GetTarget().getcontent()["name"]
+ modulename = "targets." + targetname
+ classname = targetname + "_target"
+
+ # Get module reference
+ try :
+ targetmodule = getattr(__import__(modulename), targetname)
+
+ except Exception, msg:
+ self.logger.write_error(_("Can't find module for target %s!\n")%targetname)
+ self.logger.write_error(str(msg))
+ return None
+
+ # Get target class
+ targetclass = getattr(targetmodule, classname)
+
+ # if target already
+ if self._builder is None or not isinstance(self._builder,targetclass):
+ # Get classname instance
+ self._builder = targetclass(self)
+ return self._builder
+
+ def ResetBuildMD5(self):
+ builder=self.GetBuilder()
+ if builder is not None:
+ builder.ResetBinaryCodeMD5()
+ self.EnableMethod("_Transfer", False)
+
+ def GetLastBuildMD5(self):
+ builder=self.GetBuilder()
+ if builder is not None:
+ return builder.GetBinaryCodeMD5()
+ else:
+ return None
+
+ #######################################################################
+ #
+ # C CODE GENERATION METHODS
+ #
+ #######################################################################
+
+ def PlugGenerate_C(self, buildpath, locations):
+ """
+ Return C code generated by iec2c compiler
+ when _generate_softPLC have been called
+ @param locations: ignored
+ @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
+ """
+
+ return ([(C_file_name, self.plcCFLAGS)
+ for C_file_name in self.PLCGeneratedCFiles ],
+ "", # no ldflags
+ False) # do not expose retreive/publish calls
+
+ def ResetIECProgramsAndVariables(self):
+ """
+ Reset variable and program list that are parsed from
+ CSV file generated by IEC2C compiler.
+ """
+ self._ProgramList = None
+ self._VariablesList = None
+ self._IECPathToIdx = {}
+ self._Ticktime = 0
+ self.TracedIECPath = []
+
+ def GetIECProgramsAndVariables(self):
+ """
+ Parse CSV-like file VARIABLES.csv resulting from IEC2C compiler.
+ Each section is marked with a line staring with '//'
+ list of all variables used in various POUs
+ """
+ if self._ProgramList is None or self._VariablesList is None:
+ try:
+ csvfile = os.path.join(self._getBuildPath(),"VARIABLES.csv")
+ # describes CSV columns
+ ProgramsListAttributeName = ["num", "C_path", "type"]
+ VariablesListAttributeName = ["num", "vartype", "IEC_path", "C_path", "type"]
+ self._ProgramList = []
+ self._VariablesList = []
+ self._IECPathToIdx = {}
+
+ # Separate sections
+ ListGroup = []
+ for line in open(csvfile,'r').xreadlines():
+ strippedline = line.strip()
+ if strippedline.startswith("//"):
+ # Start new section
+ ListGroup.append([])
+ elif len(strippedline) > 0 and len(ListGroup) > 0:
+ # append to this section
+ ListGroup[-1].append(strippedline)
+
+ # first section contains programs
+ for line in ListGroup[0]:
+ # Split and Maps each field to dictionnary entries
+ attrs = dict(zip(ProgramsListAttributeName,line.strip().split(';')))
+ # Truncate "C_path" to remove conf an ressources names
+ attrs["C_path"] = '__'.join(attrs["C_path"].split(".",2)[1:])
+ # Push this dictionnary into result.
+ self._ProgramList.append(attrs)
+
+ # second section contains all variables
+ for line in ListGroup[1]:
+ # Split and Maps each field to dictionnary entries
+ attrs = dict(zip(VariablesListAttributeName,line.strip().split(';')))
+ # Truncate "C_path" to remove conf an ressources names
+ parts = attrs["C_path"].split(".",2)
+ if len(parts) > 2:
+ attrs["C_path"] = '__'.join(parts[1:])
+ else:
+ attrs["C_path"] = '__'.join(parts)
+ # Push this dictionnary into result.
+ self._VariablesList.append(attrs)
+ # Fill in IEC<->C translation dicts
+ IEC_path=attrs["IEC_path"]
+ Idx=int(attrs["num"])
+ self._IECPathToIdx[IEC_path]=(Idx, attrs["type"])
+
+ # third section contains ticktime
+ if len(ListGroup) > 2:
+ self._Ticktime = int(ListGroup[2][0])
+
+ except Exception,e:
+ self.logger.write_error(_("Cannot open/parse VARIABLES.csv!\n"))
+ self.logger.write_error(traceback.format_exc())
+ self.ResetIECProgramsAndVariables()
+ return False
+
+ return True
+
+ def Generate_plc_debugger(self):
+ """
+ Generate trace/debug code out of PLC variable list
+ """
+ self.GetIECProgramsAndVariables()
+
+ # prepare debug code
+ debug_code = targets.code("plc_debug") % {
+ "buffer_size": reduce(lambda x, y: x + y, [DebugTypesSize.get(v["type"], 0) for v in self._VariablesList], 0),
+ "programs_declarations":
+ "\n".join(["extern %(type)s %(C_path)s;"%p for p in self._ProgramList]),
+ "extern_variables_declarations":"\n".join([
+ {"EXT":"extern __IEC_%(type)s_p %(C_path)s;",
+ "IN":"extern __IEC_%(type)s_p %(C_path)s;",
+ "MEM":"extern __IEC_%(type)s_p %(C_path)s;",
+ "OUT":"extern __IEC_%(type)s_p %(C_path)s;",
+ "VAR":"extern __IEC_%(type)s_t %(C_path)s;"}[v["vartype"]]%v
+ for v in self._VariablesList if v["vartype"] != "FB" and v["C_path"].find('.')<0]),
+ "for_each_variable_do_code":"\n".join([
+ {"EXT":" (*fp)((void*)&%(C_path)s,%(type)s_P_ENUM);\n",
+ "IN":" (*fp)((void*)&%(C_path)s,%(type)s_P_ENUM);\n",
+ "MEM":" (*fp)((void*)&%(C_path)s,%(type)s_O_ENUM);\n",
+ "OUT":" (*fp)((void*)&%(C_path)s,%(type)s_O_ENUM);\n",
+ "VAR":" (*fp)((void*)&%(C_path)s,%(type)s_ENUM);\n"}[v["vartype"]]%v
+ for v in self._VariablesList if v["vartype"] != "FB" and v["type"] in DebugTypesSize ]),
+ "find_variable_case_code":"\n".join([
+ " case %(num)s:\n"%v+
+ " *varp = (void*)&%(C_path)s;\n"%v+
+ {"EXT":" return %(type)s_P_ENUM;\n",
+ "IN":" return %(type)s_P_ENUM;\n",
+ "MEM":" return %(type)s_O_ENUM;\n",
+ "OUT":" return %(type)s_O_ENUM;\n",
+ "VAR":" return %(type)s_ENUM;\n"}[v["vartype"]]%v
+ for v in self._VariablesList if v["vartype"] != "FB" and v["type"] in DebugTypesSize ])}
+
+ return debug_code
+
+ def Generate_plc_common_main(self):
+ """
+ Use confnodes layout given in LocationCFilesAndCFLAGS to
+ generate glue code that dispatch calls to all confnodes
+ """
+ # filter location that are related to code that will be called
+ # in retreive, publish, init, cleanup
+ locstrs = map(lambda x:"_".join(map(str,x)),
+ [loc for loc,Cfiles,DoCalls in self.LocationCFilesAndCFLAGS if loc and DoCalls])
+
+ # Generate main, based on template
+ if self.BeremizRoot.getEnable_ConfNodes():
+ plc_main_code = targets.code("plc_common_main") % {
+ "calls_prototypes":"\n".join([(
+ "int __init_%(s)s(int argc,char **argv);\n"+
+ "void __cleanup_%(s)s(void);\n"+
+ "void __retrieve_%(s)s(void);\n"+
+ "void __publish_%(s)s(void);")%{'s':locstr} for locstr in locstrs]),
+ "retrieve_calls":"\n ".join([
+ "__retrieve_%s();"%locstrs[i-1] for i in xrange(len(locstrs), 0, -1)]),
+ "publish_calls":"\n ".join([ #Call publish in reverse order
+ "__publish_%s();"%locstr for locstr in locstrs]),
+ "init_calls":"\n ".join([
+ "init_level=%d; "%(i+1)+
+ "if((res = __init_%s(argc,argv))){"%locstr +
+ #"printf(\"%s\"); "%locstr + #for debug
+ "return res;}" for i,locstr in enumerate(locstrs)]),
+ "cleanup_calls":"\n ".join([
+ "if(init_level >= %d) "%i+
+ "__cleanup_%s();"%locstrs[i-1] for i in xrange(len(locstrs), 0, -1)])
+ }
+ else:
+ plc_main_code = targets.code("plc_common_main") % {
+ "calls_prototypes":"\n",
+ "retrieve_calls":"\n",
+ "publish_calls":"\n",
+ "init_calls":"\n",
+ "cleanup_calls":"\n"
+ }
+ plc_main_code += targets.targetcode(self.GetTarget().getcontent()["name"])
+ return plc_main_code
+
+
+ def _Build(self):
+ """
+ Method called by user to (re)build SoftPLC and confnode tree
+ """
+ if self.AppFrame is not None:
+ self.AppFrame.ClearErrors()
+
+ buildpath = self._getBuildPath()
+
+ # Eventually create build dir
+ if not os.path.exists(buildpath):
+ os.mkdir(buildpath)
+ # There is something to clean
+ self.EnableMethod("_Clean", True)
+
+ self.logger.flush()
+ self.logger.write(_("Start build in %s\n") % buildpath)
+
+ # Generate SoftPLC IEC code
+ IECGenRes = self._Generate_SoftPLC()
+ self.ShowMethod("_showIECcode", True)
+
+ # If IEC code gen fail, bail out.
+ if not IECGenRes:
+ self.logger.write_error(_("IEC-61131-3 code generation failed !\n"))
+ self.ResetBuildMD5()
+ return False
+
+ # Reset variable and program list that are parsed from
+ # CSV file generated by IEC2C compiler.
+ self.ResetIECProgramsAndVariables()
+
+ # Generate C code and compilation params from confnode hierarchy
+ self.logger.write(_("Generating confnodes C code\n"))
+ try:
+ self.LocationCFilesAndCFLAGS, self.LDFLAGS, ExtraFiles = self._Generate_C(
+ buildpath,
+ self.PLCGeneratedLocatedVars)
+ except Exception, exc:
+ self.logger.write_error(_("ConfNodes code generation failed !\n"))
+ self.logger.write_error(traceback.format_exc())
+ self.ResetBuildMD5()
+ return False
+
+ # Get temporary directory path
+ extrafilespath = self._getExtraFilesPath()
+ # Remove old directory
+ if os.path.exists(extrafilespath):
+ shutil.rmtree(extrafilespath)
+ # Recreate directory
+ os.mkdir(extrafilespath)
+ # Then write the files
+ for fname,fobject in ExtraFiles:
+ fpath = os.path.join(extrafilespath,fname)
+ open(fpath, "wb").write(fobject.read())
+ # Now we can forget ExtraFiles (will close files object)
+ del ExtraFiles
+
+ # Template based part of C code generation
+ # files are stacked at the beginning, as files of confnode tree root
+ for generator, filename, name in [
+ # debugger code
+ (self.Generate_plc_debugger, "plc_debugger.c", "Debugger"),
+ # init/cleanup/retrieve/publish, run and align code
+ (self.Generate_plc_common_main,"plc_common_main.c","Common runtime")]:
+ try:
+ # Do generate
+ code = generator()
+ if code is None:
+ raise
+ code_path = os.path.join(buildpath,filename)
+ open(code_path, "w").write(code)
+ # Insert this file as first file to be compiled at root confnode
+ self.LocationCFilesAndCFLAGS[0][1].insert(0,(code_path, self.plcCFLAGS))
+ except Exception, exc:
+ self.logger.write_error(name+_(" generation failed !\n"))
+ self.logger.write_error(traceback.format_exc())
+ self.ResetBuildMD5()
+ return False
+
+ self.logger.write(_("C code generated successfully.\n"))
+
+ # Get current or fresh builder
+ builder = self.GetBuilder()
+ if builder is None:
+ self.logger.write_error(_("Fatal : cannot get builder.\n"))
+ self.ResetBuildMD5()
+ return False
+
+ # Build
+ try:
+ if not builder.build() :
+ self.logger.write_error(_("C Build failed.\n"))
+ return False
+ except Exception, exc:
+ self.logger.write_error(_("C Build crashed !\n"))
+ self.logger.write_error(traceback.format_exc())
+ self.ResetBuildMD5()
+ return False
+
+ self.logger.write(_("Successfully built.\n"))
+ # Update GUI status about need for transfer
+ self.CompareLocalAndRemotePLC()
+ return True
+
+ def ShowError(self, logger, from_location, to_location):
+ chunk_infos = self.GetChunkInfos(from_location, to_location)
+ for infos, (start_row, start_col) in chunk_infos:
+ start = (from_location[0] - start_row, from_location[1] - start_col)
+ end = (to_location[0] - start_row, to_location[1] - start_col)
+ #print from_location, to_location, start_row, start_col, start, end
+ if self.AppFrame is not None:
+ self.AppFrame.ShowError(infos, start, end)
+
+ def _showIECcode(self):
+ self._OpenView("IEC code")
+
+ def _editIECrawcode(self):
+ self._OpenView("IEC raw code")
+
+ def _OpenView(self, name=None):
+ if name == "IEC code":
+ plc_file = self._getIECcodepath()
+
+ IEC_code_viewer = TextViewer(self.AppFrame.TabsOpened, "", None, None, instancepath=name)
+ #IEC_code_viewer.Enable(False)
+ IEC_code_viewer.SetTextSyntax("ALL")
+ IEC_code_viewer.SetKeywords(IEC_KEYWORDS)
+ try:
+ text = file(plc_file).read()
+ except:
+ text = '(* No IEC code have been generated at that time ! *)'
+ IEC_code_viewer.SetText(text = text)
+ IEC_code_viewer.SetIcon(self.AppFrame.GenerateBitmap("ST"))
+
+ self.AppFrame.EditProjectElement(IEC_code_viewer, name)
+
+ return IEC_code_viewer
+
+ elif name == "IEC raw code":
+ controler = MiniTextControler(self._getIECrawcodepath())
+ IEC_raw_code_viewer = TextViewer(self.AppFrame.TabsOpened, "", None, controler, instancepath=name)
+ #IEC_raw_code_viewer.Enable(False)
+ IEC_raw_code_viewer.SetTextSyntax("ALL")
+ IEC_raw_code_viewer.SetKeywords(IEC_KEYWORDS)
+ IEC_raw_code_viewer.RefreshView()
+ IEC_raw_code_viewer.SetIcon(self.AppFrame.GenerateBitmap("ST"))
+
+ self.AppFrame.EditProjectElement(IEC_raw_code_viewer, name)
+
+ return IEC_raw_code_viewer
+
+ return None
+
+ def _Clean(self):
+ if os.path.isdir(os.path.join(self._getBuildPath())):
+ self.logger.write(_("Cleaning the build directory\n"))
+ shutil.rmtree(os.path.join(self._getBuildPath()))
+ else:
+ self.logger.write_error(_("Build directory already clean\n"))
+ self.ShowMethod("_showIECcode", False)
+ self.EnableMethod("_Clean", False)
+ # kill the builder
+ self._builder = None
+ self.CompareLocalAndRemotePLC()
+
+ ############# Real PLC object access #############
+ def UpdateMethodsFromPLCStatus(self):
+ # Get PLC state : Running or Stopped
+ # TODO : use explicit status instead of boolean
+ status = None
+ if self._connector is not None:
+ status = self._connector.GetPLCstatus()
+ if status is None:
+ self._connector = None
+ status = "Disconnected"
+ if(self.previous_plcstate != status):
+ for args in {
+ "Started" : [("_Run", False),
+ ("_Stop", True)],
+ "Stopped" : [("_Run", True),
+ ("_Stop", False)],
+ "Empty" : [("_Run", False),
+ ("_Stop", False)],
+ "Broken" : [],
+ "Disconnected" :[("_Run", False),
+ ("_Stop", False),
+ ("_Transfer", False),
+ ("_Connect", True),
+ ("_Disconnect", False)],
+ }.get(status,[]):
+ self.ShowMethod(*args)
+ self.previous_plcstate = status
+ return True
+ return False
+
+ def PullPLCStatusProc(self, event):
+ if self._connector is None:
+ self.StatusTimer.Stop()
+ if self.UpdateMethodsFromPLCStatus():
+
+ status = _(self.previous_plcstate)
+ {"Broken": self.logger.write_error,
+ None: lambda x: None}.get(
+ self.previous_plcstate, self.logger.write)(_("PLC is %s\n")%status)
+ self.AppFrame.RefreshAll()
+
+ def RegisterDebugVarToConnector(self):
+ self.DebugTimer=None
+ Idxs = []
+ self.TracedIECPath = []
+ if self._connector is not None:
+ self.IECdebug_lock.acquire()
+ IECPathsToPop = []
+ for IECPath,data_tuple in self.IECdebug_datas.iteritems():
+ WeakCallableDict, data_log, status, fvalue = data_tuple
+ if len(WeakCallableDict) == 0:
+ # Callable Dict is empty.
+ # This variable is not needed anymore!
+ #print "Unused : " + IECPath
+ IECPathsToPop.append(IECPath)
+ elif IECPath != "__tick__":
+ # Convert
+ Idx, IEC_Type = self._IECPathToIdx.get(IECPath,(None,None))
+ if Idx is not None:
+ if IEC_Type in DebugTypesSize:
+ Idxs.append((Idx, IEC_Type, fvalue, IECPath))
+ else:
+ self.logger.write_warning(_("Debug : Unsuppoted type to debug %s\n")%IEC_Type)
+ else:
+ self.logger.write_warning(_("Debug : Unknown variable %s\n")%IECPath)
+ for IECPathToPop in IECPathsToPop:
+ self.IECdebug_datas.pop(IECPathToPop)
+
+ if Idxs:
+ Idxs.sort()
+ self.TracedIECPath = zip(*Idxs)[3]
+ self._connector.SetTraceVariablesList(zip(*zip(*Idxs)[0:3]))
+ else:
+ self.TracedIECPath = []
+ self._connector.SetTraceVariablesList([])
+ self.IECdebug_lock.release()
+
+ #for IEC_path, IECdebug_data in self.IECdebug_datas.iteritems():
+ # print IEC_path, IECdebug_data[0].keys()
+
+ def ReArmDebugRegisterTimer(self):
+ if self.DebugTimer is not None:
+ self.DebugTimer.cancel()
+
+ # Timer to prevent rapid-fire when registering many variables
+ # use wx.CallAfter use keep using same thread. TODO : use wx.Timer instead
+ self.DebugTimer=Timer(0.5,wx.CallAfter,args = [self.RegisterDebugVarToConnector])
+ # Rearm anti-rapid-fire timer
+ self.DebugTimer.start()
+
+ def GetDebugIECVariableType(self, IECPath):
+ Idx, IEC_Type = self._IECPathToIdx.get(IECPath,(None,None))
+ return IEC_Type
+
+ def SubscribeDebugIECVariable(self, IECPath, callableobj, *args, **kwargs):
+ """
+ Dispatching use a dictionnary linking IEC variable paths
+ to a WeakKeyDictionary linking
+ weakly referenced callables to optionnal args
+ """
+ if IECPath != "__tick__" and not self._IECPathToIdx.has_key(IECPath):
+ return None
+
+ self.IECdebug_lock.acquire()
+ # If no entry exist, create a new one with a fresh WeakKeyDictionary
+ IECdebug_data = self.IECdebug_datas.get(IECPath, None)
+ if IECdebug_data is None:
+ IECdebug_data = [
+ WeakKeyDictionary(), # Callables
+ [], # Data storage [(tick, data),...]
+ "Registered", # Variable status
+ None] # Forced value
+ self.IECdebug_datas[IECPath] = IECdebug_data
+
+ IECdebug_data[0][callableobj]=(args, kwargs)
+
+ self.IECdebug_lock.release()
+
+ self.ReArmDebugRegisterTimer()
+
+ return IECdebug_data[1]
+
+ def UnsubscribeDebugIECVariable(self, IECPath, callableobj):
+ #print "Unsubscribe", IECPath, callableobj
+ self.IECdebug_lock.acquire()
+ IECdebug_data = self.IECdebug_datas.get(IECPath, None)
+ if IECdebug_data is not None:
+ IECdebug_data[0].pop(callableobj,None)
+ self.IECdebug_lock.release()
+
+ self.ReArmDebugRegisterTimer()
+
+ def UnsubscribeAllDebugIECVariable(self):
+ self.IECdebug_lock.acquire()
+ IECdebug_data = {}
+ self.IECdebug_lock.release()
+
+ self.ReArmDebugRegisterTimer()
+
+ def ForceDebugIECVariable(self, IECPath, fvalue):
+ if not self.IECdebug_datas.has_key(IECPath):
+ return
+
+ self.IECdebug_lock.acquire()
+
+ # If no entry exist, create a new one with a fresh WeakKeyDictionary
+ IECdebug_data = self.IECdebug_datas.get(IECPath, None)
+ IECdebug_data[2] = "Forced"
+ IECdebug_data[3] = fvalue
+
+ self.IECdebug_lock.release()
+
+ self.ReArmDebugRegisterTimer()
+
+ def ReleaseDebugIECVariable(self, IECPath):
+ if not self.IECdebug_datas.has_key(IECPath):
+ return
+
+ self.IECdebug_lock.acquire()
+
+ # If no entry exist, create a new one with a fresh WeakKeyDictionary
+ IECdebug_data = self.IECdebug_datas.get(IECPath, None)
+ IECdebug_data[2] = "Registered"
+ IECdebug_data[3] = None
+
+ self.IECdebug_lock.release()
+
+ self.ReArmDebugRegisterTimer()
+
+ def CallWeakcallables(self, IECPath, function_name, *cargs):
+ data_tuple = self.IECdebug_datas.get(IECPath, None)
+ if data_tuple is not None:
+ WeakCallableDict, data_log, status, fvalue = data_tuple
+ #data_log.append((debug_tick, value))
+ for weakcallable,(args,kwargs) in WeakCallableDict.iteritems():
+ #print weakcallable, value, args, kwargs
+ function = getattr(weakcallable, function_name, None)
+ if function is not None:
+ if status == "Forced" and cargs[1] == fvalue:
+ function(*(cargs + (True,) + args), **kwargs)
+ else:
+ function(*(cargs + args), **kwargs)
+ # This will block thread if more than one call is waiting
+
+ def GetTicktime(self):
+ return self._Ticktime
+
+ def RemoteExec(self, script, **kwargs):
+ if self._connector is None:
+ return -1, "No runtime connected!"
+ return self._connector.RemoteExec(script, **kwargs)
+
+ def DebugThreadProc(self):
+ """
+ This thread waid PLC debug data, and dispatch them to subscribers
+ """
+ self.debug_break = False
+ debug_getvar_retry = 0
+ while (not self.debug_break) and (self._connector is not None):
+ Trace = self._connector.GetTraceVariables()
+ if(Trace):
+ plc_status, debug_tick, debug_vars = Trace
+ else:
+ plc_status = None
+ debug_getvar_retry += 1
+ #print debug_tick, debug_vars
+ if plc_status == "Started":
+ self.IECdebug_lock.acquire()
+ if len(debug_vars) == len(self.TracedIECPath):
+ if debug_getvar_retry > DEBUG_RETRIES_WARN:
+ self.logger.write(_("... debugger recovered\n"))
+ debug_getvar_retry = 0
+ for IECPath,value in zip(self.TracedIECPath, debug_vars):
+ if value is not None:
+ self.CallWeakcallables(IECPath, "NewValue", debug_tick, value)
+ self.CallWeakcallables("__tick__", "NewDataAvailable")
+ self.IECdebug_lock.release()
+ if debug_getvar_retry == DEBUG_RETRIES_WARN:
+ self.logger.write(_("Waiting debugger to recover...\n"))
+ if debug_getvar_retry == DEBUG_RETRIES_REREGISTER:
+ # re-register debug registry to PLC
+ wx.CallAfter(self.RegisterDebugVarToConnector)
+ if debug_getvar_retry != 0:
+ # Be patient, tollerate PLC to come up before debugging
+ time.sleep(0.1)
+ else:
+ self.debug_break = True
+ self.logger.write(_("Debugger disabled\n"))
+ self.DebugThread = None
+
+ def KillDebugThread(self):
+ tmp_debugthread = self.DebugThread
+ self.debug_break = True
+ if tmp_debugthread is not None:
+ self.logger.writeyield(_("Stopping debugger...\n"))
+ tmp_debugthread.join(timeout=5)
+ if tmp_debugthread.isAlive() and self.logger:
+ self.logger.write_warning(_("Couldn't stop debugger.\n"))
+ else:
+ self.logger.write(_("Debugger stopped.\n"))
+ self.DebugThread = None
+
+ def _connect_debug(self):
+ if self.AppFrame:
+ self.AppFrame.ResetGraphicViewers()
+ self.RegisterDebugVarToConnector()
+ if self.DebugThread is None:
+ self.DebugThread = Thread(target=self.DebugThreadProc)
+ self.DebugThread.start()
+
+ def _Run(self):
+ """
+ Start PLC
+ """
+ if self.GetIECProgramsAndVariables():
+ self._connector.StartPLC()
+ self.logger.write(_("Starting PLC\n"))
+ self._connect_debug()
+ else:
+ self.logger.write_error(_("Couldn't start PLC !\n"))
+ wx.CallAfter(self.UpdateMethodsFromPLCStatus)
+
+ def _Stop(self):
+ """
+ Stop PLC
+ """
+ if self._connector is not None and not self._connector.StopPLC():
+ self.logger.write_error(_("Couldn't stop PLC !\n"))
+
+ # debugthread should die on his own
+ #self.KillDebugThread()
+
+ wx.CallAfter(self.UpdateMethodsFromPLCStatus)
+
+ def _Connect(self):
+ # don't accept re-connetion is already connected
+ if self._connector is not None:
+ self.logger.write_error(_("Already connected. Please disconnect\n"))
+ return
+
+ # Get connector uri
+ uri = self.\
+ BeremizRoot.\
+ getURI_location().\
+ strip()
+
+ # if uri is empty launch discovery dialog
+ if uri == "":
+ # Launch Service Discovery dialog
+ dialog = DiscoveryDialog(self.AppFrame)
+ answer = dialog.ShowModal()
+ uri = dialog.GetURI()
+ dialog.Destroy()
+
+ # Nothing choosed or cancel button
+ if uri is None or answer == wx.ID_CANCEL:
+ self.logger.write_error(_("Connection canceled!\n"))
+ return
+ else:
+ self.\
+ BeremizRoot.\
+ setURI_location(uri)
+
+ # Get connector from uri
+ try:
+ self._connector = connectors.ConnectorFactory(uri, self)
+ except Exception, msg:
+ self.logger.write_error(_("Exception while connecting %s!\n")%uri)
+ self.logger.write_error(traceback.format_exc())
+
+ # Did connection success ?
+ if self._connector is None:
+ # Oups.
+ self.logger.write_error(_("Connection failed to %s!\n")%uri)
+ else:
+ self.ShowMethod("_Connect", False)
+ self.ShowMethod("_Disconnect", True)
+ self.ShowMethod("_Transfer", True)
+
+ self.CompareLocalAndRemotePLC()
+
+ # Init with actual PLC status and print it
+ self.UpdateMethodsFromPLCStatus()
+ if self.previous_plcstate is not None:
+ status = _(self.previous_plcstate)
+ else:
+ status = ""
+ self.logger.write(_("PLC is %s\n")%status)
+
+ # Start the status Timer
+ self.StatusTimer.Start(milliseconds=500, oneShot=False)
+
+ if self.previous_plcstate=="Started":
+ if self.DebugAvailable() and self.GetIECProgramsAndVariables():
+ self.logger.write(_("Debug connect matching running PLC\n"))
+ self._connect_debug()
+ else:
+ self.logger.write_warning(_("Debug do not match PLC - stop/transfert/start to re-enable\n"))
+
+ def CompareLocalAndRemotePLC(self):
+ if self._connector is None:
+ return
+ # We are now connected. Update button status
+ MD5 = self.GetLastBuildMD5()
+ # Check remote target PLC correspondance to that md5
+ if MD5 is not None:
+ if not self._connector.MatchMD5(MD5):
+# self.logger.write_warning(
+# _("Latest build does not match with target, please transfer.\n"))
+ self.EnableMethod("_Transfer", True)
+ else:
+# self.logger.write(
+# _("Latest build matches target, no transfer needed.\n"))
+ self.EnableMethod("_Transfer", True)
+ # warns controller that program match
+ self.ProgramTransferred()
+ #self.EnableMethod("_Transfer", False)
+ else:
+# self.logger.write_warning(
+# _("Cannot compare latest build to target. Please build.\n"))
+ self.EnableMethod("_Transfer", False)
+
+
+ def _Disconnect(self):
+ self._connector = None
+ self.StatusTimer.Stop()
+ wx.CallAfter(self.UpdateMethodsFromPLCStatus)
+
+ def _Transfer(self):
+ # Get the last build PLC's
+ MD5 = self.GetLastBuildMD5()
+
+ # Check if md5 file is empty : ask user to build PLC
+ if MD5 is None :
+ self.logger.write_error(_("Failed : Must build before transfer.\n"))
+ return False
+
+ # Compare PLC project with PLC on target
+ if self._connector.MatchMD5(MD5):
+ self.logger.write(
+ _("Latest build already matches current target. Transfering anyway...\n"))
+
+ # Get temprary directory path
+ extrafilespath = self._getExtraFilesPath()
+ extrafiles = [(name, open(os.path.join(extrafilespath, name),
+ 'rb').read()) \
+ for name in os.listdir(extrafilespath) \
+ if not name=="CVS"]
+
+ # Send PLC on target
+ builder = self.GetBuilder()
+ if builder is not None:
+ data = builder.GetBinaryCode()
+ if data is not None :
+ if self._connector.NewPLC(MD5, data, extrafiles) and self.GetIECProgramsAndVariables():
+ self.UnsubscribeAllDebugIECVariable()
+ self.ProgramTransferred()
+ if self.AppFrame is not None:
+ self.AppFrame.RefreshInstancesTree()
+ self.AppFrame.CloseObsoleteDebugTabs()
+ self.logger.write(_("Transfer completed successfully.\n"))
+ else:
+ self.logger.write_error(_("Transfer failed\n"))
+ else:
+ self.logger.write_error(_("No PLC to transfer (did build succeed ?)\n"))
+
+ wx.CallAfter(self.UpdateMethodsFromPLCStatus)
+
+ ConfNodeMethods = [
+ {"bitmap" : opjimg("Build"),
+ "name" : _("Build"),
+ "tooltip" : _("Build project into build folder"),
+ "method" : "_Build"},
+ {"bitmap" : opjimg("Clean"),
+ "name" : _("Clean"),
+ "enabled" : False,
+ "tooltip" : _("Clean project build folder"),
+ "method" : "_Clean"},
+ {"bitmap" : opjimg("Run"),
+ "name" : _("Run"),
+ "shown" : False,
+ "tooltip" : _("Start PLC"),
+ "method" : "_Run"},
+ {"bitmap" : opjimg("Stop"),
+ "name" : _("Stop"),
+ "shown" : False,
+ "tooltip" : _("Stop Running PLC"),
+ "method" : "_Stop"},
+ {"bitmap" : opjimg("Connect"),
+ "name" : _("Connect"),
+ "tooltip" : _("Connect to the target PLC"),
+ "method" : "_Connect"},
+ {"bitmap" : opjimg("Transfer"),
+ "name" : _("Transfer"),
+ "shown" : False,
+ "tooltip" : _("Transfer PLC"),
+ "method" : "_Transfer"},
+ {"bitmap" : opjimg("Disconnect"),
+ "name" : _("Disconnect"),
+ "shown" : False,
+ "tooltip" : _("Disconnect from PLC"),
+ "method" : "_Disconnect"},
+ {"bitmap" : opjimg("ShowIECcode"),
+ "name" : _("Show code"),
+ "shown" : False,
+ "tooltip" : _("Show IEC code generated by PLCGenerator"),
+ "method" : "_showIECcode"},
+ {"bitmap" : opjimg("editIECrawcode"),
+ "name" : _("Raw IEC code"),
+ "tooltip" : _("Edit raw IEC code added to code generated by PLCGenerator"),
+ "method" : "_editIECrawcode"},
+ ]
diff -r 180e4a7d945c -r 1c23952dbde1 LPCBeremiz.py
--- a/LPCBeremiz.py Thu May 03 19:02:34 2012 +0200
+++ b/LPCBeremiz.py Mon May 07 18:47:29 2012 +0200
@@ -59,25 +59,25 @@
__builtin__.__dict__['_'] = wx.GetTranslation#unicode_translation
from Beremiz import *
-from plugger import PluginsRoot, PlugTemplate, opjimg, connectors
+from ConfigTree import ConfigTreeRoot, ConfigTreeNode, opjimg, connectors
from plcopen.structures import LOCATIONDATATYPES
-from PLCControler import LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP,\
+from PLCControler import LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP,\
LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
from PLCOpenEditor import IDEFrame, ProjectDialog
havecanfestival = False
try:
- from plugins.canfestival import RootClass as CanOpenRootClass
- from plugins.canfestival.canfestival import _SlavePlug, _NodeListPlug, NodeManager
+ from confnodes.canfestival import RootClass as CanOpenRootClass
+ from confnodes.canfestival.canfestival import _SlavePlug, _NodeListPlug, NodeManager
havecanfestival = True
except:
havecanfestival = False
#-------------------------------------------------------------------------------
-# CANFESTIVAL PLUGIN HACK
+# CANFESTIVAL CONFNODE HACK
#-------------------------------------------------------------------------------
-# from plugins.canfestival import canfestival
+# from confnodes.canfestival import canfestival
# class LPC_canfestival_config:
# def getCFLAGS(self, *args):
# return ""
@@ -148,9 +148,9 @@
if group["type"] == LOCATION_GROUP and child in group["children"]:
group["children"].remove(child)
-BUS_TEXT = """/* Code generated by LPCBus plugin */
-
-/* LPCBus plugin includes */
+BUS_TEXT = """/* Code generated by LPCBus confnode */
+
+/* LPCBus confnode includes */
#include "app_glue.h"
#ifdef _WINDOWS_H
#include "iec_types.h"
@@ -160,10 +160,10 @@
%(declare_code)s
-/* LPCBus plugin user variables definition */
+/* LPCBus confnode user variables definition */
%(var_decl)s
-/* LPCBus plugin functions */
+/* LPCBus confnode functions */
int __init_%(location_str)s(int argc,char **argv)
{
%(init_code)s
@@ -240,7 +240,7 @@
def GetVariableLocationTree(self):
return {"name": self.BaseParams.getName(),
- "type": LOCATION_PLUGIN,
+ "type": LOCATION_CONFNODE,
"location": self.GetFullIEC_Channel(),
"icon": self.Icon,
"children": [self._GetVariableLocationTree(self.GetCurrentLocation(), child)
@@ -291,7 +291,7 @@
def PlugGenerate_C(self, buildpath, locations):
"""
Generate C code
- @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
+ @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
@param locations: List of complete variables locations \
[{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
"NAME" : name of the variable (generally "__IW0_1_2" style)
@@ -367,7 +367,7 @@
return [(Gen_Module_path, matiec_flags)],"",True
#-------------------------------------------------------------------------------
-# LPC CanFestival Plugin Class
+# LPC CanFestival ConfNode Class
#-------------------------------------------------------------------------------
if havecanfestival:
@@ -444,7 +444,7 @@
return ""
def LoadChilds(self):
- PlugTemplate.LoadChilds(self)
+ ConfigTreeNode.LoadChilds(self)
if self.GetChildByName("Master") is None:
master = self.PlugAddChild("Master", "CanOpenNode", 0)
@@ -456,7 +456,7 @@
#-------------------------------------------------------------------------------
-# LPCPluginsRoot Class
+# LPCConfigTreeRoot Class
#-------------------------------------------------------------------------------
def mycopytree(src, dst):
@@ -479,9 +479,9 @@
[SIMULATION_MODE, TRANSFER_MODE] = range(2)
-class LPCPluginsRoot(PluginsRoot):
-
- PluginMethods = [
+class LPCConfigTreeRoot(ConfigTreeRoot):
+
+ ConfNodeMethods = [
{"bitmap" : opjimg("Debug"),
"name" : _("Simulate"),
"tooltip" : _("Simulate PLC"),
@@ -510,7 +510,7 @@
def __init__(self, frame, logger, buildpath):
self.OrigBuildPath = buildpath
- PluginsRoot.__init__(self, frame, logger)
+ ConfigTreeRoot.__init__(self, frame, logger)
if havecanfestival:
self.PlugChildsTypes += [("LPCBus", LPCBus, "LPC bus"), ("CanOpen", LPCCanOpen, "CanOpen bus")]
@@ -528,23 +528,23 @@
self.AbortTransferTimer = None
- def PluginLibraryFilePath(self):
+ def ConfNodeLibraryFilePath(self):
if self.OrigBuildPath is not None:
return os.path.join(self.OrigBuildPath, "pous.xml")
else:
- return PluginsRoot.PluginLibraryFilePath(self)
+ return ConfigTreeRoot.ConfNodeLibraryFilePath(self)
def GetProjectName(self):
return self.Project.getname()
def GetDefaultTargetName(self):
if self.CurrentMode == SIMULATION_MODE:
- return PluginsRoot.GetDefaultTargetName(self)
+ return ConfigTreeRoot.GetDefaultTargetName(self)
else:
return "LPC"
def GetTarget(self):
- target = PluginsRoot.GetTarget(self)
+ target = ConfigTreeRoot.GetTarget(self)
if self.CurrentMode != SIMULATION_MODE:
target.getcontent()["value"].setBuildPath(self.BuildPath)
return target
@@ -555,7 +555,7 @@
self.SimulationBuildPath = os.path.join(tempfile.mkdtemp(), os.path.basename(self.ProjectPath), "build")
return self.SimulationBuildPath
else:
- return PluginsRoot._getBuildPath(self)
+ return ConfigTreeRoot._getBuildPath(self)
def _Build(self):
save = self.ProjectTestModified()
@@ -564,7 +564,7 @@
self.AppFrame._Refresh(TITLE, FILEMENU)
if self.BuildPath is not None:
mycopytree(self.OrigBuildPath, self.BuildPath)
- PluginsRoot._Build(self)
+ ConfigTreeRoot._Build(self)
if save:
wx.CallAfter(self.AppFrame.RefreshAll)
@@ -678,7 +678,7 @@
self._AddParamsMembers()
self.PluggedChilds = {}
- # Keep track of the root plugin (i.e. project path)
+ # Keep track of the root confnode (i.e. project path)
self.ProjectPath = ProjectPath
self.BuildPath = self._getBuildPath()
@@ -686,8 +686,8 @@
mycopytree(self.OrigBuildPath, self.BuildPath)
# If dir have already be made, and file exist
- if os.path.isdir(self.PlugPath()) and os.path.isfile(self.PluginXmlFilePath()):
- #Load the plugin.xml file into parameters members
+ if os.path.isdir(self.PlugPath()) and os.path.isfile(self.ConfNodeXmlFilePath()):
+ #Load the confnode.xml file into parameters members
result = self.LoadXMLParams()
if result:
return result
@@ -703,9 +703,9 @@
self.SaveProject()
if wx.GetApp() is None:
- self.RefreshPluginsBlockLists()
+ self.RefreshConfNodesBlockLists()
else:
- wx.CallAfter(self.RefreshPluginsBlockLists)
+ wx.CallAfter(self.RefreshConfNodesBlockLists)
return None
@@ -889,7 +889,7 @@
else:
self.LocationCFilesAndCFLAGS = []
- # plugin asks for some LDFLAGS
+ # confnode asks for some LDFLAGS
if PlugLDFLAGS:
# LDFLAGS can be either string
if type(PlugLDFLAGS)==type(str()):
@@ -901,7 +901,7 @@
self.LDFLAGS=[]
# Template based part of C code generation
- # files are stacked at the beginning, as files of plugin tree root
+ # files are stacked at the beginning, as files of confnode tree root
for generator, filename, name in [
# debugger code
(self.Generate_plc_debugger, "plc_debugger.c", "Debugger"),
@@ -918,7 +918,7 @@
raise
code_path = os.path.join(buildpath,filename)
open(code_path, "w").write(code)
- # Insert this file as first file to be compiled at root plugin
+ # Insert this file as first file to be compiled at root confnode
self.LocationCFilesAndCFLAGS[0][1].insert(0,(code_path, self.plcCFLAGS))
except Exception, exc:
self.logger.write_error(name+_(" generation failed !\n"))
@@ -970,7 +970,7 @@
self.ApplyOnlineMode()
def _Stop(self):
- PluginsRoot._Stop(self)
+ ConfigTreeRoot._Stop(self)
if self.CurrentMode == SIMULATION_MODE:
self.StopSimulation()
@@ -1001,7 +1001,7 @@
if self.CurrentMode is None and self.OnlineMode != "OFF":
self.CurrentMode = TRANSFER_MODE
- if PluginsRoot._Build(self):
+ if ConfigTreeRoot._Build(self):
ID_ABORTTRANSFERTIMER = wx.NewId()
self.AbortTransferTimer = wx.Timer(self.AppFrame, ID_ABORTTRANSFERTIMER)
@@ -1023,7 +1023,7 @@
self.logger.write(_("Start PLC transfer\n"))
self.AbortTransferTimer.Stop()
- PluginsRoot._Transfer(self)
+ ConfigTreeRoot._Transfer(self)
self.AbortTransferTimer.Start(milliseconds=5000, oneShot=True)
def AbortTransfer(self, event):
@@ -1113,11 +1113,11 @@
frame.Hide()
- self.PluginRoot.ResetAppFrame(lpcberemiz_cmd.Log)
- if self.PluginRoot.OnlineMode == 0:
- self.PluginRoot._connector = None
-
- self.PluginRoot.KillDebugThread()
+ self.CTR.ResetAppFrame(lpcberemiz_cmd.Log)
+ if self.CTR.OnlineMode == 0:
+ self.CTR._connector = None
+
+ self.CTR.KillDebugThread()
self.KillLocalRuntime()
self.SaveLastState()
@@ -1141,7 +1141,7 @@
def RefreshFileMenu(self):
MenuToolBar = self.Panes["MenuToolBar"]
- if self.PluginRoot is not None:
+ if self.CTR is not None:
selected = self.TabsOpened.GetSelection()
if selected >= 0:
graphic_viewer = isinstance(self.TabsOpened.GetPage(selected), Viewer)
@@ -1163,7 +1163,7 @@
self.FileMenu.Enable(wx.ID_PRINT, False)
MenuToolBar.EnableTool(wx.ID_PRINT, False)
self.FileMenu.Enable(wx.ID_PAGE_SETUP, True)
- project_modified = self.PluginRoot.ProjectTestModified()
+ project_modified = self.CTR.ProjectTestModified()
self.FileMenu.Enable(wx.ID_SAVE, project_modified)
MenuToolBar.EnableTool(wx.ID_SAVE, project_modified)
self.FileMenu.Enable(wx.ID_PROPERTIES, True)
@@ -1181,15 +1181,15 @@
self.Freeze()
self.ClearSizer(self.PLCParamsSizer)
- if self.PluginRoot is not None:
+ if self.CTR is not None:
plcwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1))
- if self.PluginRoot.PlugTestModified():
+ if self.CTR.PlugTestModified():
bkgdclr = CHANGED_TITLE_COLOUR
else:
bkgdclr = TITLE_COLOUR
- if self.PluginRoot not in self.PluginInfos:
- self.PluginInfos[self.PluginRoot] = {"right_visible" : False}
+ if self.CTR not in self.ConfNodeInfos:
+ self.ConfNodeInfos[self.CTR] = {"right_visible" : False}
plcwindow.SetBackgroundColour(TITLE_COLOUR)
plcwindow.Bind(wx.EVT_LEFT_DOWN, self.OnPanelLeftDown)
@@ -1200,7 +1200,7 @@
st = wx.StaticText(plcwindow, -1)
st.SetFont(wx.Font(faces["size"], wx.DEFAULT, wx.NORMAL, wx.BOLD, faceName = faces["helv"]))
- st.SetLabel(self.PluginRoot.GetProjectName())
+ st.SetLabel(self.CTR.GetProjectName())
plcwindowsizer.AddWindow(st, 0, border=5, flag=wx.ALL|wx.ALIGN_CENTER)
plcwindowmainsizer = wx.BoxSizer(wx.VERTICAL)
@@ -1209,38 +1209,38 @@
plcwindowbuttonsizer = wx.BoxSizer(wx.HORIZONTAL)
plcwindowmainsizer.AddSizer(plcwindowbuttonsizer, 0, border=0, flag=wx.ALIGN_CENTER)
- msizer = self.GenerateMethodButtonSizer(self.PluginRoot, plcwindow, not self.PluginInfos[self.PluginRoot]["right_visible"])
+ msizer = self.GenerateMethodButtonSizer(self.CTR, plcwindow, not self.ConfNodeInfos[self.CTR]["right_visible"])
plcwindowbuttonsizer.AddSizer(msizer, 0, border=0, flag=wx.GROW)
self.PLCConfigMainSizer.Layout()
self.RefreshScrollBars()
self.Thaw()
- def GenerateTreeBranch(self, plugin):
+ def GenerateTreeBranch(self, confnode):
leftwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1))
- if plugin.PlugTestModified():
+ if confnode.PlugTestModified():
bkgdclr=CHANGED_WINDOW_COLOUR
else:
bkgdclr=WINDOW_COLOUR
leftwindow.SetBackgroundColour(bkgdclr)
- if plugin not in self.PluginInfos:
- self.PluginInfos[plugin] = {"expanded" : False, "left_visible" : False, "right_visible" : False}
-
- self.PluginInfos[plugin]["children"] = plugin.IECSortedChilds()
- plugin_infos = plugin.GetVariableLocationTree()
- plugin_locations = []
- if len(self.PluginInfos[plugin]["children"]) == 0:
- plugin_locations = plugin_infos["children"]
- if not self.PluginInfos[plugin].has_key("locations_infos"):
- self.PluginInfos[plugin]["locations_infos"] = {"root": {"expanded" : False}}
-
- self.PluginInfos[plugin]["locations_infos"]["root"]["left"] = None
- self.PluginInfos[plugin]["locations_infos"]["root"]["right"] = None
- self.PluginInfos[plugin]["locations_infos"]["root"]["children"] = []
-
- self.PluginTreeSizer.AddWindow(leftwindow, 0, border=0, flag=wx.GROW)
+ if confnode not in self.ConfNodeInfos:
+ self.ConfNodeInfos[confnode] = {"expanded" : False, "left_visible" : False, "right_visible" : False}
+
+ self.ConfNodeInfos[confnode]["children"] = confnode.IECSortedChilds()
+ confnode_infos = confnode.GetVariableLocationTree()
+ confnode_locations = []
+ if len(self.ConfNodeInfos[confnode]["children"]) == 0:
+ confnode_locations = confnode_infos["children"]
+ if not self.ConfNodeInfos[confnode].has_key("locations_infos"):
+ self.ConfNodeInfos[confnode]["locations_infos"] = {"root": {"expanded" : False}}
+
+ self.ConfNodeInfos[confnode]["locations_infos"]["root"]["left"] = None
+ self.ConfNodeInfos[confnode]["locations_infos"]["root"]["right"] = None
+ self.ConfNodeInfos[confnode]["locations_infos"]["root"]["children"] = []
+
+ self.ConfNodeTreeSizer.AddWindow(leftwindow, 0, border=0, flag=wx.GROW)
leftwindowvsizer = wx.BoxSizer(wx.VERTICAL)
leftwindow.SetSizer(leftwindowvsizer)
@@ -1248,11 +1248,11 @@
leftwindowsizer = wx.BoxSizer(wx.HORIZONTAL)
leftwindowvsizer.AddSizer(leftwindowsizer, 0, border=0, flag=0)
- self.GenerateEnableButton(leftwindow, leftwindowsizer, plugin)
+ self.GenerateEnableButton(leftwindow, leftwindowsizer, confnode)
st = wx.StaticText(leftwindow, -1)
st.SetFont(wx.Font(faces["size"], wx.DEFAULT, wx.NORMAL, wx.BOLD, faceName = faces["helv"]))
- st.SetLabel(plugin.GetFullIEC_Channel())
+ st.SetLabel(confnode.GetFullIEC_Channel())
leftwindowsizer.AddWindow(st, 0, border=5, flag=wx.RIGHT)
expandbutton_id = wx.NewId()
@@ -1264,27 +1264,27 @@
expandbutton.SetUseFocusIndicator(False)
expandbutton.SetBitmapSelected(wx.Bitmap(Bpath( 'images', 'minus.png')))
- if len(self.PluginInfos[plugin]["children"]) > 0:
- expandbutton.SetToggle(self.PluginInfos[plugin]["expanded"])
+ if len(self.ConfNodeInfos[confnode]["children"]) > 0:
+ expandbutton.SetToggle(self.ConfNodeInfos[confnode]["expanded"])
def togglebutton(event):
if expandbutton.GetToggle():
- self.ExpandPlugin(plugin)
+ self.ExpandConfNode(confnode)
else:
- self.CollapsePlugin(plugin)
- self.PluginInfos[plugin]["expanded"] = expandbutton.GetToggle()
+ self.CollapseConfNode(confnode)
+ self.ConfNodeInfos[confnode]["expanded"] = expandbutton.GetToggle()
self.PLCConfigMainSizer.Layout()
self.RefreshScrollBars()
event.Skip()
expandbutton.Bind(wx.EVT_BUTTON, togglebutton, id=expandbutton_id)
- elif len(plugin_locations) > 0:
- locations_infos = self.PluginInfos[plugin]["locations_infos"]
+ elif len(confnode_locations) > 0:
+ locations_infos = self.ConfNodeInfos[confnode]["locations_infos"]
expandbutton.SetToggle(locations_infos["root"]["expanded"])
def togglebutton(event):
if expandbutton.GetToggle():
self.ExpandLocation(locations_infos, "root")
else:
self.CollapseLocation(locations_infos, "root")
- self.PluginInfos[plugin]["expanded"] = expandbutton.GetToggle()
+ self.ConfNodeInfos[confnode]["expanded"] = expandbutton.GetToggle()
locations_infos["root"]["expanded"] = expandbutton.GetToggle()
self.PLCConfigMainSizer.Layout()
self.RefreshScrollBars()
@@ -1295,9 +1295,9 @@
leftwindowsizer.AddWindow(expandbutton, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL)
sb = wx.StaticBitmap(leftwindow, -1)
- icon = plugin_infos.get("icon", None)
+ icon = confnode_infos.get("icon", None)
if icon is None:
- icon_bitmap = self.LocationImageList.GetBitmap(self.LocationImageDict[plugin_infos["type"]])
+ icon_bitmap = self.LocationImageList.GetBitmap(self.LocationImageDict[confnode_infos["type"]])
else:
icon_bitmap = wx.Bitmap(icon)
sb.SetBitmap(icon_bitmap)
@@ -1306,21 +1306,21 @@
st_id = wx.NewId()
st = wx.StaticText(leftwindow, st_id, size=wx.DefaultSize, style=wx.NO_BORDER)
st.SetFont(wx.Font(faces["size"] * 0.75, wx.DEFAULT, wx.NORMAL, wx.BOLD, faceName = faces["helv"]))
- st.SetLabel(plugin.MandatoryParams[1].getName())
+ st.SetLabel(confnode.MandatoryParams[1].getName())
leftwindowsizer.AddWindow(st, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL)
- rightwindow = self.GenerateParamsPanel(plugin, bkgdclr)
- self.PluginTreeSizer.AddWindow(rightwindow, 0, border=0, flag=wx.GROW)
-
- self.PluginInfos[plugin]["left"] = leftwindow
- self.PluginInfos[plugin]["right"] = rightwindow
- for child in self.PluginInfos[plugin]["children"]:
+ rightwindow = self.GenerateParamsPanel(confnode, bkgdclr)
+ self.ConfNodeTreeSizer.AddWindow(rightwindow, 0, border=0, flag=wx.GROW)
+
+ self.ConfNodeInfos[confnode]["left"] = leftwindow
+ self.ConfNodeInfos[confnode]["right"] = rightwindow
+ for child in self.ConfNodeInfos[confnode]["children"]:
self.GenerateTreeBranch(child)
- if not self.PluginInfos[child]["expanded"]:
- self.CollapsePlugin(child)
-
- if len(plugin_locations) > 0:
- locations_infos = self.PluginInfos[plugin]["locations_infos"]
+ if not self.ConfNodeInfos[child]["expanded"]:
+ self.CollapseConfNode(child)
+
+ if len(confnode_locations) > 0:
+ locations_infos = self.ConfNodeInfos[confnode]["locations_infos"]
treectrl = wx.TreeCtrl(self.PLCConfig, -1, size=wx.DefaultSize,
style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.NO_BORDER|wx.TR_HIDE_ROOT|wx.TR_NO_LINES|wx.TR_LINES_AT_ROOT)
treectrl.SetImageList(self.LocationImageList)
@@ -1329,15 +1329,15 @@
treectrl.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.GenerateLocationExpandCollapseFunction(locations_infos, False))
treectrl.AddRoot("")
- self.PluginTreeSizer.AddWindow(treectrl, 0, border=0, flag=0)
+ self.ConfNodeTreeSizer.AddWindow(treectrl, 0, border=0, flag=0)
rightwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1))
rightwindow.SetBackgroundColour(wx.WHITE)
- self.PluginTreeSizer.AddWindow(rightwindow, 0, border=0, flag=wx.GROW)
+ self.ConfNodeTreeSizer.AddWindow(rightwindow, 0, border=0, flag=wx.GROW)
locations_infos["root"]["left"] = treectrl
locations_infos["root"]["right"] = rightwindow
- for location in plugin_locations:
+ for location in confnode_locations:
locations_infos["root"]["children"].append("root.%s" % location["name"])
self.GenerateLocationTreeBranch(treectrl, treectrl.GetRootItem(), locations_infos, "root", location)
if locations_infos["root"]["expanded"]:
@@ -1416,11 +1416,11 @@
prompt = ""
RefreshTimer = None
- def __init__(self, PluginRoot, Log):
+ def __init__(self, CTR, Log):
cmd.Cmd.__init__(self, stdin=Log, stdout=Log)
self.use_rawinput = False
self.Log = Log
- self.PluginRoot = PluginRoot
+ self.CTR = CTR
def RestartTimer(self):
if self.RefreshTimer is not None:
@@ -1440,7 +1440,7 @@
def Show(self):
global frame
if frame is not None:
- self.PluginRoot.SetAppFrame(frame, frame.Log)
+ self.CTR.SetAppFrame(frame, frame.Log)
frame.Show()
frame.Raise()
@@ -1454,77 +1454,77 @@
def Close(self):
global frame
- self.PluginRoot.ResetAppFrame(self.Log)
+ self.CTR.ResetAppFrame(self.Log)
if frame is not None:
frame.Hide()
def Compile(self):
- self.PluginRoot._Build()
+ self.CTR._Build()
def SetProjectProperties(self, projectname, productname, productversion, companyname):
- properties = self.PluginRoot.GetProjectProperties()
+ properties = self.CTR.GetProjectProperties()
new_properties = properties.copy()
new_properties["projectName"] = projectname
new_properties["productName"] = productname
new_properties["productVersion"] = productversion
new_properties["companyName"] = companyname
if new_properties != properties:
- self.PluginRoot.SetProjectProperties(properties=new_properties, buffer=False)
+ self.CTR.SetProjectProperties(properties=new_properties, buffer=False)
self.RestartTimer()
def SetOnlineMode(self, mode, path=None):
- self.PluginRoot.SetOnlineMode(mode, path)
+ self.CTR.SetOnlineMode(mode, path)
self.RestartTimer()
def AddBus(self, iec_channel, name, icon=None):
- for child in self.PluginRoot.IterChilds():
+ for child in self.CTR.IterChilds():
if child.BaseParams.getName() == name:
return "Error: A bus named %s already exists\n" % name
elif child.BaseParams.getIEC_Channel() == iec_channel:
return "Error: A bus with IEC_channel %d already exists\n" % iec_channel
- bus = self.PluginRoot.PlugAddChild(name, "LPCBus", iec_channel)
+ bus = self.CTR.PlugAddChild(name, "LPCBus", iec_channel)
if bus is None:
return "Error: Unable to create bus\n"
bus.SetIcon(icon)
self.RestartTimer()
def RenameBus(self, iec_channel, name):
- bus = self.PluginRoot.GetChildByIECLocation((iec_channel,))
+ bus = self.CTR.GetChildByIECLocation((iec_channel,))
if bus is None:
return "Error: No bus found\n"
- for child in self.PluginRoot.IterChilds():
+ for child in self.CTR.IterChilds():
if child != bus and child.BaseParams.getName() == name:
return "Error: A bus named %s already exists\n" % name
bus.BaseParams.setName(name)
self.RestartTimer()
def ChangeBusIECChannel(self, old_iec_channel, new_iec_channel):
- bus = self.PluginRoot.GetChildByIECLocation((old_iec_channel,))
+ bus = self.CTR.GetChildByIECLocation((old_iec_channel,))
if bus is None:
return "Error: No bus found\n"
- for child in self.PluginRoot.IterChilds():
+ for child in self.CTR.IterChilds():
if child != bus and child.BaseParams.getIEC_Channel() == new_iec_channel:
return "Error: A bus with IEC_channel %d already exists\n" % new_iec_channel
if wx.GetApp() is None:
- self.PluginRoot.UpdateProjectVariableLocation(str(old_iec_channel),
+ self.CTR.UpdateProjectVariableLocation(str(old_iec_channel),
str(new_iec_channel))
else:
- self.PluginRoot.UpdateProjectVariableLocation(
+ self.CTR.UpdateProjectVariableLocation(
str(old_iec_channel),
str(new_iec_channel))
bus.BaseParams.setIEC_Channel(new_iec_channel)
self.RestartTimer()
def RemoveBus(self, iec_channel):
- bus = self.PluginRoot.GetChildByIECLocation((iec_channel,))
+ bus = self.CTR.GetChildByIECLocation((iec_channel,))
if bus is None:
return "Error: No bus found\n"
- self.PluginRoot.RemoveProjectVariableByFilter(str(iec_channel))
- self.PluginRoot.PluggedChilds["LPCBus"].remove(bus)
+ self.CTR.RemoveProjectVariableByFilter(str(iec_channel))
+ self.CTR.PluggedChilds["LPCBus"].remove(bus)
self.RestartTimer()
def AddModule(self, parent, iec_channel, name, icode, icon=None):
- module = self.PluginRoot.GetChildByIECLocation(parent)
+ module = self.CTR.GetChildByIECLocation(parent)
if module is None:
return "Error: No parent found\n"
for child in _GetModuleChildren(module):
@@ -1541,11 +1541,11 @@
self.RestartTimer()
def RenameModule(self, iec_location, name):
- module = self.PluginRoot.GetChildByIECLocation(iec_location)
+ module = self.CTR.GetChildByIECLocation(iec_location)
if module is None:
return "Error: No module found\n"
- parent = self.PluginRoot.GetChildByIECLocation(iec_location[:-1])
- if parent is self.PluginRoot:
+ parent = self.CTR.GetChildByIECLocation(iec_location[:-1])
+ if parent is self.CTR:
return "Error: No module found\n"
if module["name"] != name:
for child in _GetModuleChildren(parent):
@@ -1555,39 +1555,39 @@
self.RestartTimer()
def ChangeModuleIECChannel(self, old_iec_location, new_iec_channel):
- module = self.PluginRoot.GetChildByIECLocation(old_iec_location)
+ module = self.CTR.GetChildByIECLocation(old_iec_location)
if module is None:
return "Error: No module found\n"
- parent = self.PluginRoot.GetChildByIECLocation(old_iec_location[:-1])
- if parent is self.PluginRoot:
+ parent = self.CTR.GetChildByIECLocation(old_iec_location[:-1])
+ if parent is self.CTR:
return "Error: No module found\n"
if module["IEC_Channel"] != new_iec_channel:
for child in _GetModuleChildren(parent):
if child["IEC_Channel"] == new_iec_channel:
return "Error: A module with IEC_channel %d already exists\n" % new_iec_channel
- self.PluginRoot.UpdateProjectVariableLocation(".".join(map(str, old_iec_location)), ".".join(map(str, old_iec_location[:1] + (new_iec_channel,))))
+ self.CTR.UpdateProjectVariableLocation(".".join(map(str, old_iec_location)), ".".join(map(str, old_iec_location[:1] + (new_iec_channel,))))
module["IEC_Channel"] = new_iec_channel
self.RestartTimer()
def ChangeModuleInitCode(self, iec_location, icode):
- module = self.PluginRoot.GetChildByIECLocation(iec_location)
+ module = self.CTR.GetChildByIECLocation(iec_location)
if module is None:
return "Error: No module found\n"
module["init"] = icode
def RemoveModule(self, parent, iec_channel):
- module = self.PluginRoot.GetChildByIECLocation(parent)
+ module = self.CTR.GetChildByIECLocation(parent)
if module is None:
return "Error: No parent found\n"
child = _GetModuleBySomething(module, "IEC_Channel", (iec_channel,))
if child is None:
return "Error: No module found\n"
- self.PluginRoot.RemoveProjectVariableByFilter(".".join(map(str, parent + (iec_channel,))))
+ self.CTR.RemoveProjectVariableByFilter(".".join(map(str, parent + (iec_channel,))))
_RemoveModuleChild(module, child)
self.RestartTimer()
def StartGroup(self, parent, name, icon=None):
- module = self.PluginRoot.GetChildByIECLocation(parent)
+ module = self.CTR.GetChildByIECLocation(parent)
if module is None:
return "Error: No parent found\n"
for child in module["children"]:
@@ -1600,7 +1600,7 @@
self.RestartTimer()
def AddVariable(self, parent, location, name, direction, type, rcode, pcode, description=""):
- module = self.PluginRoot.GetChildByIECLocation(parent)
+ module = self.CTR.GetChildByIECLocation(parent)
if module is None:
return "Error: No parent found\n"
for child in _GetModuleChildren(module):
@@ -1618,7 +1618,7 @@
self.RestartTimer()
def ChangeVariableParams(self, parent, location, new_name, new_direction, new_type, new_rcode, new_pcode, new_description=None):
- module = self.PluginRoot.GetChildByIECLocation(parent)
+ module = self.CTR.GetChildByIECLocation(parent)
if module is None:
return "Error: No parent found\n"
variable = None
@@ -1630,7 +1630,7 @@
if variable is None:
return "Error: No variable found\n"
if variable["name"] != new_name:
- self.PluginRoot.UpdateProjectVariableName(variable["name"], new_name)
+ self.CTR.UpdateProjectVariableName(variable["name"], new_name)
variable["name"] = new_name
variable["type"] = LOCATION_TYPES[new_direction]
variable["IEC_type"] = new_type
@@ -1641,15 +1641,15 @@
self.RestartTimer()
def RemoveVariable(self, parent, location, direction):
- module = self.PluginRoot.GetChildByIECLocation(parent)
+ module = self.CTR.GetChildByIECLocation(parent)
if module is None:
return "Error: No parent found\n"
child = _GetModuleVariable(module, location, direction)
if child is None:
return "Error: No variable found\n"
- size = LOCATION_SIZES[self.PluginRoot.GetBaseType(child["IEC_type"])]
+ size = LOCATION_SIZES[self.CTR.GetBaseType(child["IEC_type"])]
address = "%" + LOCATION_DIRS[child["type"]] + size + ".".join(map(str, parent + location))
- self.PluginRoot.RemoveProjectVariableByAddress(address)
+ self.CTR.RemoveProjectVariableByAddress(address)
_RemoveModuleChild(module, child)
self.RestartTimer()
@@ -1714,7 +1714,7 @@
return res
return CmdFunction
- def CmdThreadProc(PluginRoot, Log):
+ def CmdThreadProc(CTR, Log):
global lpcberemiz_cmd
for function, (arg_types, opt) in {"Exit": ([], 0),
"Show": ([], 0),
@@ -1738,26 +1738,26 @@
"RemoveVariable": ([location, location], 0)}.iteritems():
setattr(LPCBeremiz_Cmd, "do_%s" % function, GetCmdFunction(function, arg_types, opt))
- lpcberemiz_cmd = LPCBeremiz_Cmd(PluginRoot, Log)
+ lpcberemiz_cmd = LPCBeremiz_Cmd(CTR, Log)
lpcberemiz_cmd.cmdloop()
Log = StdoutPseudoFile(port)
- PluginRoot = LPCPluginsRoot(None, Log, buildpath)
+ CTR = LPCConfigTreeRoot(None, Log, buildpath)
if projectOpen is not None and os.path.isdir(projectOpen):
- result = PluginRoot.LoadProject(projectOpen)
+ result = CTR.LoadProject(projectOpen)
if result:
Log.write("Error: Invalid project directory", result)
else:
Log.write("Error: No such file or directory")
- cmd_thread=Thread(target=CmdThreadProc, args=[PluginRoot, Log])
+ cmd_thread=Thread(target=CmdThreadProc, args=[CTR, Log])
cmd_thread.start()
# Install a exception handle for bug reports
AddExceptHook(os.getcwd(),__version__)
- frame = LPCBeremiz(None, plugin_root=PluginRoot, debug=True)
+ frame = LPCBeremiz(None, ctr=CTR, debug=True)
app.MainLoop()
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/.cvsignore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/.cvsignore Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+*.pyc
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/__init__.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,13 @@
+from os import listdir, path
+
+_base_path = path.split(__file__)[0]
+
+__all__ = [name for name in listdir(_base_path) if path.isdir(path.join(_base_path, name)) and name.upper() != "CVS" or name.endswith(".py") and not name.startswith("__")]
+
+helps = []
+for name in __all__:
+ helpfilename = path.join(_base_path, name, "README")
+ if path.isfile(helpfilename):
+ helps.append(open(helpfilename).readline().strip())
+ else:
+ helps.append(name)
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/c_ext/.cvsignore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/c_ext/.cvsignore Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+*.pyc
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/c_ext/CFileEditor.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/c_ext/CFileEditor.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,967 @@
+import keyword
+
+import wx
+import wx.grid
+import wx.stc as stc
+import wx.lib.buttons
+
+from controls import CustomGrid, CustomTable, EditorPanel
+
+if wx.Platform == '__WXMSW__':
+ faces = { 'times': 'Times New Roman',
+ 'mono' : 'Courier New',
+ 'helv' : 'Arial',
+ 'other': 'Comic Sans MS',
+ 'size' : 10,
+ 'size2': 8,
+ }
+else:
+ faces = { 'times': 'Times',
+ 'mono' : 'Courier',
+ 'helv' : 'Helvetica',
+ 'other': 'new century schoolbook',
+ 'size' : 12,
+ 'size2': 10,
+ }
+
+
+def AppendMenu(parent, help, id, kind, text):
+ if wx.VERSION >= (2, 6, 0):
+ parent.Append(help=help, id=id, kind=kind, text=text)
+ else:
+ parent.Append(helpString=help, id=id, kind=kind, item=text)
+
+
+[ID_CPPEDITOR,
+] = [wx.NewId() for _init_ctrls in range(1)]
+
+CPP_KEYWORDS = ["asm", "auto", "bool", "break", "case", "catch", "char", "class",
+ "const", "const_cast", "continue", "default", "delete", "do", "double",
+ "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false",
+ "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable",
+ "namespace", "new", "operator", "private", "protected", "public", "register",
+ "reinterpret_cast", "return", "short", "signed", "sizeof", "static",
+ "static_cast", "struct", "switch", "template", "this", "throw", "true", "try",
+ "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual",
+ "void", "volatile", "wchar_t", "while"]
+
+def GetCursorPos(old, new):
+ old_length = len(old)
+ new_length = len(new)
+ common_length = min(old_length, new_length)
+ i = 0
+ for i in xrange(common_length):
+ if old[i] != new[i]:
+ break
+ if old_length < new_length:
+ if common_length > 0 and old[i] != new[i]:
+ return i + new_length - old_length
+ else:
+ return i + new_length - old_length + 1
+ elif old_length > new_length or i < min(old_length, new_length) - 1:
+ if common_length > 0 and old[i] != new[i]:
+ return i
+ else:
+ return i + 1
+ else:
+ return None
+
+class CppEditor(stc.StyledTextCtrl):
+
+ fold_symbols = 3
+
+ def __init__(self, parent, name, window, controler):
+ stc.StyledTextCtrl.__init__(self, parent, ID_CPPEDITOR, wx.DefaultPosition,
+ wx.Size(0, 0), 0)
+
+ self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
+ self.SetMarginWidth(1, 25)
+
+ self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
+ self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
+
+ self.SetLexer(stc.STC_LEX_CPP)
+ self.SetKeyWords(0, " ".join(CPP_KEYWORDS))
+
+ self.SetProperty("fold", "1")
+ self.SetProperty("tab.timmy.whinge.level", "1")
+ self.SetMargins(0,0)
+
+ self.SetViewWhiteSpace(False)
+ #self.SetBufferedDraw(False)
+ #self.SetViewEOL(True)
+ #self.SetEOLMode(stc.STC_EOL_CRLF)
+ #self.SetUseAntiAliasing(True)
+
+ self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
+ self.SetEdgeColumn(78)
+
+ # Setup a margin to hold fold markers
+ #self.SetFoldFlags(16) ### WHAT IS THIS VALUE? WHAT ARE THE OTHER FLAGS? DOES IT MATTER?
+ self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
+ self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
+ self.SetMarginSensitive(2, True)
+ self.SetMarginWidth(2, 12)
+
+ if self.fold_symbols == 0:
+ # Arrow pointing right for contracted folders, arrow pointing down for expanded
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_ARROWDOWN, "black", "black")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_ARROW, "black", "black")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "black", "black")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "black", "black")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
+
+ elif self.fold_symbols == 1:
+ # Plus for contracted folders, minus for expanded
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_MINUS, "white", "black")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_PLUS, "white", "black")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "white", "black")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "white", "black")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
+
+ elif self.fold_symbols == 2:
+ # Like a flattened tree control using circular headers and curved joins
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_CIRCLEMINUS, "white", "#404040")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_CIRCLEPLUS, "white", "#404040")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#404040")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNERCURVE, "white", "#404040")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_CIRCLEPLUSCONNECTED, "white", "#404040")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE, "white", "#404040")
+
+ elif self.fold_symbols == 3:
+ # Like a flattened tree control using square headers
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "#808080")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "#808080")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#808080")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "#808080")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "#808080")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
+ self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "#808080")
+
+
+ self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
+ self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
+
+ # Make some styles, The lexer defines what each style is used for, we
+ # just have to define what each style looks like. This set is adapted from
+ # Scintilla sample property files.
+
+ # Global default styles for all languages
+ self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces)
+ self.StyleClearAll() # Reset all to be like the default
+
+ # Global default styles for all languages
+ self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces)
+ self.StyleSetSpec(stc.STC_STYLE_LINENUMBER, "back:#C0C0C0,face:%(helv)s,size:%(size2)d" % faces)
+ self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(other)s" % faces)
+ self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, "fore:#FFFFFF,back:#0000FF,bold")
+ self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, "fore:#000000,back:#FF0000,bold")
+
+ self.StyleSetSpec(stc.STC_C_COMMENT, 'fore:#408060')
+ self.StyleSetSpec(stc.STC_C_COMMENTLINE, 'fore:#408060')
+ self.StyleSetSpec(stc.STC_C_COMMENTDOC, 'fore:#408060')
+ self.StyleSetSpec(stc.STC_C_NUMBER, 'fore:#0076AE')
+ self.StyleSetSpec(stc.STC_C_WORD, 'bold,fore:#800056')
+ self.StyleSetSpec(stc.STC_C_STRING, 'fore:#2a00ff')
+ self.StyleSetSpec(stc.STC_C_PREPROCESSOR, 'bold,fore:#800056')
+ self.StyleSetSpec(stc.STC_C_OPERATOR, 'bold')
+ self.StyleSetSpec(stc.STC_C_STRINGEOL, 'back:#FFD5FF')
+
+ # register some images for use in the AutoComplete box.
+ #self.RegisterImage(1, images.getSmilesBitmap())
+ self.RegisterImage(1,
+ wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16)))
+ self.RegisterImage(2,
+ wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16)))
+ self.RegisterImage(3,
+ wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
+
+ # Indentation size
+ self.SetTabWidth(2)
+ self.SetUseTabs(0)
+
+ self.Controler = controler
+ self.ParentWindow = window
+
+ self.DisableEvents = True
+ self.Name = name
+ self.CurrentAction = None
+
+ self.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE)
+
+ self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_CPPEDITOR)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+ self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_CPPEDITOR)
+
+ def OnModification(self, event):
+ if not self.DisableEvents:
+ mod_type = event.GetModificationType()
+ if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO):
+ if mod_type&wx.stc.STC_MOD_BEFOREINSERT:
+ if self.CurrentAction == None:
+ self.StartBuffering()
+ elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
+ self.Controler.EndBuffering()
+ self.StartBuffering()
+ self.CurrentAction = ("Add", event.GetPosition())
+ wx.CallAfter(self.RefreshModel)
+ elif mod_type&wx.stc.STC_MOD_BEFOREDELETE:
+ if self.CurrentAction == None:
+ self.StartBuffering()
+ elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
+ self.Controler.EndBuffering()
+ self.StartBuffering()
+ self.CurrentAction = ("Delete", event.GetPosition())
+ wx.CallAfter(self.RefreshModel)
+ event.Skip()
+
+ def OnDoDrop(self, event):
+ self.ResetBuffer()
+ wx.CallAfter(self.RefreshModel)
+ event.Skip()
+
+ # Buffer the last model state
+ def RefreshBuffer(self):
+ self.Controler.BufferCFile()
+ if self.ParentWindow is not None:
+ self.ParentWindow.RefreshTitle()
+ self.ParentWindow.RefreshFileMenu()
+ self.ParentWindow.RefreshEditMenu()
+ self.ParentWindow.RefreshPageTitles()
+
+ def StartBuffering(self):
+ self.Controler.StartBuffering()
+ if self.ParentWindow is not None:
+ self.ParentWindow.RefreshTitle()
+ self.ParentWindow.RefreshFileMenu()
+ self.ParentWindow.RefreshEditMenu()
+ self.ParentWindow.RefreshPageTitles()
+
+ def ResetBuffer(self):
+ if self.CurrentAction != None:
+ self.Controler.EndBuffering()
+ self.CurrentAction = None
+
+ def RefreshView(self):
+ self.ResetBuffer()
+ self.DisableEvents = True
+ old_cursor_pos = self.GetCurrentPos()
+ old_text = self.GetText()
+ new_text = self.Controler.GetPartText(self.Name)
+ self.SetText(new_text)
+ new_cursor_pos = GetCursorPos(old_text, new_text)
+ if new_cursor_pos != None:
+ self.GotoPos(new_cursor_pos)
+ else:
+ self.GotoPos(old_cursor_pos)
+ self.ScrollToColumn(0)
+ self.EmptyUndoBuffer()
+ self.DisableEvents = False
+
+ self.Colourise(0, -1)
+
+ def DoGetBestSize(self):
+ return self.ParentWindow.GetPanelBestSize()
+
+ def RefreshModel(self):
+ self.Controler.SetPartText(self.Name, self.GetText())
+
+ def OnKeyPressed(self, event):
+ if self.CallTipActive():
+ self.CallTipCancel()
+ key = event.GetKeyCode()
+
+ if key == 32 and event.ControlDown():
+ pos = self.GetCurrentPos()
+
+ # Tips
+ if event.ShiftDown():
+ pass
+## self.CallTipSetBackground("yellow")
+## self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n'
+## 'show some suff, maybe parameters..\n\n'
+## 'fubar(param1, param2)')
+ # Code completion
+ else:
+ self.AutoCompSetIgnoreCase(False) # so this needs to match
+
+ # Images are specified with a appended "?type"
+ self.AutoCompShow(0, " ".join([word + "?1" for word in CPP_KEYWORDS]))
+ else:
+ event.Skip()
+
+ def OnKillFocus(self, event):
+ self.AutoCompCancel()
+ event.Skip()
+
+ def OnUpdateUI(self, evt):
+ # check for matching braces
+ braceAtCaret = -1
+ braceOpposite = -1
+ charBefore = None
+ caretPos = self.GetCurrentPos()
+
+ if caretPos > 0:
+ charBefore = self.GetCharAt(caretPos - 1)
+ styleBefore = self.GetStyleAt(caretPos - 1)
+
+ # check before
+ if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
+ braceAtCaret = caretPos - 1
+
+ # check after
+ if braceAtCaret < 0:
+ charAfter = self.GetCharAt(caretPos)
+ styleAfter = self.GetStyleAt(caretPos)
+
+ if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
+ braceAtCaret = caretPos
+
+ if braceAtCaret >= 0:
+ braceOpposite = self.BraceMatch(braceAtCaret)
+
+ if braceAtCaret != -1 and braceOpposite == -1:
+ self.BraceBadLight(braceAtCaret)
+ else:
+ self.BraceHighlight(braceAtCaret, braceOpposite)
+ #pt = self.PointFromPosition(braceOpposite)
+ #self.Refresh(True, wxRect(pt.x, pt.y, 5,5))
+ #print pt
+ #self.Refresh(False)
+
+
+ def OnMarginClick(self, evt):
+ # fold and unfold as needed
+ if evt.GetMargin() == 2:
+ if evt.GetShift() and evt.GetControl():
+ self.FoldAll()
+ else:
+ lineClicked = self.LineFromPosition(evt.GetPosition())
+
+ if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
+ if evt.GetShift():
+ self.SetFoldExpanded(lineClicked, True)
+ self.Expand(lineClicked, True, True, 1)
+ elif evt.GetControl():
+ if self.GetFoldExpanded(lineClicked):
+ self.SetFoldExpanded(lineClicked, False)
+ self.Expand(lineClicked, False, True, 0)
+ else:
+ self.SetFoldExpanded(lineClicked, True)
+ self.Expand(lineClicked, True, True, 100)
+ else:
+ self.ToggleFold(lineClicked)
+
+
+ def FoldAll(self):
+ lineCount = self.GetLineCount()
+ expanding = True
+
+ # find out if we are folding or unfolding
+ for lineNum in range(lineCount):
+ if self.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
+ expanding = not self.GetFoldExpanded(lineNum)
+ break
+
+ lineNum = 0
+
+ while lineNum < lineCount:
+ level = self.GetFoldLevel(lineNum)
+ if level & stc.STC_FOLDLEVELHEADERFLAG and \
+ (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
+
+ if expanding:
+ self.SetFoldExpanded(lineNum, True)
+ lineNum = self.Expand(lineNum, True)
+ lineNum = lineNum - 1
+ else:
+ lastChild = self.GetLastChild(lineNum, -1)
+ self.SetFoldExpanded(lineNum, False)
+
+ if lastChild > lineNum:
+ self.HideLines(lineNum+1, lastChild)
+
+ lineNum = lineNum + 1
+
+
+
+ def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
+ lastChild = self.GetLastChild(line, level)
+ line = line + 1
+
+ while line <= lastChild:
+ if force:
+ if visLevels > 0:
+ self.ShowLines(line, line)
+ else:
+ self.HideLines(line, line)
+ else:
+ if doExpand:
+ self.ShowLines(line, line)
+
+ if level == -1:
+ level = self.GetFoldLevel(line)
+
+ if level & stc.STC_FOLDLEVELHEADERFLAG:
+ if force:
+ if visLevels > 1:
+ self.SetFoldExpanded(line, True)
+ else:
+ self.SetFoldExpanded(line, False)
+
+ line = self.Expand(line, doExpand, force, visLevels-1)
+
+ else:
+ if doExpand and self.GetFoldExpanded(line):
+ line = self.Expand(line, True, force, visLevels-1)
+ else:
+ line = self.Expand(line, False, force, visLevels-1)
+ else:
+ line = line + 1
+
+ return line
+
+ def Cut(self):
+ self.ResetBuffer()
+ self.DisableEvents = True
+ self.CmdKeyExecute(wx.stc.STC_CMD_CUT)
+ self.DisableEvents = False
+ self.RefreshModel()
+ self.RefreshBuffer()
+
+ def Copy(self):
+ self.CmdKeyExecute(wx.stc.STC_CMD_COPY)
+
+ def Paste(self):
+ self.ResetBuffer()
+ self.DisableEvents = True
+ self.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
+ self.DisableEvents = False
+ self.RefreshModel()
+ self.RefreshBuffer()
+
+
+#-------------------------------------------------------------------------------
+# Helper for VariablesGrid values
+#-------------------------------------------------------------------------------
+
+class VariablesTable(CustomTable):
+
+ def GetValue(self, row, col):
+ if row < self.GetNumberRows():
+ if col == 0:
+ return row + 1
+ else:
+ return str(self.data[row].get(self.GetColLabelValue(col, False), ""))
+
+ def _updateColAttrs(self, grid):
+ """
+ wxGrid -> update the column attributes to add the
+ appropriate renderer given the column name.
+
+ Otherwise default to the default renderer.
+ """
+
+ typelist = None
+ accesslist = None
+ for row in range(self.GetNumberRows()):
+ for col in range(self.GetNumberCols()):
+ editor = None
+ renderer = None
+ colname = self.GetColLabelValue(col, False)
+
+ if colname == "Name":
+ editor = wx.grid.GridCellTextEditor()
+ elif colname == "Class":
+ editor = wx.grid.GridCellChoiceEditor()
+ editor.SetParameters("input,memory,output")
+ elif colname == "Type":
+ pass
+ else:
+ grid.SetReadOnly(row, col, True)
+
+ grid.SetCellEditor(row, col, editor)
+ grid.SetCellRenderer(row, col, renderer)
+
+ grid.SetCellBackgroundColour(row, col, wx.WHITE)
+ self.ResizeRow(grid, row)
+
+
+[ID_VARIABLESEDITOR, ID_VARIABLESEDITORVARIABLESGRID,
+ ID_VARIABLESEDITORADDVARIABLEBUTTON, ID_VARIABLESEDITORDELETEVARIABLEBUTTON,
+ ID_VARIABLESEDITORUPVARIABLEBUTTON, ID_VARIABLESEDITORDOWNVARIABLEBUTTON
+] = [wx.NewId() for _init_ctrls in range(6)]
+
+class VariablesEditor(wx.Panel):
+
+ if wx.VERSION < (2, 6, 0):
+ def Bind(self, event, function, id = None):
+ if id is not None:
+ event(self, id, function)
+ else:
+ event(self, function)
+
+ def _init_coll_MainSizer_Growables(self, parent):
+ parent.AddGrowableCol(0)
+ parent.AddGrowableRow(0)
+
+ def _init_coll_MainSizer_Items(self, parent):
+ parent.AddWindow(self.VariablesGrid, 0, border=0, flag=wx.GROW)
+ parent.AddSizer(self.ButtonsSizer, 0, border=0, flag=wx.GROW)
+
+ def _init_coll_ButtonsSizer_Growables(self, parent):
+ parent.AddGrowableCol(0)
+ parent.AddGrowableRow(0)
+
+ def _init_coll_ButtonsSizer_Items(self, parent):
+ parent.AddWindow(self.AddVariableButton, 0, border=0, flag=wx.ALIGN_RIGHT)
+ parent.AddWindow(self.DeleteVariableButton, 0, border=0, flag=0)
+ parent.AddWindow(self.UpVariableButton, 0, border=0, flag=0)
+ parent.AddWindow(self.DownVariableButton, 0, border=0, flag=0)
+
+ def _init_sizers(self):
+ self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=4)
+ self.ButtonsSizer = wx.FlexGridSizer(cols=5, hgap=5, rows=1, vgap=0)
+
+ self._init_coll_MainSizer_Growables(self.MainSizer)
+ self._init_coll_MainSizer_Items(self.MainSizer)
+ self._init_coll_ButtonsSizer_Growables(self.ButtonsSizer)
+ self._init_coll_ButtonsSizer_Items(self.ButtonsSizer)
+
+ self.SetSizer(self.MainSizer)
+
+ def _init_ctrls(self, prnt):
+ wx.Panel.__init__(self, id=ID_VARIABLESEDITOR, name='', parent=prnt,
+ size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
+
+ self.VariablesGrid = CustomGrid(id=ID_VARIABLESEDITORVARIABLESGRID,
+ name='VariablesGrid', parent=self, pos=wx.Point(0, 0),
+ size=wx.Size(-1, -1), style=wx.VSCROLL)
+ if wx.VERSION >= (2, 5, 0):
+ self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnVariablesGridCellChange)
+ self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnVariablesGridCellLeftClick)
+ self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, self.OnVariablesGridEditorShown)
+ else:
+ wx.grid.EVT_GRID_CELL_CHANGE(self.VariablesGrid, self.OnVariablesGridCellChange)
+ wx.grid.EVT_GRID_CELL_LEFT_CLICK(self.VariablesGrid, self.OnVariablesGridCellLeftClick)
+ wx.grid.EVT_GRID_EDITOR_SHOWN(self.VariablesGrid, self.OnVariablesGridEditorShown)
+
+ self.AddVariableButton = wx.Button(id=ID_VARIABLESEDITORADDVARIABLEBUTTON, label='Add Variable',
+ name='AddVariableButton', parent=self, pos=wx.Point(0, 0),
+ size=wx.Size(122, 32), style=0)
+
+ self.DeleteVariableButton = wx.Button(id=ID_VARIABLESEDITORDELETEVARIABLEBUTTON, label='Delete Variable',
+ name='DeleteVariableButton', parent=self, pos=wx.Point(0, 0),
+ size=wx.Size(122, 32), style=0)
+
+ self.UpVariableButton = wx.Button(id=ID_VARIABLESEDITORUPVARIABLEBUTTON, label='^',
+ name='UpVariableButton', parent=self, pos=wx.Point(0, 0),
+ size=wx.Size(32, 32), style=0)
+
+ self.DownVariableButton = wx.Button(id=ID_VARIABLESEDITORDOWNVARIABLEBUTTON, label='v',
+ name='DownVariableButton', parent=self, pos=wx.Point(0, 0),
+ size=wx.Size(32, 32), style=0)
+
+ self._init_sizers()
+
+ def __init__(self, parent, window, controler):
+ self._init_ctrls(parent)
+
+ self.ParentWindow = window
+ self.Controler = controler
+
+ self.VariablesDefaultValue = {"Name" : "", "Class" : "input", "Type" : ""}
+ self.Table = VariablesTable(self, [], ["#", "Name", "Class", "Type"])
+ self.ColAlignements = [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
+ self.ColSizes = [40, 200, 150, 150]
+ self.VariablesGrid.SetTable(self.Table)
+ self.VariablesGrid.SetButtons({"Add": self.AddVariableButton,
+ "Delete": self.DeleteVariableButton,
+ "Up": self.UpVariableButton,
+ "Down": self.DownVariableButton})
+
+ def _AddVariable(new_row):
+ self.Table.InsertRow(new_row, self.VariablesDefaultValue.copy())
+ self.RefreshModel()
+ self.RefreshView()
+ return new_row
+ setattr(self.VariablesGrid, "_AddRow", _AddVariable)
+
+ def _DeleteVariable(row):
+ self.Table.RemoveRow(row)
+ self.RefreshModel()
+ self.RefreshView()
+ setattr(self.VariablesGrid, "_DeleteRow", _DeleteVariable)
+
+ def _MoveVariable(row, move):
+ new_row = self.Table.MoveRow(row, move)
+ if new_row != row:
+ self.RefreshModel()
+ self.RefreshView()
+ return new_row
+ setattr(self.VariablesGrid, "_MoveRow", _MoveVariable)
+
+ self.VariablesGrid.SetRowLabelSize(0)
+ for col in range(self.Table.GetNumberCols()):
+ attr = wx.grid.GridCellAttr()
+ attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE)
+ self.VariablesGrid.SetColAttr(col, attr)
+ self.VariablesGrid.SetColSize(col, self.ColSizes[col])
+ self.Table.ResetView(self.VariablesGrid)
+
+ def RefreshModel(self):
+ self.Controler.SetVariables(self.Table.GetData())
+ self.RefreshBuffer()
+
+ # Buffer the last model state
+ def RefreshBuffer(self):
+ self.Controler.BufferCFile()
+ self.ParentWindow.RefreshTitle()
+ self.ParentWindow.RefreshFileMenu()
+ self.ParentWindow.RefreshEditMenu()
+ self.ParentWindow.RefreshPageTitles()
+
+ def RefreshView(self):
+ self.Table.SetData(self.Controler.GetVariables())
+ self.Table.ResetView(self.VariablesGrid)
+ self.VariablesGrid.RefreshButtons()
+
+ def DoGetBestSize(self):
+ return self.ParentWindow.GetPanelBestSize()
+
+ def OnVariablesGridCellChange(self, event):
+ self.RefreshModel()
+ wx.CallAfter(self.RefreshView)
+ event.Skip()
+
+ def OnVariablesGridEditorShown(self, event):
+ row, col = event.GetRow(), event.GetCol()
+ if self.Table.GetColLabelValue(col) == "Type":
+ type_menu = wx.Menu(title='')
+ base_menu = wx.Menu(title='')
+ for base_type in self.Controler.GetBaseTypes():
+ new_id = wx.NewId()
+ AppendMenu(base_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=base_type)
+ self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(base_type), id=new_id)
+ type_menu.AppendMenu(wx.NewId(), "Base Types", base_menu)
+ datatype_menu = wx.Menu(title='')
+ for datatype in self.Controler.GetDataTypes(basetypes=False, only_locatables=True):
+ new_id = wx.NewId()
+ AppendMenu(datatype_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
+ self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
+ type_menu.AppendMenu(wx.NewId(), "User Data Types", datatype_menu)
+ rect = self.VariablesGrid.BlockToDeviceRect((row, col), (row, col))
+
+ self.VariablesGrid.PopupMenuXY(type_menu, rect.x + rect.width, rect.y + self.VariablesGrid.GetColLabelSize())
+ type_menu.Destroy()
+ event.Veto()
+ else:
+ event.Skip()
+
+ def GetVariableTypeFunction(self, base_type):
+ def VariableTypeFunction(event):
+ row = self.VariablesGrid.GetGridCursorRow()
+ self.Table.SetValueByName(row, "Type", base_type)
+ self.Table.ResetView(self.VariablesGrid)
+ self.RefreshModel()
+ self.RefreshView()
+ event.Skip()
+ return VariableTypeFunction
+
+ def OnVariablesGridCellLeftClick(self, event):
+ if event.GetCol() == 0:
+ row = event.GetRow()
+ num = 0
+ if self.Table.GetValueByName(row, "Class") == "input":
+ dir = "%I"
+ for i in xrange(row):
+ if self.Table.GetValueByName(i, "Class") == "input":
+ num += 1
+ elif self.Table.GetValueByName(row, "Class") == "memory":
+ dir = "%M"
+ for i in xrange(row):
+ if self.Table.GetValueByName(i, "Class") == "memory":
+ num += 1
+ else:
+ dir = "%Q"
+ for i in xrange(row):
+ if self.Table.GetValueByName(i, "Class") == "output":
+ num += 1
+ data_type = self.Table.GetValueByName(row, "Type")
+ var_name = self.Table.GetValueByName(row, "Name")
+ base_location = ".".join(map(lambda x:str(x), self.Controler.GetCurrentLocation()))
+ location = "%s%s%s.%d"%(dir, self.Controler.GetSizeOfType(data_type), base_location, num)
+ data = wx.TextDataObject(str((location, "location", data_type, var_name, "")))
+ dragSource = wx.DropSource(self.VariablesGrid)
+ dragSource.SetData(data)
+ dragSource.DoDragDrop()
+ event.Skip()
+
+
+#-------------------------------------------------------------------------------
+# SVGUIEditor Main Frame Class
+#-------------------------------------------------------------------------------
+
+CFILE_PARTS = [
+ ("Includes", CppEditor),
+ ("Variables", VariablesEditor),
+ ("Globals", CppEditor),
+ ("Init", CppEditor),
+ ("CleanUp", CppEditor),
+ ("Retrieve", CppEditor),
+ ("Publish", CppEditor),
+]
+
+#----------------------------------------------------------------------
+# different icons for the collapsed/expanded states.
+# Taken from standard Windows XP collapsed/expanded states.
+#----------------------------------------------------------------------
+
+def GetCollapsedIconData():
+ return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
+\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
+\x00\x01\x8eIDAT8\x8d\xa5\x93-n\xe4@\x10\x85?g\x03\n6lh)\xc4\xd2\x12\xc3\x81\
+\xd6\xa2I\x90\x154\xb9\x81\x8f1G\xc8\x11\x16\x86\xcd\xa0\x99F\xb3A\x91\xa1\
+\xc9J&\x96L"5lX\xcc\x0bl\xf7v\xb2\x7fZ\xa5\x98\xebU\xbdz\xf5\\\x9deW\x9f\xf8\
+H\\\xbfO|{y\x9dT\x15P\x04\x01\x01UPUD\x84\xdb/7YZ\x9f\xa5\n\xce\x97aRU\x8a\
+\xdc`\xacA\x00\x04P\xf0!0\xf6\x81\xa0\xf0p\xff9\xfb\x85\xe0|\x19&T)K\x8b\x18\
+\xf9\xa3\xe4\xbe\xf3\x8c^#\xc9\xd5\n\xa8*\xc5?\x9a\x01\x8a\xd2b\r\x1cN\xc3\
+\x14\t\xce\x97a\xb2F0Ks\xd58\xaa\xc6\xc5\xa6\xf7\xdfya\xe7\xbdR\x13M2\xf9\
+\xf9qKQ\x1fi\xf6-\x00~T\xfac\x1dq#\x82,\xe5q\x05\x91D\xba@\xefj\xba1\xf0\xdc\
+zzW\xcff&\xb8,\x89\xa8@Q\xd6\xaaf\xdfRm,\xee\xb1BDxr#\xae\xf5|\xddo\xd6\xe2H\
+\x18\x15\x84\xa0q@]\xe54\x8d\xa3\xedf\x05M\xe3\xd8Uy\xc4\x15\x8d\xf5\xd7\x8b\
+~\x82\x0fh\x0e"\xb0\xad,\xee\xb8c\xbb\x18\xe7\x8e;6\xa5\x89\x04\xde\xff\x1c\
+\x16\xef\xe0p\xfa>\x19\x11\xca\x8d\x8d\xe0\x93\x1b\x01\xd8m\xf3(;x\xa5\xef=\
+\xb7w\xf3\x1d$\x7f\xc1\xe0\xbd\xa7\xeb\xa0(,"Kc\x12\xc1+\xfd\xe8\tI\xee\xed)\
+\xbf\xbcN\xc1{D\x04k\x05#\x12\xfd\xf2a\xde[\x81\x87\xbb\xdf\x9cr\x1a\x87\xd3\
+0)\xba>\x83\xd5\xb97o\xe0\xaf\x04\xff\x13?\x00\xd2\xfb\xa9`z\xac\x80w\x00\
+\x00\x00\x00IEND\xaeB`\x82'
+
+def GetCollapsedIconBitmap():
+ return wx.BitmapFromImage(GetCollapsedIconImage())
+
+def GetCollapsedIconImage():
+ import cStringIO
+ stream = cStringIO.StringIO(GetCollapsedIconData())
+ return wx.ImageFromStream(stream)
+
+#----------------------------------------------------------------------
+def GetExpandedIconData():
+ return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
+\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
+\x00\x01\x9fIDAT8\x8d\x95\x93\xa1\x8e\xdc0\x14EO\xb2\xc4\xd0\xd2\x12\xb7(mI\
+\xa4%V\xd1lQT4[4-\x9a\xfe\xc1\xc2|\xc6\xc2~BY\x83:A3E\xd3\xa0*\xa4\xd2\x90H!\
+\x95\x0c\r\r\x1fK\x81g\xb2\x99\x84\xb4\x0fY\xd6\xbb\xc7\xf7>=\'Iz\xc3\xbcv\
+\xfbn\xb8\x9c\x15 \xe7\xf3\xc7\x0fw\xc9\xbc7\x99\x03\x0e\xfbn0\x99F+\x85R\
+\x80RH\x10\x82\x08\xde\x05\x1ef\x90+\xc0\xe1\xd8\ryn\xd0Z-\\A\xb4\xd2\xf7\
+\x9e\xfbwoF\xc8\x088\x1c\xbbae\xb3\xe8y&\x9a\xdf\xf5\xbd\xe7\xfem\x84\xa4\
+\x97\xccYf\x16\x8d\xdb\xb2a]\xfeX\x18\xc9s\xc3\xe1\x18\xe7\x94\x12cb\xcc\xb5\
+\xfa\xb1l8\xf5\x01\xe7\x84\xc7\xb2Y@\xb2\xcc0\x02\xb4\x9a\x88%\xbe\xdc\xb4\
+\x9e\xb6Zs\xaa74\xadg[6\x88<\xb7]\xc6\x14\x1dL\x86\xe6\x83\xa0\x81\xba\xda\
+\x10\x02x/\xd4\xd5\x06\r\x840!\x9c\x1fM\x92\xf4\x86\x9f\xbf\xfe\x0c\xd6\x9ae\
+\xd6u\x8d \xf4\xf5\x165\x9b\x8f\x04\xe1\xc5\xcb\xdb$\x05\x90\xa97@\x04lQas\
+\xcd*7\x14\xdb\x9aY\xcb\xb8\\\xe9E\x10|\xbc\xf2^\xb0E\x85\xc95_\x9f\n\xaa/\
+\x05\x10\x81\xce\xc9\xa8\xf6>\x13\xc0n\xff{PJ\xc5\xfdP\x11""<\xbc\
+\xff\x87\xdf\xf8\xbf\xf5\x17FF\xaf\x8f\x8b\xd3\xe6K\x00\x00\x00\x00IEND\xaeB\
+`\x82'
+
+def GetExpandedIconBitmap():
+ return wx.BitmapFromImage(GetExpandedIconImage())
+
+def GetExpandedIconImage():
+ import cStringIO
+ stream = cStringIO.StringIO(GetExpandedIconData())
+ return wx.ImageFromStream(stream)
+
+class FoldPanelCaption(wx.lib.buttons.GenBitmapTextToggleButton):
+
+ def GetBackgroundBrush(self, dc):
+ colBg = self.GetBackgroundColour()
+ brush = wx.Brush(colBg, wx.SOLID)
+ if self.style & wx.BORDER_NONE:
+ myAttr = self.GetDefaultAttributes()
+ parAttr = self.GetParent().GetDefaultAttributes()
+ myDef = colBg == myAttr.colBg
+ parDef = self.GetParent().GetBackgroundColour() == parAttr.colBg
+ if myDef and parDef:
+ if wx.Platform == "__WXMAC__":
+ brush.MacSetTheme(1) # 1 == kThemeBrushDialogBackgroundActive
+ elif wx.Platform == "__WXMSW__":
+ if self.DoEraseBackground(dc):
+ brush = None
+ elif myDef and not parDef:
+ colBg = self.GetParent().GetBackgroundColour()
+ brush = wx.Brush(colBg, wx.SOLID)
+ return brush
+
+ def DrawLabel(self, dc, width, height, dx=0, dy=0):
+ bmp = self.bmpLabel
+ if bmp is not None: # if the bitmap is used
+ if self.bmpDisabled and not self.IsEnabled():
+ bmp = self.bmpDisabled
+ if self.bmpFocus and self.hasFocus:
+ bmp = self.bmpFocus
+ if self.bmpSelected and not self.up:
+ bmp = self.bmpSelected
+ bw,bh = bmp.GetWidth(), bmp.GetHeight()
+ hasMask = bmp.GetMask() is not None
+ else:
+ bw = bh = 0 # no bitmap -> size is zero
+
+ dc.SetFont(self.GetFont())
+ if self.IsEnabled():
+ dc.SetTextForeground(self.GetForegroundColour())
+ else:
+ dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
+
+ label = self.GetLabel()
+ tw, th = dc.GetTextExtent(label) # size of text
+
+ if bmp is not None:
+ dc.DrawBitmap(bmp, width - bw - 2, (height-bh)/2, hasMask) # draw bitmap if available
+
+ dc.DrawText(label, 2, (height-th)/2) # draw the text
+
+ dc.SetPen(wx.Pen(self.GetForegroundColour()))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawRectangle(0, 0, width, height)
+
+[ID_CFILEEDITOR, ID_CFILEEDITORMAINSPLITTER,
+ ID_CFILEEDITORCFILETREE, ID_CFILEEDITORPARTSOPENED,
+] = [wx.NewId() for _init_ctrls in range(4)]
+
+class CFileEditor(EditorPanel):
+
+ def _init_Editor(self, prnt):
+ self.Editor = wx.Panel(id=ID_CFILEEDITOR, parent=prnt, pos=wx.Point(0, 0),
+ size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
+
+ self.Panels = {}
+ self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2 * len(CFILE_PARTS) + 1, vgap=0)
+ self.MainSizer.AddGrowableCol(0)
+
+ for idx, (name, panel_class) in enumerate(CFILE_PARTS):
+ button_id = wx.NewId()
+ button = FoldPanelCaption(id=button_id, name='FoldPanelCaption_%s' % name,
+ label=name, bitmap=GetCollapsedIconBitmap(), parent=self.Editor, pos=wx.Point(0, 0),
+ size=wx.Size(0, 20), style=wx.NO_BORDER|wx.ALIGN_LEFT)
+ button.SetBitmapSelected(GetExpandedIconBitmap())
+ button.Bind(wx.EVT_BUTTON, self.GenPanelButtonCallback(name), id=button_id)
+ self.MainSizer.AddWindow(button, 0, border=0, flag=wx.TOP|wx.GROW)
+
+ if panel_class == VariablesEditor:
+ panel = VariablesEditor(self.Editor, self.ParentWindow, self.Controler)
+ else:
+ panel = panel_class(self.Editor, name, self.ParentWindow, self.Controler)
+ self.MainSizer.AddWindow(panel, 0, border=0, flag=wx.BOTTOM|wx.GROW)
+ panel.Hide()
+
+ self.Panels[name] = {"button": button, "panel": panel, "expanded": False, "row": 2 * idx + 1}
+
+ self.Spacer = wx.Panel(self.Editor, -1)
+ self.SpacerExpanded = True
+ self.MainSizer.AddWindow(self.Spacer, 0, border=0, flag=wx.GROW)
+
+ self.MainSizer.AddGrowableRow(2 * len(CFILE_PARTS))
+
+ self.Editor.SetSizer(self.MainSizer)
+
+ def __init__(self, parent, controler, window):
+ EditorPanel.__init__(self, parent, "", window, controler)
+
+ img = wx.Bitmap(self.Controler.GetIconPath("Cfile.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
+ self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
+
+ def __del__(self):
+ self.Controler.OnCloseEditor(self)
+
+ def GetTitle(self):
+ fullname = self.Controler.PlugFullName()
+ if not self.Controler.CFileIsSaved():
+ return "~%s~" % fullname
+ return fullname
+
+ def GetBufferState(self):
+ return self.Controler.GetBufferState()
+
+ def Undo(self):
+ self.Controler.LoadPrevious()
+ self.RefreshView()
+
+ def Redo(self):
+ self.Controler.LoadNext()
+ self.RefreshView()
+
+ def HasNoModel(self):
+ return False
+
+ def RefreshView(self):
+ for infos in self.Panels.itervalues():
+ infos["panel"].RefreshView()
+
+ def GenPanelButtonCallback(self, name):
+ def PanelButtonCallback(event):
+ self.TogglePanel(name)
+ return PanelButtonCallback
+
+ def ExpandPanel(self, name):
+ infos = self.Panels.get(name, None)
+ if infos is not None and not infos["expanded"]:
+ infos["expanded"] = True
+ infos["button"].SetToggle(True)
+ infos["panel"].Show()
+ self.MainSizer.AddGrowableRow(infos["row"])
+
+ self.RefreshSizerLayout()
+
+ def CollapsePanel(self, name):
+ infos = self.Panels.get(name, None)
+ if infos is not None and infos["expanded"]:
+ infos["expanded"] = False
+ infos["button"].SetToggle(False)
+ infos["panel"].Hide()
+ self.MainSizer.RemoveGrowableRow(infos["row"])
+
+ self.RefreshSizerLayout()
+
+ def TogglePanel(self, name):
+ infos = self.Panels.get(name, None)
+ if infos is not None:
+ infos["expanded"] = not infos["expanded"]
+ infos["button"].SetToggle(infos["expanded"])
+ if infos["expanded"]:
+ infos["panel"].Show()
+ self.MainSizer.AddGrowableRow(infos["row"])
+ else:
+ infos["panel"].Hide()
+ self.MainSizer.RemoveGrowableRow(infos["row"])
+
+ self.RefreshSizerLayout()
+
+ def RefreshSizerLayout(self):
+ expand_spacer = True
+ for infos in self.Panels.itervalues():
+ expand_spacer = expand_spacer and not infos["expanded"]
+
+ if self.SpacerExpanded != expand_spacer:
+ self.SpacerExpanded = expand_spacer
+ if expand_spacer:
+ self.Spacer.Show()
+ self.MainSizer.AddGrowableRow(2 * len(CFILE_PARTS))
+ else:
+ self.Spacer.Hide()
+ self.MainSizer.RemoveGrowableRow(2 * len(CFILE_PARTS))
+
+ self.MainSizer.Layout()
+
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/c_ext/README
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/c_ext/README Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+C extension
\ No newline at end of file
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/c_ext/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/c_ext/__init__.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+from c_ext import *
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/c_ext/c_ext.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/c_ext/c_ext.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,315 @@
+import wx
+import os
+from xml.dom import minidom
+import cPickle
+
+from xmlclass import *
+
+from ConfigTree import ConfigTreeNode, opjimg
+from CFileEditor import CFileEditor
+from PLCControler import PLCControler, UndoBuffer, LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
+
+CFileClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "cext_xsd.xsd"))
+
+TYPECONVERSION = {"BOOL" : "X", "SINT" : "B", "INT" : "W", "DINT" : "D", "LINT" : "L",
+ "USINT" : "B", "UINT" : "W", "UDINT" : "D", "ULINT" : "L", "REAL" : "D", "LREAL" : "L",
+ "STRING" : "B", "BYTE" : "B", "WORD" : "W", "DWORD" : "D", "LWORD" : "L", "WSTRING" : "W"}
+
+class _Cfile:
+ XSD = """
+
+
+
+
+
+
+
+
+ """
+ EditorType = CFileEditor
+
+ def __init__(self):
+ filepath = self.CFileName()
+
+ self.CFile = CFileClasses["CFile"]()
+ if os.path.isfile(filepath):
+ xmlfile = open(filepath, 'r')
+ tree = minidom.parse(xmlfile)
+ xmlfile.close()
+
+ for child in tree.childNodes:
+ if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "CFile":
+ self.CFile.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"])
+ self.CreateCFileBuffer(True)
+ else:
+ self.CreateCFileBuffer(False)
+ self.OnPlugSave()
+
+ def CFileName(self):
+ return os.path.join(self.PlugPath(), "cfile.xml")
+
+ def GetBaseTypes(self):
+ return self.GetPlugRoot().GetBaseTypes()
+
+ def GetDataTypes(self, basetypes = False, only_locatables = False):
+ return self.GetPlugRoot().GetDataTypes(basetypes=basetypes, only_locatables=only_locatables)
+
+ def GetSizeOfType(self, type):
+ return TYPECONVERSION.get(self.GetPlugRoot().GetBaseType(type), None)
+
+ def SetVariables(self, variables):
+ self.CFile.variables.setvariable([])
+ for var in variables:
+ variable = CFileClasses["variables_variable"]()
+ variable.setname(var["Name"])
+ variable.settype(var["Type"])
+ variable.setclass(var["Class"])
+ self.CFile.variables.appendvariable(variable)
+
+ def GetVariables(self):
+ datas = []
+ for var in self.CFile.variables.getvariable():
+ datas.append({"Name" : var.getname(), "Type" : var.gettype(), "Class" : var.getclass()})
+ return datas
+
+ def GetVariableLocationTree(self):
+ '''See ConfigTreeNode.GetVariableLocationTree() for a description.'''
+
+ current_location = ".".join(map(str, self.GetCurrentLocation()))
+
+ vars = []
+ input = memory = output = 0
+ for var in self.CFile.variables.getvariable():
+ var_size = self.GetSizeOfType(var.gettype())
+ var_location = ""
+ if var.getclass() == "input":
+ var_class = LOCATION_VAR_INPUT
+ if var_size is not None:
+ var_location = "%%I%s%s.%d"%(var_size, current_location, input)
+ input += 1
+ elif var.getclass() == "memory":
+ var_class = LOCATION_VAR_INPUT
+ if var_size is not None:
+ var_location = "%%M%s%s.%d"%(var_size, current_location, memory)
+ memory += 1
+ else:
+ var_class = LOCATION_VAR_OUTPUT
+ if var_size is not None:
+ var_location = "%%Q%s%s.%d"%(var_size, current_location, output)
+ output += 1
+ vars.append({"name": var.getname(),
+ "type": var_class,
+ "size": var_size,
+ "IEC_type": var.gettype(),
+ "var_name": var.getname(),
+ "location": var_location,
+ "description": "",
+ "children": []})
+
+ return {"name": self.BaseParams.getName(),
+ "type": LOCATION_CONFNODE,
+ "location": self.GetFullIEC_Channel(),
+ "children": vars}
+
+ def SetPartText(self, name, text):
+ if name == "Includes":
+ self.CFile.includes.settext(text)
+ elif name == "Globals":
+ self.CFile.globals.settext(text)
+ elif name == "Init":
+ self.CFile.initFunction.settext(text)
+ elif name == "CleanUp":
+ self.CFile.cleanUpFunction.settext(text)
+ elif name == "Retrieve":
+ self.CFile.retrieveFunction.settext(text)
+ elif name == "Publish":
+ self.CFile.publishFunction.settext(text)
+
+ def GetPartText(self, name):
+ if name == "Includes":
+ return self.CFile.includes.gettext()
+ elif name == "Globals":
+ return self.CFile.globals.gettext()
+ elif name == "Init":
+ return self.CFile.initFunction.gettext()
+ elif name == "CleanUp":
+ return self.CFile.cleanUpFunction.gettext()
+ elif name == "Retrieve":
+ return self.CFile.retrieveFunction.gettext()
+ elif name == "Publish":
+ return self.CFile.publishFunction.gettext()
+ return ""
+
+ ConfNodeMethods = [
+ {"bitmap" : os.path.join("images", "EditCfile"),
+ "name" : _("Edit C File"),
+ "tooltip" : _("Edit C File"),
+ "method" : "_OpenView"},
+ ]
+
+ def PlugTestModified(self):
+ return self.ChangesToSave or not self.CFileIsSaved()
+
+ def OnPlugSave(self):
+ filepath = self.CFileName()
+
+ text = "\n"
+ extras = {"xmlns":"http://www.w3.org/2001/XMLSchema",
+ "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
+ "xsi:schemaLocation" : "cext_xsd.xsd"}
+ text += self.CFile.generateXMLText("CFile", 0, extras)
+
+ xmlfile = open(filepath,"w")
+ xmlfile.write(text.encode("utf-8"))
+ xmlfile.close()
+
+ self.MarkCFileAsSaved()
+ return True
+
+ def PlugGenerate_C(self, buildpath, locations):
+ """
+ Generate C code
+ @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
+ @param locations: List of complete variables locations \
+ [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
+ "NAME" : name of the variable (generally "__IW0_1_2" style)
+ "DIR" : direction "Q","I" or "M"
+ "SIZE" : size "X", "B", "W", "D", "L"
+ "LOC" : tuple of interger for IEC location (0,1,2,...)
+ }, ...]
+ @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
+ """
+ current_location = self.GetCurrentLocation()
+ # define a unique name for the generated C file
+ location_str = "_".join(map(str, current_location))
+
+ text = "/* Code generated by Beremiz c_ext confnode */\n\n"
+
+ # Adding includes
+ text += "/* User includes */\n"
+ text += self.CFile.includes.gettext()
+ text += "\n"
+
+ text += """/* Beremiz c_ext confnode includes */
+#ifdef _WINDOWS_H
+ #include "iec_types.h"
+#else
+ #include "iec_std_lib.h"
+#endif
+
+"""
+
+ # Adding variables
+ vars = []
+ inputs = memories = outputs = 0
+ for variable in self.CFile.variables.variable:
+ var = {"Name" : variable.getname(), "Type" : variable.gettype()}
+ if variable.getclass() == "input":
+ var["location"] = "__I%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, inputs)
+ inputs += 1
+ elif variable.getclass() == "memory":
+ var["location"] = "__M%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, memories)
+ memories += 1
+ else:
+ var["location"] = "__Q%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, outputs)
+ outputs += 1
+ vars.append(var)
+ text += "/* Beremiz c_ext confnode user variables definition */\n"
+ base_types = self.GetPlugRoot().GetBaseTypes()
+ for var in vars:
+ if var["Type"] in base_types:
+ prefix = "IEC_"
+ else:
+ prefix = ""
+ text += "%s%s beremiz%s;\n"%(prefix, var["Type"], var["location"])
+ text += "%s%s *%s = &beremiz%s;\n"%(prefix, var["Type"], var["location"], var["location"])
+ text += "/* User variables reference */\n"
+ for var in vars:
+ text += "#define %s beremiz%s\n"%(var["Name"], var["location"])
+ text += "\n"
+
+ # Adding user global variables and routines
+ text += "/* User internal user variables and routines */\n"
+ text += self.CFile.globals.gettext()
+
+ # Adding Beremiz confnode functions
+ text += "/* Beremiz confnode functions */\n"
+ text += "int __init_%s(int argc,char **argv)\n{\n"%location_str
+ text += self.CFile.initFunction.gettext()
+ text += " return 0;\n"
+ text += "\n}\n\n"
+
+ text += "void __cleanup_%s(void)\n{\n"%location_str
+ text += self.CFile.cleanUpFunction.gettext()
+ text += "\n}\n\n"
+
+ text += "void __retrieve_%s(void)\n{\n"%location_str
+ text += self.CFile.retrieveFunction.gettext()
+ text += "\n}\n\n"
+
+ text += "void __publish_%s(void)\n{\n"%location_str
+ text += self.CFile.publishFunction.gettext()
+ text += "\n}\n\n"
+
+ Gen_Cfile_path = os.path.join(buildpath, "CFile_%s.c"%location_str)
+ cfile = open(Gen_Cfile_path,'w')
+ cfile.write(text)
+ cfile.close()
+
+ matiec_flags = '"-I%s"'%os.path.abspath(self.GetPlugRoot().GetIECLibPath())
+
+ return [(Gen_Cfile_path, str(self.CExtension.getCFLAGS() + matiec_flags))],str(self.CExtension.getLDFLAGS()),True
+
+
+#-------------------------------------------------------------------------------
+# Current Buffering Management Functions
+#-------------------------------------------------------------------------------
+
+ """
+ Return a copy of the cfile model
+ """
+ def Copy(self, model):
+ return cPickle.loads(cPickle.dumps(model))
+
+ def CreateCFileBuffer(self, saved):
+ self.Buffering = False
+ self.CFileBuffer = UndoBuffer(cPickle.dumps(self.CFile), saved)
+
+ def BufferCFile(self):
+ self.CFileBuffer.Buffering(cPickle.dumps(self.CFile))
+
+ def StartBuffering(self):
+ self.Buffering = True
+
+ def EndBuffering(self):
+ if self.Buffering:
+ self.CFileBuffer.Buffering(cPickle.dumps(self.CFile))
+ self.Buffering = False
+
+ def MarkCFileAsSaved(self):
+ self.EndBuffering()
+ self.CFileBuffer.CurrentSaved()
+
+ def CFileIsSaved(self):
+ return self.CFileBuffer.IsCurrentSaved() and not self.Buffering
+
+ def LoadPrevious(self):
+ self.EndBuffering()
+ self.CFile = cPickle.loads(self.CFileBuffer.Previous())
+
+ def LoadNext(self):
+ self.CFile = cPickle.loads(self.CFileBuffer.Next())
+
+ def GetBufferState(self):
+ first = self.CFileBuffer.IsFirst() and not self.Buffering
+ last = self.CFileBuffer.IsLast()
+ return not first, not last
+
+class RootClass:
+
+ PlugChildsTypes = [("C_File",_Cfile, "C file")]
+
+ def PlugGenerate_C(self, buildpath, locations):
+ return [],"",False
+
+
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/c_ext/cext_xsd.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/c_ext/cext_xsd.xsd Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Formatted text according to parts of XHTML 1.1
+
+
+
+
+
+
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/canfestival/.cvsignore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/.cvsignore Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+*.pyc
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/canfestival/NetworkEditor.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/NetworkEditor.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,122 @@
+import os, sys
+base_folder = os.path.split(sys.path[0])[0]
+CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
+
+import wx
+
+from subindextable import EditingPanel
+from networkedit import NetworkEditorTemplate
+from controls import EditorPanel
+
+[ID_NETWORKEDITOR,
+] = [wx.NewId() for _init_ctrls in range(1)]
+
+[ID_NETWORKEDITORCONFNODEMENUADDSLAVE, ID_NETWORKEDITORCONFNODEMENUREMOVESLAVE,
+ ID_NETWORKEDITORCONFNODEMENUMASTER,
+] = [wx.NewId() for _init_coll_ConfNodeMenu_Items in range(3)]
+
+[ID_NETWORKEDITORMASTERMENUNODEINFOS, ID_NETWORKEDITORMASTERMENUDS301PROFILE,
+ ID_NETWORKEDITORMASTERMENUDS302PROFILE, ID_NETWORKEDITORMASTERMENUDSOTHERPROFILE,
+ ID_NETWORKEDITORMASTERMENUADD,
+] = [wx.NewId() for _init_coll_MasterMenu_Items in range(5)]
+
+[ID_NETWORKEDITORADDMENUSDOSERVER, ID_NETWORKEDITORADDMENUSDOCLIENT,
+ ID_NETWORKEDITORADDMENUPDOTRANSMIT, ID_NETWORKEDITORADDMENUPDORECEIVE,
+ ID_NETWORKEDITORADDMENUMAPVARIABLE, ID_NETWORKEDITORADDMENUUSERTYPE,
+] = [wx.NewId() for _init_coll_AddMenu_Items in range(6)]
+
+class NetworkEditor(EditorPanel, NetworkEditorTemplate):
+
+ ID = ID_NETWORKEDITOR
+
+ def _init_coll_MainSizer_Items(self, parent):
+ parent.AddWindow(self.NetworkNodes, 0, border=5, flag=wx.GROW|wx.ALL)
+
+ def _init_coll_MainSizer_Growables(self, parent):
+ parent.AddGrowableCol(0)
+ parent.AddGrowableRow(0)
+
+ def _init_sizers(self):
+ self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=1, vgap=0)
+
+ self._init_coll_MainSizer_Items(self.MainSizer)
+ self._init_coll_MainSizer_Growables(self.MainSizer)
+
+ self.Editor.SetSizer(self.MainSizer)
+
+ def _init_Editor(self, prnt):
+ self.Editor = wx.Panel(id=-1, parent=prnt, pos=wx.Point(0, 0),
+ size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
+
+ NetworkEditorTemplate._init_ctrls(self, self.Editor)
+
+ self._init_sizers()
+
+ def __init__(self, parent, controler, window):
+ EditorPanel.__init__(self, parent, "", window, controler)
+ NetworkEditorTemplate.__init__(self, controler, window, False)
+
+ img = wx.Bitmap(os.path.join(CanFestivalPath, "objdictgen", "networkedit.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
+ self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
+
+ self.RefreshNetworkNodes()
+ self.RefreshBufferState()
+
+ def __del__(self):
+ self.Controler.OnCloseEditor(self)
+
+ def GetConfNodeMenuItems(self):
+ add_menu = [(wx.ITEM_NORMAL, (_('SDO Server'), ID_NETWORKEDITORADDMENUSDOSERVER, '', self.OnAddSDOServerMenu)),
+ (wx.ITEM_NORMAL, (_('SDO Client'), ID_NETWORKEDITORADDMENUSDOCLIENT, '', self.OnAddSDOClientMenu)),
+ (wx.ITEM_NORMAL, (_('PDO Transmit'), ID_NETWORKEDITORADDMENUPDOTRANSMIT, '', self.OnAddPDOTransmitMenu)),
+ (wx.ITEM_NORMAL, (_('PDO Receive'), ID_NETWORKEDITORADDMENUPDORECEIVE, '', self.OnAddPDOReceiveMenu)),
+ (wx.ITEM_NORMAL, (_('Map Variable'), ID_NETWORKEDITORADDMENUMAPVARIABLE, '', self.OnAddMapVariableMenu)),
+ (wx.ITEM_NORMAL, (_('User Type'), ID_NETWORKEDITORADDMENUUSERTYPE, '', self.OnAddUserTypeMenu))]
+
+ profile = self.Manager.GetCurrentProfileName()
+ if profile not in ("None", "DS-301"):
+ other_profile_text = _("%s Profile") % profile
+ add_menu.append((wx.ITEM_SEPARATOR, None))
+ for text, indexes in self.Manager.GetCurrentSpecificMenu():
+ add_menu.append((wx.ITEM_NORMAL, (text, wx.NewId(), '', self.GetProfileCallBack(text))))
+ else:
+ other_profile_text = _('Other Profile')
+
+ master_menu = [(wx.ITEM_NORMAL, (_('Node infos'), ID_NETWORKEDITORMASTERMENUNODEINFOS, '', self.OnNodeInfosMenu)),
+ (wx.ITEM_NORMAL, (_('DS-301 Profile'), ID_NETWORKEDITORMASTERMENUDS301PROFILE, '', self.OnCommunicationMenu)),
+ (wx.ITEM_NORMAL, (_('DS-302 Profile'), ID_NETWORKEDITORMASTERMENUDS302PROFILE, '', self.OnOtherCommunicationMenu)),
+ (wx.ITEM_NORMAL, (other_profile_text, ID_NETWORKEDITORMASTERMENUDSOTHERPROFILE, '', self.OnEditProfileMenu)),
+ (wx.ITEM_SEPARATOR, None),
+ (add_menu, (_('Add'), ID_NETWORKEDITORMASTERMENUADD))]
+
+ return [(wx.ITEM_NORMAL, (_('Add slave'), ID_NETWORKEDITORCONFNODEMENUADDSLAVE, '', self.OnAddSlaveMenu)),
+ (wx.ITEM_NORMAL, (_('Remove slave'), ID_NETWORKEDITORCONFNODEMENUREMOVESLAVE, '', self.OnRemoveSlaveMenu)),
+ (wx.ITEM_SEPARATOR, None),
+ (master_menu, (_('Master'), ID_NETWORKEDITORCONFNODEMENUMASTER))]
+
+ def RefreshMainMenu(self):
+ pass
+
+ def RefreshConfNodeMenu(self, confnode_menu):
+ confnode_menu.Enable(ID_NETWORKEDITORCONFNODEMENUMASTER, self.NetworkNodes.GetSelection() == 0)
+
+ def GetTitle(self):
+ fullname = self.Controler.PlugFullName()
+ if not self.Manager.CurrentIsSaved():
+ return "~%s~" % fullname
+ return fullname
+
+ def RefreshView(self):
+ self.RefreshCurrentIndexList()
+
+ def RefreshBufferState(self):
+ NetworkEditorTemplate.RefreshBufferState(self)
+ self.ParentWindow.RefreshTitle()
+ self.ParentWindow.RefreshFileMenu()
+ self.ParentWindow.RefreshEditMenu()
+ self.ParentWindow.RefreshPageTitles()
+
+ def OnNodeSelectedChanged(self, event):
+ NetworkEditorTemplate.OnNodeSelectedChanged(self, event)
+ wx.CallAfter(self.ParentWindow.RefreshConfNodeMenu)
+
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/canfestival/README
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/README Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+CANOpen
\ No newline at end of file
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/canfestival/SlaveEditor.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/SlaveEditor.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,83 @@
+import os, sys
+base_folder = os.path.split(sys.path[0])[0]
+CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
+
+import wx
+
+from subindextable import EditingPanel
+from nodeeditor import NodeEditorTemplate
+from controls import EditorPanel
+
+[ID_SLAVEEDITORCONFNODEMENUNODEINFOS, ID_SLAVEEDITORCONFNODEMENUDS301PROFILE,
+ ID_SLAVEEDITORCONFNODEMENUDS302PROFILE, ID_SLAVEEDITORCONFNODEMENUDSOTHERPROFILE,
+ ID_SLAVEEDITORCONFNODEMENUADD,
+] = [wx.NewId() for _init_coll_ConfNodeMenu_Items in range(5)]
+
+[ID_SLAVEEDITORADDMENUSDOSERVER, ID_SLAVEEDITORADDMENUSDOCLIENT,
+ ID_SLAVEEDITORADDMENUPDOTRANSMIT, ID_SLAVEEDITORADDMENUPDORECEIVE,
+ ID_SLAVEEDITORADDMENUMAPVARIABLE, ID_SLAVEEDITORADDMENUUSERTYPE,
+] = [wx.NewId() for _init_coll_AddMenu_Items in range(6)]
+
+class SlaveEditor(EditorPanel, NodeEditorTemplate):
+
+ def _init_Editor(self, prnt):
+ self.Editor = EditingPanel(prnt, self, self.Controler, self.Editable)
+
+ def __init__(self, parent, controler, window, editable=True):
+ self.Editable = editable
+ EditorPanel.__init__(self, parent, "", window, controler)
+ NodeEditorTemplate.__init__(self, controler, window, False)
+
+ img = wx.Bitmap(os.path.join(CanFestivalPath, "objdictgen", "networkedit.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
+ self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
+
+ def __del__(self):
+ self.Controler.OnCloseEditor(self)
+
+ def GetConfNodeMenuItems(self):
+ if self.Editable:
+ add_menu = [(wx.ITEM_NORMAL, (_('SDO Server'), ID_SLAVEEDITORADDMENUSDOSERVER, '', self.OnAddSDOServerMenu)),
+ (wx.ITEM_NORMAL, (_('SDO Client'), ID_SLAVEEDITORADDMENUSDOCLIENT, '', self.OnAddSDOClientMenu)),
+ (wx.ITEM_NORMAL, (_('PDO Transmit'), ID_SLAVEEDITORADDMENUPDOTRANSMIT, '', self.OnAddPDOTransmitMenu)),
+ (wx.ITEM_NORMAL, (_('PDO Receive'), ID_SLAVEEDITORADDMENUPDORECEIVE, '', self.OnAddPDOReceiveMenu)),
+ (wx.ITEM_NORMAL, (_('Map Variable'), ID_SLAVEEDITORADDMENUMAPVARIABLE, '', self.OnAddMapVariableMenu)),
+ (wx.ITEM_NORMAL, (_('User Type'), ID_SLAVEEDITORADDMENUUSERTYPE, '', self.OnAddUserTypeMenu))]
+
+ profile = self.Controler.GetCurrentProfileName()
+ if profile not in ("None", "DS-301"):
+ other_profile_text = _("%s Profile") % profile
+ add_menu.append((wx.ITEM_SEPARATOR, None))
+ for text, indexes in self.Manager.GetCurrentSpecificMenu():
+ add_menu.append((wx.ITEM_NORMAL, (text, wx.NewId(), '', self.GetProfileCallBack(text))))
+ else:
+ other_profile_text = _('Other Profile')
+
+ return [(wx.ITEM_NORMAL, (_('Node infos'), ID_SLAVEEDITORCONFNODEMENUNODEINFOS, '', self.OnNodeInfosMenu)),
+ (wx.ITEM_NORMAL, (_('DS-301 Profile'), ID_SLAVEEDITORCONFNODEMENUDS301PROFILE, '', self.OnCommunicationMenu)),
+ (wx.ITEM_NORMAL, (_('DS-302 Profile'), ID_SLAVEEDITORCONFNODEMENUDS302PROFILE, '', self.OnOtherCommunicationMenu)),
+ (wx.ITEM_NORMAL, (other_profile_text, ID_SLAVEEDITORCONFNODEMENUDSOTHERPROFILE, '', self.OnEditProfileMenu)),
+ (wx.ITEM_SEPARATOR, None),
+ (add_menu, (_('Add'), ID_SLAVEEDITORCONFNODEMENUADD))]
+ return []
+
+ def RefreshConfNodeMenu(self, confnode_menu):
+ confnode_menu.Enable(ID_SLAVEEDITORCONFNODEMENUDSOTHERPROFILE, False)
+
+ def GetTitle(self):
+ fullname = self.Controler.PlugFullName()
+ if not self.Controler.CurrentIsSaved():
+ return "~%s~" % fullname
+ return fullname
+
+ def RefreshView(self):
+ self.Editor.RefreshIndexList()
+
+ def RefreshCurrentIndexList(self):
+ self.RefreshView()
+
+ def RefreshBufferState(self):
+ self.ParentWindow.RefreshTitle()
+ self.ParentWindow.RefreshFileMenu()
+ self.ParentWindow.RefreshEditMenu()
+ self.ParentWindow.RefreshPageTitles()
+
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/canfestival/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/__init__.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+from canfestival import *
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/canfestival/canfestival.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/canfestival.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,484 @@
+import os, sys
+base_folder = os.path.split(sys.path[0])[0]
+CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
+sys.path.append(os.path.join(CanFestivalPath, "objdictgen"))
+
+from nodelist import NodeList
+from nodemanager import NodeManager
+import config_utils, gen_cfile, eds_utils
+from networkedit import networkedit
+from objdictedit import objdictedit
+import canfestival_config as local_canfestival_config
+from ConfigTree import ConfigTreeNode
+from commondialogs import CreateNodeDialog
+import wx
+
+from SlaveEditor import SlaveEditor
+from NetworkEditor import NetworkEditor
+
+from gnosis.xml.pickle import *
+from gnosis.xml.pickle.util import setParanoia
+setParanoia(0)
+
+if wx.Platform == '__WXMSW__':
+ DEFAULT_SETTINGS = {
+ "CAN_Driver": "can_tcp_win32",
+ "CAN_Device": "127.0.0.1",
+ "CAN_Baudrate": "125K",
+ "Slave_NodeId": 2,
+ "Master_NodeId": 1,
+ }
+else:
+ DEFAULT_SETTINGS = {
+ "CAN_Driver": "../CanFestival-3/drivers/can_socket/libcanfestival_can_socket.so",
+ "CAN_Device": "vcan0",
+ "CAN_Baudrate": "125K",
+ "Slave_NodeId": 2,
+ "Master_NodeId": 1,
+ }
+
+#--------------------------------------------------
+# SLAVE
+#--------------------------------------------------
+
+class _SlavePlug(NodeManager):
+ XSD = """
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ """ % DEFAULT_SETTINGS
+
+ EditorType = SlaveEditor
+
+ def __init__(self):
+ # TODO change netname when name change
+ NodeManager.__init__(self)
+ odfilepath = self.GetSlaveODPath()
+ if(os.path.isfile(odfilepath)):
+ self.OpenFileInCurrent(odfilepath)
+ else:
+ self.FilePath = ""
+ dialog = CreateNodeDialog(None, wx.OK)
+ dialog.Type.Enable(False)
+ dialog.GenSYNC.Enable(False)
+ if dialog.ShowModal() == wx.ID_OK:
+ name, id, nodetype, description = dialog.GetValues()
+ profile, filepath = dialog.GetProfile()
+ NMT = dialog.GetNMTManagement()
+ options = dialog.GetOptions()
+ self.CreateNewNode(name, # Name - will be changed at build time
+ id, # NodeID - will be changed at build time
+ "slave", # Type
+ description,# description
+ profile, # profile
+ filepath, # prfile filepath
+ NMT, # NMT
+ options) # options
+ else:
+ self.CreateNewNode("SlaveNode", # Name - will be changed at build time
+ 0x00, # NodeID - will be changed at build time
+ "slave", # Type
+ "", # description
+ "None", # profile
+ "", # prfile filepath
+ "heartbeat", # NMT
+ []) # options
+ dialog.Destroy()
+ self.OnPlugSave()
+
+ def GetSlaveODPath(self):
+ return os.path.join(self.PlugPath(), 'slave.od')
+
+ def GetCanDevice(self):
+ return self.CanFestivalSlaveNode.getCan_Device()
+
+ def _OpenView(self):
+ ConfigTreeNode._OpenView(self)
+ if self._View is not None:
+ self._View.SetBusId(self.GetCurrentLocation())
+
+ ConfNodeMethods = [
+ {"bitmap" : os.path.join("images", "NetworkEdit"),
+ "name" : "Edit slave",
+ "tooltip" : "Edit CanOpen slave with ObjdictEdit",
+ "method" : "_OpenView"},
+ ]
+
+ def OnPlugClose(self):
+ if self._View:
+ self._View.Close()
+
+ def PlugTestModified(self):
+ return self.ChangesToSave or self.OneFileHasChanged()
+
+ def OnPlugSave(self):
+ return self.SaveCurrentInFile(self.GetSlaveODPath())
+
+ def SetParamsAttribute(self, path, value):
+ result = ConfigTreeNode.SetParamsAttribute(self, path, value)
+
+ # Filter IEC_Channel and Name, that have specific behavior
+ if path == "BaseParams.IEC_Channel" and self._View is not None:
+ self._View.SetBusId(self.GetCurrentLocation())
+
+ return result
+
+ def PlugGenerate_C(self, buildpath, locations):
+ """
+ Generate C code
+ @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
+ @param locations: List of complete variables locations \
+ [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
+ "NAME" : name of the variable (generally "__IW0_1_2" style)
+ "DIR" : direction "Q","I" or "M"
+ "SIZE" : size "X", "B", "W", "D", "L"
+ "LOC" : tuple of interger for IEC location (0,1,2,...)
+ }, ...]
+ @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
+ """
+ current_location = self.GetCurrentLocation()
+ # define a unique name for the generated C file
+ prefix = "_".join(map(str, current_location))
+ Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix )
+ # Create a new copy of the model
+ slave = self.GetCurrentNodeCopy()
+ slave.SetNodeName("OD_%s"%prefix)
+ # allow access to local OD from Slave PLC
+ pointers = config_utils.LocalODPointers(locations, current_location, slave)
+ res = gen_cfile.GenerateFile(Gen_OD_path, slave, pointers)
+ if res :
+ raise Exception, res
+ res = eds_utils.GenerateEDSFile(os.path.join(buildpath, "Slave_%s.eds"%prefix), slave)
+ if res :
+ raise Exception, res
+ return [(Gen_OD_path,local_canfestival_config.getCFLAGS(CanFestivalPath))],"",False
+
+ def LoadPrevious(self):
+ self.LoadCurrentPrevious()
+
+ def LoadNext(self):
+ self.LoadCurrentNext()
+
+ def GetBufferState(self):
+ return self.GetCurrentBufferState()
+
+#--------------------------------------------------
+# MASTER
+#--------------------------------------------------
+
+class MiniNodeManager(NodeManager):
+
+ def __init__(self, parent, filepath, fullname):
+ NodeManager.__init__(self)
+
+ self.OpenFileInCurrent(filepath)
+
+ self.Parent = parent
+ self.Fullname = fullname
+
+ def OnCloseEditor(self, view):
+ self.Parent.OnCloseEditor(view)
+
+ def PlugFullName(self):
+ return self.Fullname
+
+ def GetBufferState(self):
+ return self.GetCurrentBufferState()
+
+class _NodeListPlug(NodeList):
+ XSD = """
+
+
+
+
+
+
+
+
+
+
+ """ % DEFAULT_SETTINGS
+
+ EditorType = NetworkEditor
+
+ def __init__(self):
+ manager = NodeManager()
+ NodeList.__init__(self, manager)
+ self.LoadProject(self.PlugPath())
+ self.SetNetworkName(self.BaseParams.getName())
+
+ def GetCanDevice(self):
+ return self.CanFestivalNode.getCan_Device()
+
+ def SetParamsAttribute(self, path, value):
+ result = ConfigTreeNode.SetParamsAttribute(self, path, value)
+
+ # Filter IEC_Channel and Name, that have specific behavior
+ if path == "BaseParams.IEC_Channel" and self._View is not None:
+ self._View.SetBusId(self.GetCurrentLocation())
+ elif path == "BaseParams.Name":
+ self.SetNetworkName(value)
+
+ return result
+
+ def _OpenView(self):
+ ConfigTreeNode._OpenView(self)
+ if self._View is not None:
+ self._View.SetBusId(self.GetCurrentLocation())
+
+ _GeneratedView = None
+ def _ShowMasterGenerated(self):
+ if self._GeneratedView is None:
+ buildpath = self._getBuildPath()
+ # Eventually create build dir
+ if not os.path.exists(buildpath):
+ self.GetPlugRoot().logger.write_error(_("Error: No PLC built\n"))
+ return
+
+ masterpath = os.path.join(buildpath, "MasterGenerated.od")
+ if not os.path.exists(masterpath):
+ self.GetPlugRoot().logger.write_error(_("Error: No Master generated\n"))
+ return
+
+ app_frame = self.GetPlugRoot().AppFrame
+
+ manager = MiniNodeManager(self, masterpath, self.PlugFullName() + ".generated_master")
+ self._GeneratedView = SlaveEditor(app_frame.TabsOpened, manager, app_frame, False)
+
+ app_frame.EditProjectElement(self._GeneratedView, "MasterGenerated")
+
+ def _CloseGenerateView(self):
+ if self._GeneratedView is not None:
+ app_frame = self.GetPlugRoot().AppFrame
+ if app_frame is not None:
+ app_frame.DeletePage(self._GeneratedView)
+
+ ConfNodeMethods = [
+ {"bitmap" : os.path.join("images", "NetworkEdit"),
+ "name" : _("Edit network"),
+ "tooltip" : _("Edit CanOpen Network with NetworkEdit"),
+ "method" : "_OpenView"},
+ {"bitmap" : os.path.join("images", "ShowMaster"),
+ "name" : _("Show Master"),
+ "tooltip" : _("Show Master generated by config_utils"),
+ "method" : "_ShowMasterGenerated"}
+ ]
+
+ def OnCloseEditor(self, view):
+ ConfigTreeNode.OnCloseEditor(self, view)
+ if self._GeneratedView == view:
+ self._GeneratedView = None
+
+ def OnPlugClose(self):
+ ConfigTreeNode.OnPlugClose(self)
+ self._CloseGenerateView()
+ return True
+
+ def PlugTestModified(self):
+ return self.ChangesToSave or self.HasChanged()
+
+ def OnPlugSave(self):
+ self.SetRoot(self.PlugPath())
+ return self.SaveProject() is None
+
+ def PlugGenerate_C(self, buildpath, locations):
+ """
+ Generate C code
+ @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
+ @param locations: List of complete variables locations \
+ [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
+ "NAME" : name of the variable (generally "__IW0_1_2" style)
+ "DIR" : direction "Q","I" or "M"
+ "SIZE" : size "X", "B", "W", "D", "L"
+ "LOC" : tuple of interger for IEC location (0,1,2,...)
+ }, ...]
+ @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
+ """
+ self._CloseGenerateView()
+ current_location = self.GetCurrentLocation()
+ # define a unique name for the generated C file
+ prefix = "_".join(map(str, current_location))
+ Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix )
+ # Create a new copy of the model with DCF loaded with PDO mappings for desired location
+ try:
+ master, pointers = config_utils.GenerateConciseDCF(locations, current_location, self, self.CanFestivalNode.getSync_TPDOs(),"OD_%s"%prefix)
+ except config_utils.PDOmappingException, e:
+ raise Exception, e.message
+ # Do generate C file.
+ res = gen_cfile.GenerateFile(Gen_OD_path, master, pointers)
+ if res :
+ raise Exception, res
+
+ file = open(os.path.join(buildpath, "MasterGenerated.od"), "w")
+ dump(master, file)
+ file.close()
+
+ return [(Gen_OD_path,local_canfestival_config.getCFLAGS(CanFestivalPath))],"",False
+
+ def LoadPrevious(self):
+ self.Manager.LoadCurrentPrevious()
+
+ def LoadNext(self):
+ self.Manager.LoadCurrentNext()
+
+ def GetBufferState(self):
+ return self.Manager.GetCurrentBufferState()
+
+class RootClass:
+ XSD = """
+
+
+
+
+
+
+
+
+ """ % DEFAULT_SETTINGS
+
+ PlugChildsTypes = [("CanOpenNode",_NodeListPlug, "CanOpen Master"),
+ ("CanOpenSlave",_SlavePlug, "CanOpen Slave")]
+ def GetParamsAttributes(self, path = None):
+ infos = ConfigTreeNode.GetParamsAttributes(self, path = None)
+ for element in infos:
+ if element["name"] == "CanFestivalInstance":
+ for child in element["children"]:
+ if child["name"] == "CAN_Driver":
+ DLL_LIST= getattr(local_canfestival_config,"DLL_LIST",None)
+ if DLL_LIST is not None:
+ child["type"] = DLL_LIST
+ return infos
+
+ def GetCanDriver(self):
+ can_driver = self.CanFestivalInstance.getCAN_Driver()
+ if sys.platform == 'win32':
+ if self.CanFestivalInstance.getDebug_mode() and os.path.isfile(os.path.join("%s"%(can_driver + '_DEBUG.dll'))):
+ can_driver += '_DEBUG.dll'
+ else:
+ can_driver += '.dll'
+ return can_driver
+
+ def PlugGenerate_C(self, buildpath, locations):
+
+ format_dict = {"locstr" : "_".join(map(str,self.GetCurrentLocation())),
+ "candriver" : self.GetCanDriver(),
+ "nodes_includes" : "",
+ "board_decls" : "",
+ "nodes_init" : "",
+ "nodes_open" : "",
+ "nodes_stop" : "",
+ "nodes_close" : "",
+ "nodes_send_sync" : "",
+ "nodes_proceed_sync" : "",
+ "slavebootups" : "",
+ "slavebootup_register" : "",
+ "post_sync" : "",
+ "post_sync_register" : "",
+ }
+ for child in self.IECSortedChilds():
+ childlocstr = "_".join(map(str,child.GetCurrentLocation()))
+ nodename = "OD_%s" % childlocstr
+
+ # Try to get Slave Node
+ child_data = getattr(child, "CanFestivalSlaveNode", None)
+ if child_data is None:
+ # Not a slave -> master
+ child_data = getattr(child, "CanFestivalNode")
+ # Apply sync setting
+ format_dict["nodes_init"] += 'NODE_MASTER_INIT(%s, %s)\n '%(
+ nodename,
+ child_data.getNodeId())
+ if child_data.getSync_TPDOs():
+ format_dict["nodes_send_sync"] += 'NODE_SEND_SYNC(%s)\n '%(nodename)
+ format_dict["nodes_proceed_sync"] += 'NODE_PROCEED_SYNC(%s)\n '%(nodename)
+
+ # initialize and declare node boot status variables for post_SlaveBootup lookup
+ SlaveIDs = child.GetSlaveIDs()
+ if len(SlaveIDs) == 0:
+ # define post_SlaveBootup lookup functions
+ format_dict["slavebootups"] += (
+ "static void %s_post_SlaveBootup(CO_Data* d, UNS8 nodeId){}\n"%(nodename))
+ else:
+ for id in SlaveIDs:
+ format_dict["slavebootups"] += (
+ "int %s_slave_%d_booted = 0;\n"%(nodename, id))
+ # define post_SlaveBootup lookup functions
+ format_dict["slavebootups"] += (
+ "static void %s_post_SlaveBootup(CO_Data* d, UNS8 nodeId){\n"%(nodename)+
+ " switch(nodeId){\n")
+ # one case per declared node, mark node as booted
+ for id in SlaveIDs:
+ format_dict["slavebootups"] += (
+ " case %d:\n"%(id)+
+ " %s_slave_%d_booted = 1;\n"%(nodename, id)+
+ " break;\n")
+ format_dict["slavebootups"] += (
+ " default:\n"+
+ " break;\n"+
+ " }\n"+
+ " if( ")
+ # expression to test if all declared nodes booted
+ format_dict["slavebootups"] += " && ".join(["%s_slave_%d_booted"%(nodename, id) for id in SlaveIDs])
+ format_dict["slavebootups"] += " )\n" + (
+ " Master_post_SlaveBootup(d,nodeId);\n"+
+ "}\n")
+ # register previously declared func as post_SlaveBootup callback for that node
+ format_dict["slavebootup_register"] += (
+ "%s_Data.post_SlaveBootup = %s_post_SlaveBootup;\n"%(nodename,nodename))
+ else:
+ # Slave node
+ align = child_data.getSync_Align()
+ align_ratio=child_data.getSync_Align_Ratio()
+ if align > 0:
+ format_dict["post_sync"] += (
+ "static int %s_CalCount = 0;\n"%(nodename)+
+ "static void %s_post_sync(CO_Data* d){\n"%(nodename)+
+ " if(%s_CalCount < %d){\n"%(nodename, align)+
+ " %s_CalCount++;\n"%(nodename)+
+ " align_tick(-1);\n"+
+ " }else{\n"+
+ " align_tick(%d);\n"%(align_ratio)+
+ " }\n"+
+ "}\n")
+ format_dict["post_sync_register"] += (
+ "%s_Data.post_sync = %s_post_sync;\n"%(nodename,nodename))
+ format_dict["nodes_init"] += 'NODE_SLAVE_INIT(%s, %s)\n '%(
+ nodename,
+ child_data.getNodeId())
+
+ # Include generated OD headers
+ format_dict["nodes_includes"] += '#include "%s.h"\n'%(nodename)
+ # Declare CAN channels according user filled config
+ format_dict["board_decls"] += 'BOARD_DECL(%s, "%s", "%s")\n'%(
+ nodename,
+ child.GetCanDevice(),
+ child_data.getCAN_Baudrate())
+ format_dict["nodes_open"] += 'NODE_OPEN(%s)\n '%(nodename)
+ format_dict["nodes_close"] += 'NODE_CLOSE(%s)\n '%(nodename)
+ format_dict["nodes_stop"] += 'NODE_STOP(%s)\n '%(nodename)
+
+ filename = os.path.join(os.path.split(__file__)[0],"cf_runtime.c")
+ cf_main = open(filename).read() % format_dict
+ cf_main_path = os.path.join(buildpath, "CF_%(locstr)s.c"%format_dict)
+ f = open(cf_main_path,'w')
+ f.write(cf_main)
+ f.close()
+
+ return [(cf_main_path, local_canfestival_config.getCFLAGS(CanFestivalPath))],local_canfestival_config.getLDFLAGS(CanFestivalPath), True
+
+
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/canfestival/cf_runtime.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/cf_runtime.c Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,150 @@
+
+#include "canfestival.h"
+
+/* CanFestival nodes generated OD headers*/
+%(nodes_includes)s
+
+#define BOARD_DECL(nodename, busname, baudrate)\
+ s_BOARD nodename##Board = {busname, baudrate};
+
+/* CAN channels declaration */
+%(board_decls)s
+
+/* Keep track of init level to cleanup correctly */
+static int init_level=0;
+/* Retrieve PLC cycle time */
+extern int common_ticktime__;
+
+/* Called once all NetworkEdit declares slaves have booted*/
+static void Master_post_SlaveBootup(CO_Data* d, UNS8 nodeId)
+{
+ /* Put the master in operational mode */
+ setState(d, Operational);
+
+ /* Ask slave node to go in operational mode */
+ masterSendNMTstateChange (d, 0, NMT_Start_Node);
+}
+
+/* Per master node slavebootup callbacks. Checks that
+ * every node have booted before calling Master_post_SlaveBootup */
+%(slavebootups)s
+
+/* One slave node post_sync callback.
+ * Used to align PLC tick-time on CANopen SYNC
+ */
+%(post_sync)s
+
+#define NODE_FORCE_SYNC(nodename) \
+ /* Artificially force sync state to 1 so that it is not started */\
+ nodename##_Data.CurrentCommunicationState.csSYNC = -1;\
+ /* Force sync period to common_ticktime__ so that other node can read it*/\
+ *nodename##_Data.COB_ID_Sync = 0x40000080;\
+ *nodename##_Data.Sync_Cycle_Period = common_ticktime__ * 1000;
+
+#define NODE_INIT(nodename, nodeid) \
+ /* Defining the node Id */\
+ setNodeId(&nodename##_Data, nodeid);\
+ /* init */\
+ setState(&nodename##_Data, Initialisation);
+
+#define NODE_MASTER_INIT(nodename, nodeid) \
+ NODE_FORCE_SYNC(nodename) \
+ NODE_INIT(nodename, nodeid)
+
+#define NODE_SLAVE_INIT(nodename, nodeid) \
+ NODE_INIT(nodename, nodeid)
+
+void InitNodes(CO_Data* d, UNS32 id)
+{
+ %(slavebootup_register)s
+ %(post_sync_register)s
+ %(nodes_init)s
+}
+
+#define NODE_STOP(nodename) \
+ if(init_level-- > 0)\
+ {\
+ masterSendNMTstateChange(&nodename##_Data, 0, NMT_Reset_Node);\
+ setState(&nodename##_Data, Stopped);\
+ }
+
+void Exit(CO_Data* d, UNS32 id)
+{
+ %(nodes_stop)s
+}
+
+#define NODE_CLOSE(nodename) \
+ if(init_level_c-- > 0)\
+ {\
+ canClose(&nodename##_Data);\
+ }
+
+void __cleanup_%(locstr)s(void)
+{
+ // Stop timer thread
+ if(init_level-- > 0){
+ int init_level_c = init_level;
+ StopTimerLoop(&Exit);
+ %(nodes_close)s
+ }
+
+ TimerCleanup();
+}
+
+#ifndef stderr
+#define fprintf(...)
+#define fflush(...)
+#endif
+
+#define NODE_OPEN(nodename)\
+ if(!canOpen(&nodename##Board,&nodename##_Data)){\
+ fprintf(stderr,"Cannot open CAN intefrace %%s at speed %%s\n for CANopen node \"" #nodename "\"",nodename##Board.busname, nodename##Board.baudrate);\
+ fflush(stderr);\
+ return -1;\
+ }\
+ init_level++;
+
+/*************************** INIT *****************************************/
+int __init_%(locstr)s(int argc,char **argv)
+{
+#ifndef NOT_USE_DYNAMIC_LOADING
+ if( !LoadCanDriver("%(candriver)s") ){
+ fprintf(stderr, "Cannot load CAN interface library for CanFestival (%(candriver)s)\n");\
+ fflush(stderr);\
+ return -1;\
+ }
+#endif
+
+ TimerInit();
+
+ %(nodes_open)s
+
+ // Start timer thread
+ StartTimerLoop(&InitNodes);
+ init_level++;
+ return 0;
+}
+
+#define NODE_SEND_SYNC(nodename)\
+ sendSYNCMessage(&nodename##_Data);
+
+void __retrieve_%(locstr)s(void)
+{
+ /* Locks the stack, so that no changes occurs while PLC access variables
+ * TODO : implement buffers to avoid such a big lock
+ * */
+ EnterMutex();
+ /* Send Sync */
+ %(nodes_send_sync)s
+}
+
+#define NODE_PROCEED_SYNC(nodename)\
+ proceedSYNC(&nodename##_Data);
+
+void __publish_%(locstr)s(void)
+{
+ /* Process sync event */
+ %(nodes_proceed_sync)s
+ LeaveMutex();
+}
+
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/canfestival/config_utils.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/config_utils.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,737 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#This file is part of Beremiz, a Integrated Development Environment for
+#programming IEC 61131-3 automates supporting plcopen standard and CanFestival.
+#
+#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
+#
+#See COPYING file for copyrights details.
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+#General Public License for more details.
+#
+#You should have received a copy of the GNU General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from types import *
+
+# Translation between IEC types and Can Open types
+IECToCOType = {"BOOL":0x01, "SINT":0x02, "INT":0x03,"DINT":0x04,"LINT":0x10,
+ "USINT":0x05,"UINT":0x06,"UDINT":0x07,"ULINT":0x1B,"REAL":0x08,
+ "LREAL":0x11,"STRING":0x09,"BYTE":0x05,"WORD":0x06,"DWORD":0x07,
+ "LWORD":0x1B,"WSTRING":0x0B}
+
+# Constants for PDO types
+RPDO = 1
+TPDO = 2
+
+SlavePDOType = {"I" : TPDO, "Q" : RPDO}
+InvertPDOType = {RPDO : TPDO, TPDO : RPDO}
+PDOTypeBaseIndex = {RPDO : 0x1400, TPDO : 0x1800}
+PDOTypeBaseCobId = {RPDO : 0x200, TPDO : 0x180}
+
+VariableIncrement = 0x100
+VariableStartIndex = {TPDO : 0x2000, RPDO : 0x4000}
+VariableDirText = {TPDO : "__I", RPDO : "__Q"}
+VariableTypeOffset = dict(zip(["","X","B","W","D","L"], range(6)))
+
+TrashVariables = [(1, 0x01), (8, 0x05), (16, 0x06), (32, 0x07), (64, 0x1B)]
+
+#-------------------------------------------------------------------------------
+# Specific exception for PDO mapping errors
+#-------------------------------------------------------------------------------
+
+class PDOmappingException(Exception):
+ pass
+
+
+def LE_to_BE(value, size):
+ """
+ Convert Little Endian to Big Endian
+ @param value: value expressed in integer
+ @param size: number of bytes generated
+ @return: a string containing the value converted
+ """
+
+ data = ("%" + str(size * 2) + "." + str(size * 2) + "X") % value
+ list_car = [data[i:i+2] for i in xrange(0, len(data), 2)]
+ list_car.reverse()
+ return "".join([chr(int(car, 16)) for car in list_car])
+
+
+def GetNodePDOIndexes(node, type, parameters = False):
+ """
+ Find the PDO indexes of a node
+ @param node: node
+ @param type: type of PDO searched (RPDO or TPDO or both)
+ @param parameters: indicate which indexes are expected (PDO paramaters : True or PDO mappings : False)
+ @return: a list of indexes found
+ """
+
+ indexes = []
+ if type & RPDO:
+ indexes.extend([idx for idx in node.GetIndexes() if 0x1400 <= idx <= 0x15FF])
+ if type & TPDO:
+ indexes.extend([idx for idx in node.GetIndexes() if 0x1800 <= idx <= 0x19FF])
+ if not parameters:
+ return [idx + 0x200 for idx in indexes]
+ else:
+ return indexes
+
+
+def SearchNodePDOMapping(loc_infos, node):
+ """
+ Find the PDO indexes of a node
+ @param node: node
+ @param type: type of PDO searched (RPDO or TPDO or both)
+ @param parameters: indicate which indexes are expected (PDO paramaters : True or PDO mappings : False)
+ @return: a list of indexes found
+ """
+
+ model = (loc_infos["index"] << 16) + (loc_infos["subindex"] << 8)
+
+ for PDOidx in GetNodePDOIndexes(node, loc_infos["pdotype"]):
+ values = node.GetEntry(PDOidx)
+ if values != None:
+ for subindex, mapping in enumerate(values):
+ if subindex != 0 and mapping & 0xFFFFFF00 == model:
+ return PDOidx, subindex
+ return None
+
+
+def GeneratePDOMappingDCF(idx, cobid, transmittype, pdomapping):
+ """
+ Build concise DCF value for configuring a PDO
+ @param idx: index of PDO parameters
+ @param cobid: PDO generated COB ID
+ @param transmittype : PDO transmit type
+ @param pdomapping: list of PDO mappings
+ @return: a tuple of value and number of parameters to add to DCF
+ """
+
+ # Create entry for RPDO or TPDO parameters and Disable PDO
+ dcfdata = LE_to_BE(idx, 2) + LE_to_BE(0x01, 1) + LE_to_BE(0x04, 4) + LE_to_BE(0x80000000 + cobid, 4)
+ # Set Transmit type synchrone
+ dcfdata += LE_to_BE(idx, 2) + LE_to_BE(0x02, 1) + LE_to_BE(0x01, 4) + LE_to_BE(transmittype, 1)
+ # Re-Enable PDO
+ # ---- INDEX ----- --- SUBINDEX ---- ----- SIZE ------ ------ DATA ------
+ dcfdata += LE_to_BE(idx, 2) + LE_to_BE(0x01, 1) + LE_to_BE(0x04, 4) + LE_to_BE(cobid, 4)
+ nbparams = 3
+ if len(pdomapping) > 0:
+ dcfdata += LE_to_BE(idx + 0x200, 2) + LE_to_BE(0x00, 1) + LE_to_BE(0x01, 4) + LE_to_BE(len(pdomapping), 1)
+ nbparams += 1
+ # Map Variables
+ for subindex, (name, loc_infos) in enumerate(pdomapping):
+ value = (loc_infos["index"] << 16) + (loc_infos["subindex"] << 8) + loc_infos["size"]
+ dcfdata += LE_to_BE(idx + 0x200, 2) + LE_to_BE(subindex + 1, 1) + LE_to_BE(0x04, 4) + LE_to_BE(value, 4)
+ nbparams += 1
+ return dcfdata, nbparams
+
+class ConciseDCFGenerator:
+
+ def __init__(self, nodelist, nodename):
+ # Dictionary of location informations classed by name
+ self.IECLocations = {}
+ # Dictionary of location that have not been mapped yet
+ self.LocationsNotMapped = {}
+ # Dictionary of location informations classed by name
+ self.MasterMapping = {}
+ # List of COB IDs available
+ self.ListCobIDAvailable = range(0x180, 0x580)
+ # Dictionary of mapping value where unexpected variables are stored
+ self.TrashVariables = {}
+ # Dictionary of pointed variables
+ self.PointedVariables = {}
+
+ self.NodeList = nodelist
+ self.Manager = self.NodeList.Manager
+ self.MasterNode = self.Manager.GetCurrentNodeCopy()
+ self.MasterNode.SetNodeName(nodename)
+ self.PrepareMasterNode()
+
+ def GetPointedVariables(self):
+ return self.PointedVariables
+
+ def RemoveUsedNodeCobId(self, node):
+ """
+ Remove all PDO COB ID used by the given node from the list of available COB ID
+ @param node: node
+ @return: a tuple of number of RPDO and TPDO for the node
+ """
+
+ # Get list of all node TPDO and RPDO indexes
+ nodeRpdoIndexes = GetNodePDOIndexes(node, RPDO, True)
+ nodeTpdoIndexes = GetNodePDOIndexes(node, TPDO, True)
+
+ # Mark all the COB ID of the node already mapped PDO as not available
+ for PdoIdx in nodeRpdoIndexes + nodeTpdoIndexes:
+ pdo_cobid = node.GetEntry(PdoIdx, 0x01)
+ # Extract COB ID, if PDO isn't active
+ if pdo_cobid > 0x600 :
+ pdo_cobid -= 0x80000000
+ # Remove COB ID from the list of available COB ID
+ if pdo_cobid in self.ListCobIDAvailable:
+ self.ListCobIDAvailable.remove(pdo_cobid)
+
+ return len(nodeRpdoIndexes), len(nodeTpdoIndexes)
+
+
+ def PrepareMasterNode(self):
+ """
+ Add mandatory entries for DCF generation into MasterNode.
+ """
+
+ # Adding DCF entry into Master node
+ if not self.MasterNode.IsEntry(0x1F22):
+ self.MasterNode.AddEntry(0x1F22, 1, "")
+ self.Manager.AddSubentriesToCurrent(0x1F22, 127, self.MasterNode)
+
+ # Adding trash mappable variables for unused mapped datas
+ idxTrashVariables = 0x2000 + self.MasterNode.GetNodeID()
+ # Add an entry for storing unexpected all variable
+ self.Manager.AddMapVariableToCurrent(idxTrashVariables, self.MasterNode.GetNodeName()+"_trashvariables", 3, len(TrashVariables), self.MasterNode)
+ for subidx, (size, typeidx) in enumerate(TrashVariables):
+ # Add a subentry for storing unexpected variable of this size
+ self.Manager.SetCurrentEntry(idxTrashVariables, subidx + 1, "TRASH%d" % size, "name", None, self.MasterNode)
+ self.Manager.SetCurrentEntry(idxTrashVariables, subidx + 1, typeidx, "type", None, self.MasterNode)
+ # Store the mapping value for this entry
+ self.TrashVariables[size] = (idxTrashVariables << 16) + ((subidx + 1) << 8) + size
+
+ RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(self.MasterNode)
+
+ # Store the indexes of the first RPDO and TPDO available for MasterNode
+ self.CurrentPDOParamsIdx = {RPDO : 0x1400 + RPDOnumber, TPDO : 0x1800 + TPDOnumber}
+
+ # Prepare MasterNode with all nodelist slaves
+ for idx, (nodeid, nodeinfos) in enumerate(self.NodeList.SlaveNodes.items()):
+ node = nodeinfos["Node"]
+ node.SetNodeID(nodeid)
+
+ RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(node)
+
+ # Get Slave's default SDO server parameters
+ RSDO_cobid = node.GetEntry(0x1200,0x01)
+ if not RSDO_cobid:
+ RSDO_cobid = 0x600 + nodeid
+ TSDO_cobid = node.GetEntry(0x1200,0x02)
+ if not TSDO_cobid:
+ TSDO_cobid = 0x580 + nodeid
+
+ # Configure Master's SDO parameters entries
+ self.Manager.ManageEntriesOfCurrent([0x1280 + idx], [], self.MasterNode)
+ self.MasterNode.SetEntry(0x1280 + idx, 0x01, RSDO_cobid)
+ self.MasterNode.SetEntry(0x1280 + idx, 0x02, TSDO_cobid)
+ self.MasterNode.SetEntry(0x1280 + idx, 0x03, nodeid)
+
+
+ def GetMasterNode(self):
+ """
+ Return MasterNode.
+ """
+ return self.MasterNode
+
+ def AddParamsToDCF(self, nodeid, data, nbparams):
+ """
+ Add entry to DCF, for the requested nodeID
+ @param nodeid: id of the slave (int)
+ @param data: data to add to slave DCF (string)
+ @param nbparams: number of params added to slave DCF (int)
+ """
+ # Get current DCF for slave
+ nodeDCF = self.MasterNode.GetEntry(0x1F22, nodeid)
+
+ # Extract data and number of params in current DCF
+ if nodeDCF != None and nodeDCF != '':
+ tmpnbparams = [i for i in nodeDCF[:4]]
+ tmpnbparams.reverse()
+ nbparams += int(''.join(["%2.2x"%ord(i) for i in tmpnbparams]), 16)
+ data = nodeDCF[4:] + data
+
+ # Build new DCF
+ dcf = LE_to_BE(nbparams, 0x04) + data
+ # Set new DCF for slave
+ self.MasterNode.SetEntry(0x1F22, nodeid, dcf)
+
+ def GetEmptyPDO(self, nodeid, pdotype, start_index=None):
+ """
+ Search a not configured PDO for a slave
+ @param node: the slave node object
+ @param pdotype: type of PDO to generated (RPDO or TPDO)
+ @param start_index: Index where search must start (default: None)
+ @return tuple of PDO index, COB ID and number of subindex defined
+ """
+ # If no start_index defined, start with PDOtype base index
+ if start_index is None:
+ index = PDOTypeBaseIndex[pdotype]
+ else:
+ index = start_index
+
+ # Search for all PDO possible index until find a configurable PDO
+ # starting from start_index
+ while index < PDOTypeBaseIndex[pdotype] + 0x200:
+ values = self.NodeList.GetSlaveNodeEntry(nodeid, index + 0x200)
+ if values != None and values[0] > 0:
+ # Check that all subindex upper than 0 equal 0 => configurable PDO
+ if reduce(lambda x, y: x and y, map(lambda x: x == 0, values[1:]), True):
+ cobid = self.NodeList.GetSlaveNodeEntry(nodeid, index, 1)
+ # If no COB ID defined in PDO, generate a new one (not used)
+ if cobid == 0:
+ if len(self.ListCobIDAvailable) == 0:
+ return None
+ # Calculate COB ID from standard values
+ if index < PDOTypeBaseIndex[pdotype] + 4:
+ cobid = PDOTypeBaseCobId[pdotype] + 0x100 * (index - PDOTypeBaseIndex[pdotype]) + nodeid
+ if cobid not in self.ListCobIDAvailable:
+ cobid = self.ListCobIDAvailable.pop(0)
+ return index, cobid, values[0]
+ index += 1
+ return None
+
+ def AddPDOMapping(self, nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs):
+ """
+ Record a new mapping request for a slave, and add related slave config to the DCF
+ @param nodeid: id of the slave (int)
+ @param pdotype: type of PDO to generated (RPDO or TPDO)
+ @param pdomapping: list od variables to map with PDO
+ """
+ # Add an entry to MasterMapping
+ self.MasterMapping[pdocobid] = {"type" : InvertPDOType[pdotype],
+ "mapping" : [None] + [(loc_infos["type"], name) for name, loc_infos in pdomapping]}
+
+ # Return the data to add to DCF
+ if sync_TPDOs:
+ return GeneratePDOMappingDCF(pdoindex, pdocobid, 0x01, pdomapping)
+ else:
+ return GeneratePDOMappingDCF(pdoindex, pdocobid, 0xFF, pdomapping)
+ return 0, ""
+
+ def GenerateDCF(self, locations, current_location, sync_TPDOs):
+ """
+ Generate Concise DCF of MasterNode for the locations list given
+ @param locations: list of locations to be mapped
+ @param current_location: tuple of the located prefixes not to be considered
+ @param sync_TPDOs: indicate if TPDO must be synchronous
+ """
+
+ #-------------------------------------------------------------------------------
+ # Verify that locations correspond to real slave variables
+ #-------------------------------------------------------------------------------
+
+ # Get list of locations check if exists and mappables -> put them in IECLocations
+ for location in locations:
+ COlocationtype = IECToCOType[location["IEC_TYPE"]]
+ name = location["NAME"]
+ if name in self.IECLocations:
+ if self.IECLocations[name]["type"] != COlocationtype:
+ raise PDOmappingException, _("Type conflict for location \"%s\"") % name
+ else:
+ # Get only the part of the location that concern this node
+ loc = location["LOC"][len(current_location):]
+ # loc correspond to (ID, INDEX, SUBINDEX [,BIT])
+ if len(loc) not in (2, 3, 4):
+ raise PDOmappingException, _("Bad location size : %s") % str(loc)
+ elif len(loc) == 2:
+ continue
+
+ direction = location["DIR"]
+
+ sizelocation = location["SIZE"]
+
+ # Extract and check nodeid
+ nodeid, index, subindex = loc[:3]
+
+ # Check Id is in slave node list
+ if nodeid not in self.NodeList.SlaveNodes.keys():
+ raise PDOmappingException, _("Non existing node ID : %d (variable %s)") % (nodeid,name)
+
+ # Get the model for this node (made from EDS)
+ node = self.NodeList.SlaveNodes[nodeid]["Node"]
+
+ # Extract and check index and subindex
+ if not node.IsEntry(index, subindex):
+ raise PDOmappingException, _("No such index/subindex (%x,%x) in ID : %d (variable %s)") % (index,subindex,nodeid,name)
+
+ # Get the entry info
+ subentry_infos = node.GetSubentryInfos(index, subindex)
+
+ # If a PDO mappable
+ if subentry_infos and subentry_infos["pdo"]:
+ if sizelocation == "X" and len(loc) > 3:
+ numbit = loc[3]
+ elif sizelocation != "X" and len(loc) > 3:
+ raise PDOmappingException, _("Cannot set bit offset for non bool '%s' variable (ID:%d,Idx:%x,sIdx:%x))") % (name,nodeid,index,subindex)
+ else:
+ numbit = None
+
+ if location["IEC_TYPE"] != "BOOL" and subentry_infos["type"] != COlocationtype:
+ raise PDOmappingException, _("Invalid type \"%s\"-> %d != %d for location\"%s\"") % (location["IEC_TYPE"], COlocationtype, subentry_infos["type"] , name)
+
+ typeinfos = node.GetEntryInfos(COlocationtype)
+ self.IECLocations[name] = {"type":COlocationtype, "pdotype":SlavePDOType[direction],
+ "nodeid": nodeid, "index": index,"subindex": subindex,
+ "bit": numbit, "size": typeinfos["size"], "sizelocation": sizelocation}
+ else:
+ raise PDOmappingException, _("Not PDO mappable variable : '%s' (ID:%d,Idx:%x,sIdx:%x))") % (name,nodeid,index,subindex)
+
+ #-------------------------------------------------------------------------------
+ # Search for locations already mapped
+ #-------------------------------------------------------------------------------
+
+ for name, locationinfos in self.IECLocations.items():
+ node = self.NodeList.SlaveNodes[locationinfos["nodeid"]]["Node"]
+
+ # Search if slave has a PDO mapping this locations
+ result = SearchNodePDOMapping(locationinfos, node)
+ if result != None:
+ index, subindex = result
+ # Get COB ID of the PDO
+ cobid = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 1)
+
+ # Add PDO to MasterMapping
+ if cobid not in self.MasterMapping.keys():
+ # Verify that PDO transmit type is conform to sync_TPDOs
+ transmittype = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 2)
+ if sync_TPDOs and transmittype != 0x01 or transmittype != 0xFF:
+ if sync_TPDOs:
+ # Change TransmitType to SYNCHRONE
+ data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0x01, [])
+ else:
+ # Change TransmitType to ASYCHRONE
+ data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0xFF, [])
+
+ # Add entry to slave dcf to change transmit type of
+ self.AddParamsToDCF(locationinfos["nodeid"], data, nbparams)
+
+ mapping = [None]
+ values = node.GetEntry(index)
+ # Store the size of each entry mapped in PDO
+ for value in values[1:]:
+ if value != 0:
+ mapping.append(value % 0x100)
+ self.MasterMapping[cobid] = {"type" : InvertPDOType[locationinfos["pdotype"]], "mapping" : mapping}
+
+ # Indicate that this PDO entry must be saved
+ if locationinfos["bit"] is not None:
+ if not isinstance(self.MasterMapping[cobid]["mapping"][subindex], ListType):
+ self.MasterMapping[cobid]["mapping"][subindex] = [1] * self.MasterMapping[cobid]["mapping"][subindex]
+ if locationinfos["bit"] < len(self.MasterMapping[cobid]["mapping"][subindex]):
+ self.MasterMapping[cobid]["mapping"][subindex][locationinfos["bit"]] = (locationinfos["type"], name)
+ else:
+ self.MasterMapping[cobid]["mapping"][subindex] = (locationinfos["type"], name)
+
+ else:
+ # Add location to those that haven't been mapped yet
+ if locationinfos["nodeid"] not in self.LocationsNotMapped.keys():
+ self.LocationsNotMapped[locationinfos["nodeid"]] = {TPDO : [], RPDO : []}
+ self.LocationsNotMapped[locationinfos["nodeid"]][locationinfos["pdotype"]].append((name, locationinfos))
+
+ #-------------------------------------------------------------------------------
+ # Build concise DCF for the others locations
+ #-------------------------------------------------------------------------------
+
+ for nodeid, locations in self.LocationsNotMapped.items():
+ node = self.NodeList.SlaveNodes[nodeid]["Node"]
+
+ # Initialize number of params and data to add to node DCF
+ nbparams = 0
+ dataparams = ""
+
+ # Generate the best PDO mapping for each type of PDO
+ for pdotype in (TPDO, RPDO):
+ if len(locations[pdotype]) > 0:
+ pdosize = 0
+ pdomapping = []
+ result = self.GetEmptyPDO(nodeid, pdotype)
+ if result is None:
+ raise PDOmappingException, _("Unable to define PDO mapping for node %02x") % nodeid
+ pdoindex, pdocobid, pdonbparams = result
+ for name, loc_infos in locations[pdotype]:
+ pdosize += loc_infos["size"]
+ # If pdo's size > 64 bits
+ if pdosize > 64 or len(pdomapping) >= pdonbparams:
+ # Generate a new PDO Mapping
+ data, nbaddedparams = self.AddPDOMapping(nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs)
+ dataparams += data
+ nbparams += nbaddedparams
+ pdosize = loc_infos["size"]
+ pdomapping = [(name, loc_infos)]
+ result = self.GetEmptyPDO(nodeid, pdotype, pdoindex + 1)
+ if result is None:
+ raise PDOmappingException, _("Unable to define PDO mapping for node %02x") % nodeid
+ pdoindex, pdocobid, pdonbparams = result
+ else:
+ pdomapping.append((name, loc_infos))
+ # If there isn't locations yet but there is still a PDO to generate
+ if len(pdomapping) > 0:
+ # Generate a new PDO Mapping
+ data, nbaddedparams = self.AddPDOMapping(nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs)
+ dataparams += data
+ nbparams += nbaddedparams
+
+ # Add number of params and data to node DCF
+ self.AddParamsToDCF(nodeid, dataparams, nbparams)
+
+ #-------------------------------------------------------------------------------
+ # Master Node Configuration
+ #-------------------------------------------------------------------------------
+
+ # Generate Master's Configuration from informations stored in MasterMapping
+ for cobid, pdo_infos in self.MasterMapping.items():
+ # Get next PDO index in MasterNode for this PDO type
+ current_idx = self.CurrentPDOParamsIdx[pdo_infos["type"]]
+
+ # Search if there is already a PDO in MasterNode with this cob id
+ for idx in GetNodePDOIndexes(self.MasterNode, pdo_infos["type"], True):
+ if self.MasterNode.GetEntry(idx, 1) == cobid:
+ current_idx = idx
+
+ # Add a PDO to MasterNode if not PDO have been found
+ if current_idx == self.CurrentPDOParamsIdx[pdo_infos["type"]]:
+ addinglist = [current_idx, current_idx + 0x200]
+ self.Manager.ManageEntriesOfCurrent(addinglist, [], self.MasterNode)
+ self.MasterNode.SetEntry(current_idx, 0x01, cobid)
+
+ # Increment the number of PDO for this PDO type
+ self.CurrentPDOParamsIdx[pdo_infos["type"]] += 1
+
+ # Change the transmit type of the PDO
+ if sync_TPDOs:
+ self.MasterNode.SetEntry(current_idx, 0x02, 0x01)
+ else:
+ self.MasterNode.SetEntry(current_idx, 0x02, 0xFF)
+
+ mapping = []
+ for item in pdo_infos["mapping"]:
+ if isinstance(item, ListType):
+ mapping.extend(item)
+ else:
+ mapping.append(item)
+
+ # Add some subentries to PDO mapping if there is not enough
+ if len(mapping) > 1:
+ self.Manager.AddSubentriesToCurrent(current_idx + 0x200, len(mapping) - 1, self.MasterNode)
+
+ # Generate MasterNode's PDO mapping
+ for subindex, variable in enumerate(mapping):
+ if subindex == 0:
+ continue
+ new_index = False
+
+ if isinstance(variable, (IntType, LongType)):
+ # If variable is an integer then variable is unexpected
+ self.MasterNode.SetEntry(current_idx + 0x200, subindex, self.TrashVariables[variable])
+ else:
+ typeidx, varname = variable
+ variable_infos = self.IECLocations[varname]
+
+ # Calculate base index for storing variable
+ mapvariableidx = VariableStartIndex[variable_infos["pdotype"]] + \
+ VariableTypeOffset[variable_infos["sizelocation"]] * VariableIncrement + \
+ variable_infos["nodeid"]
+
+ # Generate entry name
+ indexname = "%s%s%s_%d"%(VariableDirText[variable_infos["pdotype"]],
+ variable_infos["sizelocation"],
+ '_'.join(map(str,current_location)),
+ variable_infos["nodeid"])
+
+ # Search for an entry that has an empty subindex
+ while mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000:
+ # Entry doesn't exist
+ if not self.MasterNode.IsEntry(mapvariableidx):
+ # Add entry to MasterNode
+ self.Manager.AddMapVariableToCurrent(mapvariableidx, "beremiz"+indexname, 3, 1, self.MasterNode)
+ new_index = True
+ nbsubentries = self.MasterNode.GetEntry(mapvariableidx, 0x00)
+ else:
+ # Get Number of subentries already defined
+ nbsubentries = self.MasterNode.GetEntry(mapvariableidx, 0x00)
+ # if entry is full, go to next entry possible or stop now
+ if nbsubentries == 0xFF:
+ mapvariableidx += 8 * VariableIncrement
+ else:
+ break
+
+ # Verify that a not full entry has been found
+ if mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000:
+ # Generate subentry name
+ if variable_infos["bit"] != None:
+ subindexname = "%(index)d_%(subindex)d_%(bit)d"%variable_infos
+ else:
+ subindexname = "%(index)d_%(subindex)d"%variable_infos
+ # If entry have just been created, no subentry have to be added
+ if not new_index:
+ self.Manager.AddSubentriesToCurrent(mapvariableidx, 1, self.MasterNode)
+ nbsubentries += 1
+ # Add informations to the new subentry created
+ self.MasterNode.SetMappingEntry(mapvariableidx, nbsubentries, values = {"name" : subindexname})
+ self.MasterNode.SetMappingEntry(mapvariableidx, nbsubentries, values = {"type" : typeidx})
+
+ # Set value of the PDO mapping
+ typeinfos = self.Manager.GetEntryInfos(typeidx)
+ if typeinfos != None:
+ value = (mapvariableidx << 16) + ((nbsubentries) << 8) + typeinfos["size"]
+ self.MasterNode.SetEntry(current_idx + 0x200, subindex, value)
+
+ # Add variable to pointed variables
+ self.PointedVariables[(mapvariableidx, nbsubentries)] = "%s_%s"%(indexname, subindexname)
+
+def GenerateConciseDCF(locations, current_location, nodelist, sync_TPDOs, nodename):
+ """
+ Fills a CanFestival network editor model, with DCF with requested PDO mappings.
+ @param locations: List of complete variables locations \
+ [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
+ "NAME" : name of the variable (generally "__IW0_1_2" style)
+ "DIR" : direction "Q","I" or "M"
+ "SIZE" : size "X", "B", "W", "D", "L"
+ "LOC" : tuple of interger for IEC location (0,1,2,...)
+ }, ...]
+ @param nodelist: CanFestival network editor model
+ @return: a modified copy of the given CanFestival network editor model
+ """
+
+ dcfgenerator = ConciseDCFGenerator(nodelist, nodename)
+ dcfgenerator.GenerateDCF(locations, current_location, sync_TPDOs)
+ masternode,pointers = dcfgenerator.GetMasterNode(), dcfgenerator.GetPointedVariables()
+ # allow access to local OD from Master PLC
+ pointers.update(LocalODPointers(locations, current_location, masternode))
+ return masternode,pointers
+
+def LocalODPointers(locations, current_location, slave):
+ IECLocations = {}
+ pointers = {}
+ for location in locations:
+ COlocationtype = IECToCOType[location["IEC_TYPE"]]
+ name = location["NAME"]
+ if name in IECLocations:
+ if IECLocations[name] != COlocationtype:
+ raise PDOmappingException, _("Type conflict for location \"%s\"") % name
+ else:
+ # Get only the part of the location that concern this node
+ loc = location["LOC"][len(current_location):]
+ # loc correspond to (ID, INDEX, SUBINDEX [,BIT])
+ if len(loc) not in (2, 3, 4):
+ raise PDOmappingException, _("Bad location size : %s") % str(loc)
+ elif len(loc) != 2:
+ continue
+
+ # Extract and check nodeid
+ index, subindex = loc[:2]
+
+ # Extract and check index and subindex
+ if not slave.IsEntry(index, subindex):
+ raise PDOmappingException, _("No such index/subindex (%x,%x) (variable %s)") % (index, subindex, name)
+
+ # Get the entry info
+ subentry_infos = slave.GetSubentryInfos(index, subindex)
+ if subentry_infos["type"] != COlocationtype:
+ raise PDOmappingException, _("Invalid type \"%s\"-> %d != %d for location\"%s\"") % (location["IEC_TYPE"], COlocationtype, subentry_infos["type"] , name)
+
+ IECLocations[name] = COlocationtype
+ pointers[(index, subindex)] = name
+ return pointers
+
+if __name__ == "__main__":
+ import os, sys, getopt
+
+ def usage():
+ print """
+Usage of config_utils.py test :
+
+ %s [options]
+
+Options:
+ --help (-h)
+ Displays help informations for config_utils
+
+ --reset (-r)
+ Reset the reference result of config_utils test.
+ Use with caution. Be sure that config_utils
+ is currently working properly.
+"""%sys.argv[0]
+
+ # Boolean that indicate if reference result must be redefined
+ reset = False
+
+ # Extract command options
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], "hr", ["help","reset"])
+ except getopt.GetoptError:
+ # print help information and exit:
+ usage()
+ sys.exit(2)
+
+ # Test each option
+ for o, a in opts:
+ if o in ("-h", "--help"):
+ usage()
+ sys.exit()
+ elif o in ("-r", "--reset"):
+ reset = True
+
+ # Extract workspace base folder
+ base_folder = sys.path[0]
+ for i in xrange(3):
+ base_folder = os.path.split(base_folder)[0]
+ # Add CanFestival folder to search pathes
+ sys.path.append(os.path.join(base_folder, "CanFestival-3", "objdictgen"))
+
+ from nodemanager import *
+ from nodelist import *
+
+ # Open the test nodelist contained into test_config folder
+ manager = NodeManager()
+ nodelist = NodeList(manager)
+ result = nodelist.LoadProject("test_config")
+
+ # List of locations, we try to map for test
+ locations = [{"IEC_TYPE":"BYTE","NAME":"__IB0_1_64_24576_1","DIR":"I","SIZE":"B","LOC":(0,1,64,24576,1)},
+ {"IEC_TYPE":"INT","NAME":"__IW0_1_64_25601_2","DIR":"I","SIZE":"W","LOC":(0,1,64,25601,2)},
+ {"IEC_TYPE":"INT","NAME":"__IW0_1_64_25601_3","DIR":"I","SIZE":"W","LOC":(0,1,64,25601,3)},
+ {"IEC_TYPE":"INT","NAME":"__QW0_1_64_25617_2","DIR":"Q","SIZE":"W","LOC":(0,1,64,25617,1)},
+ {"IEC_TYPE":"BYTE","NAME":"__IB0_1_64_24578_1","DIR":"I","SIZE":"B","LOC":(0,1,64,24578,1)},
+ {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_1","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,1)},
+ {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_2","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,2)},
+ {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_3","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,3)},
+ {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_4","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,4)},
+ {"IEC_TYPE":"UDINT","NAME":"__ID0_1_4096_0","DIR":"I","SIZE":"D","LOC":(0,1,4096,0)}]
+
+ # Generate MasterNode configuration
+ try:
+ masternode, pointedvariables = GenerateConciseDCF(locations, (0, 1), nodelist, True, "TestNode")
+ except ValueError, message:
+ print "%s\nTest Failed!"%message
+ sys.exit()
+
+ import pprint
+ # Get Text corresponding to MasterNode
+ result_node = masternode.PrintString()
+ result_vars = pprint.pformat(pointedvariables)
+ result = result_node + "\n********POINTERS*********\n" + result_vars + "\n"
+
+ # If reset has been choosen
+ if reset:
+ # Write Text into reference result file
+ testfile = open("test_config/result.txt", "w")
+ testfile.write(result)
+ testfile.close()
+
+ print "Reset Successful!"
+ else:
+ import os
+
+ testfile = open("test_config/result_tmp.txt", "w")
+ testfile.write(result)
+ testfile.close()
+
+ os.system("diff test_config/result.txt test_config/result_tmp.txt")
+ os.remove("test_config/result_tmp.txt")
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/canfestival/test_config/eds/PEAK MicroMod.eds
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/test_config/eds/PEAK MicroMod.eds Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1289 @@
+[FileInfo]
+CreatedBy=ESAcademy
+ModifiedBy=ESAcademy
+Description=PEAK MicroMod CANopenIA Generic
+CreationTime=09:41PM
+CreationDate=05-05-2003
+ModificationTime=05:05PM
+ModificationDate=03-23-2005
+FileName=C:\CANopenCT\Tests\PEAK MicroMod.eds
+FileVersion=1
+FileRevision=1
+EDSVersion=4
+
+[DeviceInfo]
+VendorName=PEAK System Technik
+VendorNumber=0x00000175
+ProductName=PEAK MicroMod CANopenIA Generic
+ProductNumber=0x00100000
+RevisionNumber=0x00010001
+OrderCode=na
+BaudRate_10=0
+BaudRate_20=0
+BaudRate_50=1
+BaudRate_125=1
+BaudRate_250=1
+BaudRate_500=1
+BaudRate_800=1
+BaudRate_1000=1
+SimpleBootUpMaster=0
+SimpleBootUpSlave=1
+Granularity=0
+DynamicChannelsSupported=0
+CompactPDO=0
+GroupMessaging=0
+NrOfRXPDO=4
+NrOfTXPDO=4
+LSS_Supported=0
+
+[DummyUsage]
+Dummy0001=0
+Dummy0002=0
+Dummy0003=0
+Dummy0004=0
+Dummy0005=1
+Dummy0006=1
+Dummy0007=1
+
+[Comments]
+Lines=0
+
+[MandatoryObjects]
+SupportedObjects=3
+1=0x1000
+2=0x1001
+3=0x1018
+
+[1000]
+ParameterName=Device Type
+ObjectType=0x7
+DataType=0x0007
+AccessType=ro
+DefaultValue=0x000F0191
+PDOMapping=0
+
+[1001]
+ParameterName=Error Register
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=0
+PDOMapping=0
+
+[1018]
+ParameterName=Identity Object
+ObjectType=0x9
+SubNumber=4
+
+[1018sub0]
+ParameterName=number of entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=3
+PDOMapping=0
+
+[1018sub1]
+ParameterName=Vendor ID
+ObjectType=0x7
+DataType=0x0007
+AccessType=ro
+DefaultValue=0x00000175
+PDOMapping=0
+
+[1018sub2]
+ParameterName=Product Code
+ObjectType=0x7
+DataType=0x0007
+AccessType=ro
+DefaultValue=0x00100000
+PDOMapping=0
+
+[1018sub3]
+ParameterName=Revision number
+ObjectType=0x7
+DataType=0x0007
+AccessType=ro
+DefaultValue=0x00010001
+PDOMapping=0
+
+[OptionalObjects]
+SupportedObjects=41
+1=0x1002
+2=0x1005
+3=0x1008
+4=0x1009
+5=0x100A
+6=0x100C
+7=0x100D
+8=0x1010
+9=0x1011
+10=0x1016
+11=0x1017
+12=0x1020
+13=0x1400
+14=0x1401
+15=0x1402
+16=0x1403
+17=0x1600
+18=0x1601
+19=0x1602
+20=0x1603
+21=0x1800
+22=0x1801
+23=0x1802
+24=0x1803
+25=0x1A00
+26=0x1A01
+27=0x1A02
+28=0x1A03
+29=0x1F50
+30=0x6000
+31=0x6002
+32=0x6200
+33=0x6202
+34=0x6206
+35=0x6207
+36=0x6401
+37=0x6411
+38=0x6423
+39=0x6426
+40=0x6443
+41=0x6444
+
+[1002]
+ParameterName=PEAK Status Register
+ObjectType=0x7
+DataType=0x0007
+AccessType=ro
+PDOMapping=0
+
+[1005]
+ParameterName=COB-ID SYNC
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x00000080
+PDOMapping=0
+
+[1008]
+ParameterName=Manufacturer Device Name
+ObjectType=0x7
+DataType=0x0009
+AccessType=const
+PDOMapping=0
+
+[1009]
+ParameterName=Manufacturer Hardware Version
+ObjectType=0x7
+DataType=0x0009
+AccessType=const
+PDOMapping=0
+
+[100a]
+ParameterName=Manufacturer Software Version
+ObjectType=0x7
+DataType=0x0009
+AccessType=const
+PDOMapping=0
+
+[100c]
+ParameterName=Guard Time
+ObjectType=0x7
+DataType=0x0006
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[100d]
+ParameterName=Life Time Factor
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0x00
+PDOMapping=0
+
+[1010]
+ParameterName=Store Parameter Field
+ObjectType=0x8
+SubNumber=2
+
+[1010sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=1
+PDOMapping=0
+
+[1010sub1]
+ParameterName=Save all Parameters
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+PDOMapping=0
+
+[1011]
+ParameterName=Restore Default Parameters
+ObjectType=0x8
+SubNumber=2
+
+[1011sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=1
+PDOMapping=0
+
+[1011sub1]
+ParameterName=Restore all Default Parameters
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+PDOMapping=0
+
+[1016]
+ParameterName=Consumer Heartbeat Time
+ObjectType=0x8
+SubNumber=4
+
+[1016sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=3
+PDOMapping=0
+LowLimit=0x1
+
+[1016sub1]
+ParameterName=Consumer Heartbeat Time
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1016sub2]
+ParameterName=Consumer Heartbeat Time
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1016sub3]
+ParameterName=Consumer Heartbeat Time
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1017]
+ParameterName=Producer Heartbeat Time
+ObjectType=0x7
+DataType=0x0006
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1020]
+ParameterName=Verify Configuration
+ObjectType=0x8
+SubNumber=3
+
+[1020sub0]
+ParameterName=Number of entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=2
+PDOMapping=0
+
+[1020sub1]
+ParameterName=Configuration date
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+PDOMapping=0
+
+[1020sub2]
+ParameterName=Configuration time
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+PDOMapping=0
+
+[1400]
+ParameterName=Receive PDO Communication Parameter
+ObjectType=0x9
+SubNumber=3
+
+[1400sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=2
+PDOMapping=0
+
+[1400sub1]
+ParameterName=COB-ID
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=$NODEID+0x200
+PDOMapping=0
+LowLimit=0x00000001
+HighLimit=0xFFFFFFFF
+
+[1400sub2]
+ParameterName=Transmission Type
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=255
+PDOMapping=0
+
+[1401]
+ParameterName=Receive PDO Communication Parameter
+ObjectType=0x9
+SubNumber=3
+
+[1401sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=2
+PDOMapping=0
+
+[1401sub1]
+ParameterName=COB-ID
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=$NODEID+0x300
+PDOMapping=0
+LowLimit=0x00000001
+HighLimit=0xFFFFFFFF
+
+[1401sub2]
+ParameterName=Transmission Type
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=255
+PDOMapping=0
+
+[1402]
+ParameterName=Receive PDO Communication Parameter
+ObjectType=0x9
+SubNumber=3
+
+[1402sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=2
+PDOMapping=0
+LowLimit=0x02
+HighLimit=0x05
+
+[1402sub1]
+ParameterName=COB-ID
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=$NODEID+0x80000400
+PDOMapping=0
+LowLimit=0x00000001
+HighLimit=0xFFFFFFFF
+
+[1402sub2]
+ParameterName=Transmission Type
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=255
+PDOMapping=0
+
+[1403]
+ParameterName=Receive PDO Communication Parameter
+ObjectType=0x9
+SubNumber=3
+
+[1403sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=2
+PDOMapping=0
+LowLimit=0x02
+HighLimit=0x05
+
+[1403sub1]
+ParameterName=COB-ID
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=$NODEID+0x80000500
+PDOMapping=0
+LowLimit=0x00000001
+HighLimit=0xFFFFFFFF
+
+[1403sub2]
+ParameterName=Transmission Type
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=255
+PDOMapping=0
+
+[1600]
+ParameterName=Receive PDO Mapping Parameter
+ObjectType=0x9
+SubNumber=2
+
+[1600sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=1
+PDOMapping=0
+
+[1600sub1]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x62000108
+PDOMapping=0
+
+[1601]
+ParameterName=Receive PDO Mapping Parameter
+ObjectType=0x9
+SubNumber=5
+
+[1601sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=4
+PDOMapping=0
+
+[1601sub1]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64110110
+PDOMapping=0
+
+[1601sub2]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64110210
+PDOMapping=0
+
+[1601sub3]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64110310
+PDOMapping=0
+
+[1601sub4]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64110410
+PDOMapping=0
+
+[1602]
+ParameterName=Receive PDO Mapping Parameter
+ObjectType=0x9
+SubNumber=1
+
+[1602sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1603]
+ParameterName=Receive PDO Mapping Parameter
+ObjectType=0x9
+SubNumber=1
+
+[1603sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1800]
+ParameterName=Transmit PDO Communication Parameter
+ObjectType=0x9
+SubNumber=5
+
+[1800sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=5
+PDOMapping=0
+LowLimit=0x02
+HighLimit=0x05
+
+[1800sub1]
+ParameterName=COB-ID
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=$NODEID+0x180
+PDOMapping=0
+LowLimit=0x00000001
+HighLimit=0xFFFFFFFF
+
+[1800sub2]
+ParameterName=Transmission Type
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=255
+PDOMapping=0
+
+[1800sub3]
+ParameterName=Inhibit Time
+ObjectType=0x7
+DataType=0x0006
+AccessType=rw
+DefaultValue=0x0000
+PDOMapping=0
+
+[1800sub5]
+ParameterName=Event Timer
+ObjectType=0x7
+DataType=0x0006
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1801]
+ParameterName=Transmit PDO Communication Parameter
+ObjectType=0x9
+SubNumber=5
+
+[1801sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=5
+PDOMapping=0
+LowLimit=0x02
+HighLimit=0x05
+
+[1801sub1]
+ParameterName=COB-ID
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=$NODEID+0x280
+PDOMapping=0
+LowLimit=0x00000001
+HighLimit=0xFFFFFFFF
+
+[1801sub2]
+ParameterName=Transmission Type
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=255
+PDOMapping=0
+
+[1801sub3]
+ParameterName=Inhibit Time
+ObjectType=0x7
+DataType=0x0006
+AccessType=rw
+DefaultValue=0x0000
+PDOMapping=0
+
+[1801sub5]
+ParameterName=Event Timer
+ObjectType=0x7
+DataType=0x0006
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1802]
+ParameterName=Transmit PDO Communication Parameter
+ObjectType=0x9
+SubNumber=5
+
+[1802sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=5
+PDOMapping=0
+LowLimit=0x02
+HighLimit=0x05
+
+[1802sub1]
+ParameterName=COB-ID
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=$NODEID+0x380
+PDOMapping=0
+LowLimit=0x00000001
+HighLimit=0xFFFFFFFF
+
+[1802sub2]
+ParameterName=Transmission Type
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=255
+PDOMapping=0
+
+[1802sub3]
+ParameterName=Inhibit Time
+ObjectType=0x7
+DataType=0x0006
+AccessType=rw
+DefaultValue=0x0000
+PDOMapping=0
+
+[1802sub5]
+ParameterName=Event Timer
+ObjectType=0x7
+DataType=0x0006
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1803]
+ParameterName=Transmit PDO Communication Parameter
+ObjectType=0x9
+SubNumber=5
+
+[1803sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=5
+PDOMapping=0
+LowLimit=0x02
+HighLimit=0x05
+
+[1803sub1]
+ParameterName=COB-ID
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=$NODEID+0x80000480
+PDOMapping=0
+LowLimit=0x00000001
+HighLimit=0xFFFFFFFF
+
+[1803sub2]
+ParameterName=Transmission Type
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=255
+PDOMapping=0
+
+[1803sub3]
+ParameterName=Inhibit Time
+ObjectType=0x7
+DataType=0x0006
+AccessType=rw
+DefaultValue=0x0000
+PDOMapping=0
+
+[1803sub5]
+ParameterName=Event Timer
+ObjectType=0x7
+DataType=0x0006
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1a00]
+ParameterName=Transmit PDO Mapping Parameter
+ObjectType=0x9
+SubNumber=2
+
+[1a00sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=1
+PDOMapping=0
+
+[1a00sub1]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x60000108
+PDOMapping=0
+
+[1a01]
+ParameterName=Transmit PDO Mapping Parameter
+ObjectType=0x9
+SubNumber=5
+
+[1a01sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=4
+PDOMapping=0
+
+[1a01sub1]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64010110
+PDOMapping=0
+
+[1a01sub2]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64010210
+PDOMapping=0
+
+[1a01sub3]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64010310
+PDOMapping=0
+
+[1a01sub4]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64010410
+PDOMapping=0
+
+[1a02]
+ParameterName=Transmit PDO Mapping Parameter
+ObjectType=0x9
+SubNumber=5
+
+[1a02sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=4
+PDOMapping=0
+
+[1a02sub1]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64010510
+PDOMapping=0
+
+[1a02sub2]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64010610
+PDOMapping=0
+
+[1a02sub3]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64010710
+PDOMapping=0
+
+[1a02sub4]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64010810
+PDOMapping=0
+
+[1a03]
+ParameterName=Transmit PDO Mapping Parameter
+ObjectType=0x9
+SubNumber=1
+
+[1a03sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1f50]
+ParameterName=Download Program Data
+ObjectType=0x8
+SubNumber=2
+
+[1f50sub0]
+ParameterName=Number of elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=3
+PDOMapping=0
+
+[1f50sub3]
+ParameterName=Download Program Data - HW Settings
+ObjectType=0x7
+DataType=0x000F
+AccessType=rw
+PDOMapping=0
+
+[6000]
+ParameterName=Read Digital Input 8-bit
+ObjectType=0x8
+SubNumber=2
+
+[6000sub0]
+ParameterName=Number of Elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=1
+PDOMapping=0
+
+[6000sub1]
+ParameterName=DigInput8_1
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+PDOMapping=1
+
+[6002]
+ParameterName=Polarity Digital Input
+ObjectType=0x8
+SubNumber=2
+
+[6002sub0]
+ParameterName=Number of Elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=1
+PDOMapping=0
+
+[6002sub1]
+ParameterName=Polarity8_1
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6200]
+ParameterName=Write Digital Output 8-bit
+ObjectType=0x8
+SubNumber=2
+
+[6200sub0]
+ParameterName=Number of elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=1
+PDOMapping=0
+
+[6200sub1]
+ParameterName=DigOutput8_1
+ObjectType=0x7
+DataType=0x0005
+AccessType=rww
+PDOMapping=1
+
+[6202]
+ParameterName=Polarity Digital Output
+ObjectType=0x8
+SubNumber=2
+
+[6202sub0]
+ParameterName=Number of Elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=1
+PDOMapping=0
+
+[6202sub1]
+ParameterName=Polarity8_1
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6206]
+ParameterName=Error Mode Digital Output
+ObjectType=0x8
+SubNumber=2
+
+[6206sub0]
+ParameterName=Number of elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=1
+PDOMapping=0
+
+[6206sub1]
+ParameterName=Error Mode 1
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6207]
+ParameterName=Error Value Digital Output
+ObjectType=0x8
+SubNumber=2
+
+[6207sub0]
+ParameterName=Number of elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=1
+PDOMapping=0
+
+[6207sub1]
+ParameterName=Error Value 1
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6401]
+ParameterName=Read Analog Input 16-bit
+ObjectType=0x8
+SubNumber=9
+
+[6401sub0]
+ParameterName=Number of elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=8
+PDOMapping=0
+
+[6401sub1]
+ParameterName=AnalogInput16_1
+ObjectType=0x7
+DataType=0x0003
+AccessType=ro
+PDOMapping=1
+
+[6401sub2]
+ParameterName=AnalogInput16_2
+ObjectType=0x7
+DataType=0x0003
+AccessType=ro
+PDOMapping=1
+
+[6401sub3]
+ParameterName=AnalogInput16_3
+ObjectType=0x7
+DataType=0x0003
+AccessType=ro
+PDOMapping=1
+
+[6401sub4]
+ParameterName=AnalogInput16_4
+ObjectType=0x7
+DataType=0x0003
+AccessType=ro
+PDOMapping=1
+
+[6401sub5]
+ParameterName=AnalogInput16_5
+ObjectType=0x7
+DataType=0x0003
+AccessType=ro
+PDOMapping=1
+
+[6401sub6]
+ParameterName=AnalogInput16_6
+ObjectType=0x7
+DataType=0x0003
+AccessType=ro
+PDOMapping=1
+
+[6401sub7]
+ParameterName=AnalogInput16_7
+ObjectType=0x7
+DataType=0x0003
+AccessType=ro
+PDOMapping=1
+
+[6401sub8]
+ParameterName=AnalogInput16_8
+ObjectType=0x7
+DataType=0x0003
+AccessType=ro
+PDOMapping=1
+
+[6411]
+ParameterName=Write Analog Output 16-bit
+ObjectType=0x8
+SubNumber=5
+
+[6411sub0]
+ParameterName=Number of elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=4
+PDOMapping=0
+
+[6411sub1]
+ParameterName=AnalogOutput16_1
+ObjectType=0x7
+DataType=0x0003
+AccessType=rww
+PDOMapping=1
+
+[6411sub2]
+ParameterName=AnalogOutput16_2
+ObjectType=0x7
+DataType=0x0003
+AccessType=rww
+PDOMapping=1
+
+[6411sub3]
+ParameterName=AnalogOutput16_3
+ObjectType=0x7
+DataType=0x0003
+AccessType=rww
+PDOMapping=1
+
+[6411sub4]
+ParameterName=AnalogOutput16_4
+ObjectType=0x7
+DataType=0x0003
+AccessType=rww
+PDOMapping=1
+
+[6423]
+ParameterName=Analog Input Global Interrupt
+ObjectType=0x7
+DataType=0x0001
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6426]
+ParameterName=Analog Input Interrupt Delta
+ObjectType=0x8
+SubNumber=9
+
+[6426sub0]
+ParameterName=NrOfObjects
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=8
+PDOMapping=0
+
+[6426sub1]
+ParameterName=Analog Input Delta 1
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6426sub2]
+ParameterName=Analog Input Delta 2
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6426sub3]
+ParameterName=Analog Input Delta 3
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6426sub4]
+ParameterName=Analog Input Delta 4
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6426sub5]
+ParameterName=Analog Input Delta 5
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6426sub6]
+ParameterName=Analog Input Delta 6
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6426sub7]
+ParameterName=Analog Input Delta 7
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6426sub8]
+ParameterName=Analog Input Delta 8
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6443]
+ParameterName=Error Mode Analog Output
+ObjectType=0x8
+SubNumber=5
+
+[6443sub0]
+ParameterName=Number of elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=4
+PDOMapping=0
+
+[6443sub1]
+ParameterName=Error Mode 1
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6443sub2]
+ParameterName=Error Mode 2
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6443sub3]
+ParameterName=Error Mode 3
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6443sub4]
+ParameterName=Error Mode 4
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6444]
+ParameterName=Error Value Analog Output
+ObjectType=0x8
+SubNumber=5
+
+[6444sub0]
+ParameterName=Number of elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=4
+PDOMapping=0
+
+[6444sub1]
+ParameterName=Error Value 1
+ObjectType=0x7
+DataType=0x0004
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6444sub2]
+ParameterName=Error Value 2
+ObjectType=0x7
+DataType=0x0004
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6444sub3]
+ParameterName=Error Value 3
+ObjectType=0x7
+DataType=0x0004
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6444sub4]
+ParameterName=Error Value 4
+ObjectType=0x7
+DataType=0x0004
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[ManufacturerObjects]
+SupportedObjects=0
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/canfestival/test_config/master.od
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/test_config/master.od Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,314 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Read Inputs
+
+
+
+
+
+
+ Read Inputs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+master
+
+TestMaster
+
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/canfestival/test_config/nodelist.cpj
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/test_config/nodelist.cpj Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,7 @@
+[TOPOLOGY]
+NetName=None
+Nodes=0x01
+Node64Present=0x01
+Node64Name=micromod
+Node64DCFName=PEAK MicroMod.eds
+EDSBaseName=eds
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/canfestival/test_config/result.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/test_config/result.txt Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,257 @@
+1000 (Device Type): 12E
+1001 (Error Register): 0
+1005 (SYNC COB ID): 40000080
+1006 (Communication / Cycle Period): C350
+1016 (Consumer Heartbeat Time):
+1016 01 (Consumer Heartbeat Time): 4005DC
+1018 (Identity):
+1018 01 (Vendor ID): 0
+1018 02 (Product Code): 0
+1018 03 (Revision Number): 0
+1018 04 (Serial Number): 0
+1280 (Client SDO 1 Parameter):
+1280 01 (COB ID Client to Server (Transmit SDO)): 640
+1280 02 (COB ID Server to Client (Receive SDO)): 5C0
+1280 03 (Node ID of the SDO Server): 40
+1400 (Receive PDO 1 Parameter):
+1400 01 (COB ID used by PDO): 1C0
+1400 02 (Transmission Type): 1
+1400 03 (Inhibit Time): 0
+1400 04 (Compatibility Entry): 0
+1400 05 (Event Timer): 0
+1401 (Receive PDO 2 Parameter):
+1401 01 (COB ID used by PDO): 2C0
+1401 02 (Transmission Type): 1
+1401 03 (Inhibit Time): 0
+1401 04 (Compatibility Entry): 0
+1401 05 (Event Timer): 0
+1402 (Receive PDO 3 Parameter):
+1402 01 (COB ID used by PDO): 182
+1402 02 (Transmission Type): 1
+1402 03 (Inhibit Time): 0
+1402 04 (Compatibility Entry): 0
+1402 05 (Event Timer): 0
+1403 (Receive PDO 4 Parameter):
+1403 01 (COB ID used by PDO): 183
+1403 02 (Transmission Type): 1
+1403 03 (Inhibit Time): 0
+1403 04 (Compatibility Entry): 0
+1403 05 (Event Timer): 0
+1404 (Receive PDO 5 Parameter):
+1404 01 (COB ID used by PDO): 181
+1404 02 (Transmission Type): 1
+1404 03 (Inhibit Time): 0
+1404 04 (Compatibility Entry): 0
+1404 05 (Event Timer): 0
+1600 (Receive PDO 1 Mapping):
+1600 01 (PDO 1 Mapping for an application object 1): 22400108
+1600 02 (PDO 1 Mapping for an application object 2): 0
+1601 (Receive PDO 2 Mapping):
+1601 01 (PDO 2 Mapping for an application object 1): 20000310
+1601 02 (PDO 2 Mapping for an application object 2): 23400110
+1601 03 (PDO 2 Mapping for an application object 3): 23400210
+1601 04 (PDO 2 Mapping for an application object 4): 20000310
+1602 (Receive PDO 3 Mapping):
+1602 01 (PDO 3 Mapping for an application object 1): 24400120
+1602 02 (PDO 3 Mapping for an application object 2): 24400220
+1603 (Receive PDO 4 Mapping):
+1603 01 (PDO 4 Mapping for an application object 1): 24400320
+1604 (Receive PDO 5 Mapping):
+1604 01 (PDO 5 Mapping for an application object 1): 22400208
+1604 02 (PDO 5 Mapping for an application object 2): 24400420
+1800 (Transmit PDO 1 Parameter):
+1800 01 (COB ID used by PDO): {True:"$NODEID+0x%X80"%(base+1),False:0x80000000}[base<4]
+1800 02 (Transmission Type): 0
+1800 03 (Inhibit Time): 0
+1800 04 (Compatibility Entry): 0
+1800 05 (Event Timer): 0
+1801 (Transmit PDO 2 Parameter):
+1801 01 (COB ID used by PDO): 340
+1801 02 (Transmission Type): 1
+1801 03 (Inhibit Time): 0
+1801 04 (Compatibility Entry): 0
+1801 05 (Event Timer): 0
+1A00 (Transmit PDO 1 Mapping):
+1A00 01 (PDO 1 Mapping for a process data variable 1): 10010008
+1A01 (Transmit PDO 2 Mapping):
+1A01 01 (PDO 2 Mapping for a process data variable 1): 43400110
+1A01 02 (PDO 2 Mapping for a process data variable 2): 20000310
+1A01 03 (PDO 2 Mapping for a process data variable 3): 20000310
+1A01 04 (PDO 2 Mapping for a process data variable 4): 20000310
+1F22 (Concise DCF):
+1F22 01 (Concise DCF for Node 1):
+1F22 02 (Concise DCF for Node 2):
+1F22 03 (Concise DCF for Node 3):
+1F22 04 (Concise DCF for Node 4):
+1F22 05 (Concise DCF for Node 5):
+1F22 06 (Concise DCF for Node 6):
+1F22 07 (Concise DCF for Node 7):
+1F22 08 (Concise DCF for Node 8):
+1F22 09 (Concise DCF for Node 9):
+1F22 0A (Concise DCF for Node 10):
+1F22 0B (Concise DCF for Node 11):
+1F22 0C (Concise DCF for Node 12):
+1F22 0D (Concise DCF for Node 13):
+1F22 0E (Concise DCF for Node 14):
+1F22 0F (Concise DCF for Node 15):
+1F22 10 (Concise DCF for Node 16):
+1F22 11 (Concise DCF for Node 17):
+1F22 12 (Concise DCF for Node 18):
+1F22 13 (Concise DCF for Node 19):
+1F22 14 (Concise DCF for Node 20):
+1F22 15 (Concise DCF for Node 21):
+1F22 16 (Concise DCF for Node 22):
+1F22 17 (Concise DCF for Node 23):
+1F22 18 (Concise DCF for Node 24):
+1F22 19 (Concise DCF for Node 25):
+1F22 1A (Concise DCF for Node 26):
+1F22 1B (Concise DCF for Node 27):
+1F22 1C (Concise DCF for Node 28):
+1F22 1D (Concise DCF for Node 29):
+1F22 1E (Concise DCF for Node 30):
+1F22 1F (Concise DCF for Node 31):
+1F22 20 (Concise DCF for Node 32):
+1F22 21 (Concise DCF for Node 33):
+1F22 22 (Concise DCF for Node 34):
+1F22 23 (Concise DCF for Node 35):
+1F22 24 (Concise DCF for Node 36):
+1F22 25 (Concise DCF for Node 37):
+1F22 26 (Concise DCF for Node 38):
+1F22 27 (Concise DCF for Node 39):
+1F22 28 (Concise DCF for Node 40):
+1F22 29 (Concise DCF for Node 41):
+1F22 2A (Concise DCF for Node 42):
+1F22 2B (Concise DCF for Node 43):
+1F22 2C (Concise DCF for Node 44):
+1F22 2D (Concise DCF for Node 45):
+1F22 2E (Concise DCF for Node 46):
+1F22 2F (Concise DCF for Node 47):
+1F22 30 (Concise DCF for Node 48):
+1F22 31 (Concise DCF for Node 49):
+1F22 32 (Concise DCF for Node 50):
+1F22 33 (Concise DCF for Node 51):
+1F22 34 (Concise DCF for Node 52):
+1F22 35 (Concise DCF for Node 53):
+1F22 36 (Concise DCF for Node 54):
+1F22 37 (Concise DCF for Node 55):
+1F22 38 (Concise DCF for Node 56):
+1F22 39 (Concise DCF for Node 57):
+1F22 3A (Concise DCF for Node 58):
+1F22 3B (Concise DCF for Node 59):
+1F22 3C (Concise DCF for Node 60):
+1F22 3D (Concise DCF for Node 61):
+1F22 3E (Concise DCF for Node 62):
+1F22 3F (Concise DCF for Node 63):
+1F22 40 (Concise DCF for Node 64): 23 arg defined
+1F22 40, arg 1: 1800 01 00000004 800001C0
+1F22 40, arg 2: 1800 02 00000001 01
+1F22 40, arg 3: 1800 01 00000004 000001C0
+1F22 40, arg 4: 1801 01 00000004 800002C0
+1F22 40, arg 5: 1801 02 00000001 01
+1F22 40, arg 6: 1801 01 00000004 000002C0
+1F22 40, arg 7: 1401 01 00000004 80000340
+1F22 40, arg 8: 1401 02 00000001 01
+1F22 40, arg 9: 1401 01 00000004 00000340
+1F22 40, arg 10: 1804 01 00000004 80000181
+1F22 40, arg 11: 1804 02 00000001 01
+1F22 40, arg 12: 1804 01 00000004 00000181
+1F22 40, arg 13: 1A04 01 00000004 60020108
+1F22 40, arg 14: 1A04 02 00000004 64260120
+1F22 40, arg 15: 1805 01 00000004 80000182
+1F22 40, arg 16: 1805 02 00000001 01
+1F22 40, arg 17: 1805 01 00000004 00000182
+1F22 40, arg 18: 1A05 01 00000004 64260220
+1F22 40, arg 19: 1A05 02 00000004 64260320
+1F22 40, arg 20: 1806 01 00000004 80000183
+1F22 40, arg 21: 1806 02 00000001 01
+1F22 40, arg 22: 1806 01 00000004 00000183
+1F22 40, arg 23: 1A06 01 00000004 64260420
+1F22 41 (Concise DCF for Node 65):
+1F22 42 (Concise DCF for Node 66):
+1F22 43 (Concise DCF for Node 67):
+1F22 44 (Concise DCF for Node 68):
+1F22 45 (Concise DCF for Node 69):
+1F22 46 (Concise DCF for Node 70):
+1F22 47 (Concise DCF for Node 71):
+1F22 48 (Concise DCF for Node 72):
+1F22 49 (Concise DCF for Node 73):
+1F22 4A (Concise DCF for Node 74):
+1F22 4B (Concise DCF for Node 75):
+1F22 4C (Concise DCF for Node 76):
+1F22 4D (Concise DCF for Node 77):
+1F22 4E (Concise DCF for Node 78):
+1F22 4F (Concise DCF for Node 79):
+1F22 50 (Concise DCF for Node 80):
+1F22 51 (Concise DCF for Node 81):
+1F22 52 (Concise DCF for Node 82):
+1F22 53 (Concise DCF for Node 83):
+1F22 54 (Concise DCF for Node 84):
+1F22 55 (Concise DCF for Node 85):
+1F22 56 (Concise DCF for Node 86):
+1F22 57 (Concise DCF for Node 87):
+1F22 58 (Concise DCF for Node 88):
+1F22 59 (Concise DCF for Node 89):
+1F22 5A (Concise DCF for Node 90):
+1F22 5B (Concise DCF for Node 91):
+1F22 5C (Concise DCF for Node 92):
+1F22 5D (Concise DCF for Node 93):
+1F22 5E (Concise DCF for Node 94):
+1F22 5F (Concise DCF for Node 95):
+1F22 60 (Concise DCF for Node 96):
+1F22 61 (Concise DCF for Node 97):
+1F22 62 (Concise DCF for Node 98):
+1F22 63 (Concise DCF for Node 99):
+1F22 64 (Concise DCF for Node 100):
+1F22 65 (Concise DCF for Node 101):
+1F22 66 (Concise DCF for Node 102):
+1F22 67 (Concise DCF for Node 103):
+1F22 68 (Concise DCF for Node 104):
+1F22 69 (Concise DCF for Node 105):
+1F22 6A (Concise DCF for Node 106):
+1F22 6B (Concise DCF for Node 107):
+1F22 6C (Concise DCF for Node 108):
+1F22 6D (Concise DCF for Node 109):
+1F22 6E (Concise DCF for Node 110):
+1F22 6F (Concise DCF for Node 111):
+1F22 70 (Concise DCF for Node 112):
+1F22 71 (Concise DCF for Node 113):
+1F22 72 (Concise DCF for Node 114):
+1F22 73 (Concise DCF for Node 115):
+1F22 74 (Concise DCF for Node 116):
+1F22 75 (Concise DCF for Node 117):
+1F22 76 (Concise DCF for Node 118):
+1F22 77 (Concise DCF for Node 119):
+1F22 78 (Concise DCF for Node 120):
+1F22 79 (Concise DCF for Node 121):
+1F22 7A (Concise DCF for Node 122):
+1F22 7B (Concise DCF for Node 123):
+1F22 7C (Concise DCF for Node 124):
+1F22 7D (Concise DCF for Node 125):
+1F22 7E (Concise DCF for Node 126):
+1F22 7F (Concise DCF for Node 127):
+2000 (Read Inputs): 0
+2240 (beremiz__IB0_1_64):
+2240 01 (24576_1): 0
+2240 02 (24578_1): 0
+2340 (beremiz__IW0_1_64):
+2340 01 (25601_2): 0
+2340 02 (25601_3): 0
+2440 (beremiz__ID0_1_64):
+2440 01 (25638_2): 0
+2440 02 (25638_3): 0
+2440 03 (25638_4): 0
+2440 04 (25638_1): 0
+4340 (beremiz__QW0_1_64):
+4340 01 (25617_1): 0
+
+********POINTERS*********
+{(4096, 0): '__ID0_1_4096_0',
+ (8768, 1): '__IB0_1_64_24576_1',
+ (8768, 2): '__IB0_1_64_24578_1',
+ (9024, 1): '__IW0_1_64_25601_2',
+ (9024, 2): '__IW0_1_64_25601_3',
+ (9280, 1): '__ID0_1_64_25638_2',
+ (9280, 2): '__ID0_1_64_25638_3',
+ (9280, 3): '__ID0_1_64_25638_4',
+ (9280, 4): '__ID0_1_64_25638_1',
+ (17216, 1): '__QW0_1_64_25617_1'}
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/PythonEditor.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/PythonEditor.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,505 @@
+import wx, wx.grid
+import wx.stc as stc
+import keyword
+
+from controls import EditorPanel
+
+if wx.Platform == '__WXMSW__':
+ faces = { 'times': 'Times New Roman',
+ 'mono' : 'Courier New',
+ 'helv' : 'Arial',
+ 'other': 'Comic Sans MS',
+ 'size' : 10,
+ 'size2': 8,
+ }
+elif wx.Platform == '__WXMAC__':
+ faces = { 'times': 'Times New Roman',
+ 'mono' : 'Monaco',
+ 'helv' : 'Arial',
+ 'other': 'Comic Sans MS',
+ 'size' : 12,
+ 'size2': 10,
+ }
+else:
+ faces = { 'times': 'Times',
+ 'mono' : 'Courier',
+ 'helv' : 'Helvetica',
+ 'other': 'new century schoolbook',
+ 'size' : 12,
+ 'size2': 10,
+ }
+
+[ID_PYTHONEDITOR,
+] = [wx.NewId() for _init_ctrls in range(1)]
+
+def GetCursorPos(old, new):
+ old_length = len(old)
+ new_length = len(new)
+ common_length = min(old_length, new_length)
+ i = 0
+ for i in xrange(common_length):
+ if old[i] != new[i]:
+ break
+ if old_length < new_length:
+ if common_length > 0 and old[i] != new[i]:
+ return i + new_length - old_length
+ else:
+ return i + new_length - old_length + 1
+ elif old_length > new_length or i < min(old_length, new_length) - 1:
+ if common_length > 0 and old[i] != new[i]:
+ return i
+ else:
+ return i + 1
+ else:
+ return None
+
+class PythonEditor(EditorPanel):
+
+ fold_symbols = 3
+
+ def _init_Editor(self, prnt):
+ self.Editor = stc.StyledTextCtrl(id=ID_PYTHONEDITOR, parent=prnt,
+ name="TextViewer", pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0)
+
+ self.Editor.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
+ self.Editor.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
+
+ self.Editor.SetLexer(stc.STC_LEX_PYTHON)
+ self.Editor.SetKeyWords(0, " ".join(keyword.kwlist))
+
+ self.Editor.SetProperty("fold", "1")
+ self.Editor.SetProperty("tab.timmy.whinge.level", "1")
+ self.Editor.SetMargins(0,0)
+
+ self.Editor.SetViewWhiteSpace(False)
+
+ self.Editor.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
+ self.Editor.SetEdgeColumn(78)
+
+ # Set up the numbers in the margin for margin #1
+ self.Editor.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
+ # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
+ self.Editor.SetMarginWidth(1, 40)
+
+ # Setup a margin to hold fold markers
+ self.Editor.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
+ self.Editor.SetMarginMask(2, stc.STC_MASK_FOLDERS)
+ self.Editor.SetMarginSensitive(2, True)
+ self.Editor.SetMarginWidth(2, 12)
+
+ if self.fold_symbols == 0:
+ # Arrow pointing right for contracted folders, arrow pointing down for expanded
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_ARROWDOWN, "black", "black")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_ARROW, "black", "black")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "black", "black")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "black", "black")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
+
+ elif self.fold_symbols == 1:
+ # Plus for contracted folders, minus for expanded
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_MINUS, "white", "black")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_PLUS, "white", "black")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "white", "black")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "white", "black")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
+
+ elif self.fold_symbols == 2:
+ # Like a flattened tree control using circular headers and curved joins
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_CIRCLEMINUS, "white", "#404040")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_CIRCLEPLUS, "white", "#404040")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#404040")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNERCURVE, "white", "#404040")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_CIRCLEPLUSCONNECTED, "white", "#404040")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE, "white", "#404040")
+
+ elif self.fold_symbols == 3:
+ # Like a flattened tree control using square headers
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "#808080")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "#808080")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#808080")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "#808080")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "#808080")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
+ self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "#808080")
+
+
+ self.Editor.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
+ self.Editor.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
+ self.Editor.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
+
+ # Global default style
+ if wx.Platform == '__WXMSW__':
+ self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier New')
+ elif wx.Platform == '__WXMAC__':
+ # TODO: if this looks fine on Linux too, remove the Mac-specific case
+ # and use this whenever OS != MSW.
+ self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Monaco')
+ else:
+ defsize = wx.SystemSettings.GetFont(wx.SYS_ANSI_FIXED_FONT).GetPointSize()
+ self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier,size:%d'%defsize)
+
+ # Clear styles and revert to default.
+ self.Editor.StyleClearAll()
+
+ # Following style specs only indicate differences from default.
+ # The rest remains unchanged.
+
+ # Line numbers in margin
+ self.Editor.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2')
+ # Highlighted brace
+ self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00')
+ # Unmatched brace
+ self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000')
+ # Indentation guide
+ self.Editor.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD")
+
+ # Python styles
+ self.Editor.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000')
+ # Comments
+ self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, 'fore:#008000,back:#F0FFF0')
+ self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0')
+ # Numbers
+ self.Editor.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080')
+ # Strings and characters
+ self.Editor.StyleSetSpec(wx.stc.STC_P_STRING, 'fore:#800080')
+ self.Editor.StyleSetSpec(wx.stc.STC_P_CHARACTER, 'fore:#800080')
+ # Keywords
+ self.Editor.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold')
+ # Triple quotes
+ self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA')
+ self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA')
+ # Class names
+ self.Editor.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold')
+ # Function names
+ self.Editor.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold')
+ # Operators
+ self.Editor.StyleSetSpec(wx.stc.STC_P_OPERATOR, 'fore:#800000,bold')
+ # Identifiers. I leave this as not bold because everything seems
+ # to be an identifier if it doesn't match the above criterae
+ self.Editor.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, 'fore:#000000')
+
+ # Caret color
+ self.Editor.SetCaretForeground("BLUE")
+ # Selection background
+ self.Editor.SetSelBackground(1, '#66CCFF')
+
+ self.Editor.SetSelBackground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT))
+ self.Editor.SetSelForeground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT))
+
+ # register some images for use in the AutoComplete box.
+ #self.RegisterImage(1, images.getSmilesBitmap())
+ self.Editor.RegisterImage(1,
+ wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16)))
+ self.Editor.RegisterImage(2,
+ wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16)))
+ self.Editor.RegisterImage(3,
+ wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
+
+ # Indentation and tab stuff
+ self.Editor.SetIndent(4) # Proscribed indent size for wx
+ self.Editor.SetIndentationGuides(True) # Show indent guides
+ self.Editor.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
+ self.Editor.SetTabIndents(True) # Tab key indents
+ self.Editor.SetTabWidth(4) # Proscribed tab size for wx
+ self.Editor.SetUseTabs(False) # Use spaces rather than tabs, or
+ # TabTimmy will complain!
+ # White space
+ self.Editor.SetViewWhiteSpace(False) # Don't view white space
+
+ # EOL: Since we are loading/saving ourselves, and the
+ # strings will always have \n's in them, set the STC to
+ # edit them that way.
+ self.Editor.SetEOLMode(wx.stc.STC_EOL_LF)
+ self.Editor.SetViewEOL(False)
+
+ # No right-edge mode indicator
+ self.Editor.SetEdgeMode(stc.STC_EDGE_NONE)
+
+ self.Editor.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE)
+
+ self.Editor.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_PYTHONEDITOR)
+ self.Editor.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+ self.Editor.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_PYTHONEDITOR)
+
+
+ def __init__(self, parent, controler, window):
+ EditorPanel.__init__(self, parent, "", window, controler)
+
+ self.DisableEvents = False
+ self.CurrentAction = None
+
+ img = wx.Bitmap(self.Controler.GetIconPath("Cfile.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
+ self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
+
+ def __del__(self):
+ self.Controler.OnCloseEditor(self)
+
+ def GetTitle(self):
+ fullname = self.Controler.PlugFullName()
+ if not self.Controler.PythonIsSaved():
+ return "~%s~" % fullname
+ return fullname
+
+ def GetBufferState(self):
+ return self.Controler.GetBufferState()
+
+ def Undo(self):
+ self.Controler.LoadPrevious()
+ self.RefreshView()
+
+ def Redo(self):
+ self.Controler.LoadNext()
+ self.RefreshView()
+
+ def HasNoModel(self):
+ return False
+
+ def OnModification(self, event):
+ if not self.DisableEvents:
+ mod_type = event.GetModificationType()
+ if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO):
+ if mod_type&wx.stc.STC_MOD_BEFOREINSERT:
+ if self.CurrentAction is None:
+ self.StartBuffering()
+ elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
+ self.Controler.EndBuffering()
+ self.StartBuffering()
+ self.CurrentAction = ("Add", event.GetPosition())
+ wx.CallAfter(self.RefreshModel)
+ elif mod_type&wx.stc.STC_MOD_BEFOREDELETE:
+ if self.CurrentAction == None:
+ self.StartBuffering()
+ elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
+ self.Controler.EndBuffering()
+ self.StartBuffering()
+ self.CurrentAction = ("Delete", event.GetPosition())
+ wx.CallAfter(self.RefreshModel)
+ event.Skip()
+
+ def OnDoDrop(self, event):
+ self.ResetBuffer()
+ wx.CallAfter(self.RefreshModel)
+ event.Skip()
+
+ # Buffer the last model state
+ def RefreshBuffer(self):
+ self.Controler.BufferPython()
+ if self.ParentWindow is not None:
+ self.ParentWindow.RefreshTitle()
+ self.ParentWindow.RefreshFileMenu()
+ self.ParentWindow.RefreshEditMenu()
+ self.ParentWindow.RefreshPageTitles()
+
+ def StartBuffering(self):
+ self.Controler.StartBuffering()
+ if self.ParentWindow is not None:
+ self.ParentWindow.RefreshTitle()
+ self.ParentWindow.RefreshFileMenu()
+ self.ParentWindow.RefreshEditMenu()
+ self.ParentWindow.RefreshPageTitles()
+
+ def ResetBuffer(self):
+ if self.CurrentAction != None:
+ self.Controler.EndBuffering()
+ self.CurrentAction = None
+
+ def RefreshView(self):
+ self.ResetBuffer()
+ self.DisableEvents = True
+ old_cursor_pos = self.Editor.GetCurrentPos()
+ old_text = self.Editor.GetText()
+ new_text = self.Controler.GetPythonCode()
+ self.Editor.SetText(new_text)
+ new_cursor_pos = GetCursorPos(old_text, new_text)
+ if new_cursor_pos != None:
+ self.Editor.GotoPos(new_cursor_pos)
+ else:
+ self.Editor.GotoPos(old_cursor_pos)
+ self.Editor.ScrollToColumn(0)
+ self.Editor.EmptyUndoBuffer()
+ self.DisableEvents = False
+
+ self.Editor.Colourise(0, -1)
+
+ def RefreshModel(self):
+ self.Controler.SetPythonCode(self.Editor.GetText())
+
+ def OnKeyPressed(self, event):
+ if self.Editor.CallTipActive():
+ self.Editor.CallTipCancel()
+ key = event.GetKeyCode()
+
+ if key == 32 and event.ControlDown():
+ pos = self.Editor.GetCurrentPos()
+
+ # Tips
+ if event.ShiftDown():
+ pass
+## self.CallTipSetBackground("yellow")
+## self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n'
+## 'show some suff, maybe parameters..\n\n'
+## 'fubar(param1, param2)')
+ # Code completion
+ else:
+ self.Editor.AutoCompSetIgnoreCase(False) # so this needs to match
+
+ # Images are specified with a appended "?type"
+ self.Editor.AutoCompShow(0, " ".join([word + "?1" for word in keyword.kwlist]))
+ else:
+ event.Skip()
+
+ def OnKillFocus(self, event):
+ self.Editor.AutoCompCancel()
+ event.Skip()
+
+ def OnUpdateUI(self, evt):
+ # check for matching braces
+ braceAtCaret = -1
+ braceOpposite = -1
+ charBefore = None
+ caretPos = self.Editor.GetCurrentPos()
+
+ if caretPos > 0:
+ charBefore = self.Editor.GetCharAt(caretPos - 1)
+ styleBefore = self.Editor.GetStyleAt(caretPos - 1)
+
+ # check before
+ if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
+ braceAtCaret = caretPos - 1
+
+ # check after
+ if braceAtCaret < 0:
+ charAfter = self.Editor.GetCharAt(caretPos)
+ styleAfter = self.Editor.GetStyleAt(caretPos)
+
+ if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
+ braceAtCaret = caretPos
+
+ if braceAtCaret >= 0:
+ braceOpposite = self.Editor.BraceMatch(braceAtCaret)
+
+ if braceAtCaret != -1 and braceOpposite == -1:
+ self.Editor.BraceBadLight(braceAtCaret)
+ else:
+ self.Editor.BraceHighlight(braceAtCaret, braceOpposite)
+ #pt = self.Editor.PointFromPosition(braceOpposite)
+ #self.Editor.Refresh(True, wxRect(pt.x, pt.y, 5,5))
+ #print pt
+ #self.Editor.Refresh(False)
+
+
+ def OnMarginClick(self, evt):
+ # fold and unfold as needed
+ if evt.GetMargin() == 2:
+ if evt.GetShift() and evt.GetControl():
+ self.FoldAll()
+ else:
+ lineClicked = self.Editor.LineFromPosition(evt.GetPosition())
+
+ if self.Editor.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
+ if evt.GetShift():
+ self.Editor.SetFoldExpanded(lineClicked, True)
+ self.Expand(lineClicked, True, True, 1)
+ elif evt.GetControl():
+ if self.Editor.GetFoldExpanded(lineClicked):
+ self.Editor.SetFoldExpanded(lineClicked, False)
+ self.Expand(lineClicked, False, True, 0)
+ else:
+ self.Editor.SetFoldExpanded(lineClicked, True)
+ self.Expand(lineClicked, True, True, 100)
+ else:
+ self.Editor.ToggleFold(lineClicked)
+
+
+ def FoldAll(self):
+ lineCount = self.Editor.GetLineCount()
+ expanding = True
+
+ # find out if we are folding or unfolding
+ for lineNum in range(lineCount):
+ if self.Editor.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
+ expanding = not self.Editor.GetFoldExpanded(lineNum)
+ break
+
+ lineNum = 0
+
+ while lineNum < lineCount:
+ level = self.Editor.GetFoldLevel(lineNum)
+ if level & stc.STC_FOLDLEVELHEADERFLAG and \
+ (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
+
+ if expanding:
+ self.Editor.SetFoldExpanded(lineNum, True)
+ lineNum = self.Expand(lineNum, True)
+ lineNum = lineNum - 1
+ else:
+ lastChild = self.Editor.GetLastChild(lineNum, -1)
+ self.Editor.SetFoldExpanded(lineNum, False)
+
+ if lastChild > lineNum:
+ self.Editor.HideLines(lineNum+1, lastChild)
+
+ lineNum = lineNum + 1
+
+
+
+ def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
+ lastChild = self.Editor.GetLastChild(line, level)
+ line = line + 1
+
+ while line <= lastChild:
+ if force:
+ if visLevels > 0:
+ self.Editor.ShowLines(line, line)
+ else:
+ self.Editor.HideLines(line, line)
+ else:
+ if doExpand:
+ self.Editor.ShowLines(line, line)
+
+ if level == -1:
+ level = self.Editor.GetFoldLevel(line)
+
+ if level & stc.STC_FOLDLEVELHEADERFLAG:
+ if force:
+ if visLevels > 1:
+ self.Editor.SetFoldExpanded(line, True)
+ else:
+ self.Editor.SetFoldExpanded(line, False)
+
+ line = self.Expand(line, doExpand, force, visLevels-1)
+
+ else:
+ if doExpand and self.Editor.GetFoldExpanded(line):
+ line = self.Expand(line, True, force, visLevels-1)
+ else:
+ line = self.Expand(line, False, force, visLevels-1)
+ else:
+ line = line + 1
+
+ return line
+
+ def Cut(self):
+ self.ResetBuffer()
+ self.DisableEvents = True
+ self.Editor.CmdKeyExecute(wx.stc.STC_CMD_CUT)
+ self.DisableEvents = False
+ self.RefreshModel()
+ self.RefreshBuffer()
+
+ def Copy(self):
+ self.Editor.CmdKeyExecute(wx.stc.STC_CMD_COPY)
+
+ def Paste(self):
+ self.ResetBuffer()
+ self.DisableEvents = True
+ self.Editor.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
+ self.DisableEvents = False
+ self.RefreshModel()
+ self.RefreshBuffer()
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/README
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/README Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+Asynchronous Python Interpreter
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/__init__.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+from python import *
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/__init__.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,13 @@
+from os import listdir, path
+
+_base_path = path.split(__file__)[0]
+
+__all__ = [name for name in listdir(_base_path) if path.isdir(path.join(_base_path, name)) and name.upper() != "CVS" or name.endswith(".py") and not name.startswith("__")]
+
+helps = []
+for name in __all__:
+ helpfilename = path.join(_base_path, name, "README")
+ if path.isfile(helpfilename):
+ helps.append(open(helpfilename).readline().strip())
+ else:
+ helps.append(name)
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/svgui/README
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/README Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+SVGUI HMI
\ No newline at end of file
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/svgui/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/__init__.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+from svgui import *
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/svgui/livesvg.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/livesvg.js Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,59 @@
+// import Nevow.Athena
+// import Divmod.Base
+
+function updateAttr(id, param, value) {
+ Nevow.Athena.Widget.fromAthenaID(1).callRemote('HMIexec', 'setattr', id, param, value);
+}
+
+var svguiWidgets = new Array();
+
+var currentObject = null;
+function setCurrentObject(obj) {
+ currentObject = obj;
+}
+function isCurrentObject(obj) {
+ return currentObject == obj;
+}
+
+function getSVGElementById(id) {
+ return document.getElementById(id);
+}
+
+function blockSVGElementDrag(element) {
+ element.addEventListener("draggesture", function(event){event.stopPropagation()}, true);
+}
+
+LiveSVGPage.LiveSVGWidget = Nevow.Athena.Widget.subclass('LiveSVGPage.LiveSVGWidget');
+LiveSVGPage.LiveSVGWidget.methods(
+
+ function handleEvent(self, evt) {
+ if (currentObject != null) {
+ currentObject.handleEvent(evt);
+ }
+ },
+
+ function receiveData(self, data){
+ dataReceived = json_parse(data);
+ gadget = svguiWidgets[dataReceived.id]
+ if (gadget) {
+ gadget.updateValues(json_parse(dataReceived.kwargs));
+ }
+ //console.log("OBJET : " + dataReceived.back_id + " STATE : " + newState);
+ },
+
+ function init(self, arg1){
+ //console.log("Object received : " + arg1);
+ for (ind in arg1) {
+ gad = json_parse(arg1[ind]);
+ args = json_parse(gad.kwargs);
+ gadget = new svguilib[gad.__class__](self, gad.id, args);
+ svguiWidgets[gadget.id]=gadget;
+ //console.log('GADGET :' + gadget);
+ }
+ var elements = document.getElementsByTagName("svg");
+ for (var i = 0; i < elements.length; i++) {
+ elements[i].addEventListener("mouseup", self, false);
+ }
+ //console.log("SVGUIWIDGETS : " + svguiWidgets);
+ }
+);
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/svgui/pous.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pous.xml Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1428 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'createSVGUIControl("textControl", back_id="'
+
+
+
+
+
+
+ back_id
+
+
+
+
+
+
+ '")'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ BOOL#1
+
+
+
+
+
+
+
+
+
+
+ ID
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ID
+
+
+
+
+
+
+ set_text
+
+
+
+
+
+
+ 'setAttr('
+
+
+
+
+
+
+ ',"text","'
+
+
+
+
+
+
+ '")'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'createSVGUIControl("button",back_id="'
+
+
+
+
+
+
+ '",sele_id="'
+
+
+
+
+
+
+ ',active=True)'
+
+
+
+
+
+
+ BOOL#1
+
+
+
+
+
+
+ back_id
+
+
+
+
+
+
+ sele_id
+
+
+
+
+
+
+ set_state
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ID
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ state_in
+
+
+
+
+
+
+
+
+
+
+ state_out
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ID
+
+
+
+
+
+
+ 'setAttr('
+
+
+
+
+
+
+ ',"state",'
+
+
+
+
+
+
+ ')'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ID
+
+
+
+
+
+
+ 'int(getAttr('
+
+
+
+
+
+
+ ',"state",False))'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ '",toggle='
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ toggle
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'createSVGUIControl("button",back_id="'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ '",sele_id="'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ID
+
+
+
+
+
+
+ '",toggle=True,active=False)'
+
+
+
+
+
+
+ BOOL#1
+
+
+
+
+
+
+ back_id
+
+
+
+
+
+
+ sele_id
+
+
+
+
+
+
+ 'setAttr('
+
+
+
+
+
+
+ ',"state",'
+
+
+
+
+
+
+ ')'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ID
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ state_in
+
+
+
+
+
+
+
+
+
+
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/svgui/pyjs/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/__init__.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+from pyjs import *
+
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/svgui/pyjs/build.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/build.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,724 @@
+#!/usr/bin/env python
+
+import sys
+import os
+import shutil
+from copy import copy
+from os.path import join, dirname, basename, abspath, split, isfile, isdir
+from optparse import OptionParser
+import pyjs
+from cStringIO import StringIO
+try:
+ # Python 2.5 and above
+ from hashlib import md5
+except:
+ import md5
+import re
+
+usage = """
+ usage: %prog [options]
+
+This is the command line builder for the pyjamas project, which can
+be used to build Ajax applications from Python.
+For more information, see the website at http://pyjs.org/
+"""
+
+# GWT1.2 Impl | GWT1.2 Output | Pyjamas 0.2 Platform | Pyjamas 0.2 Output
+# -------------+-----------------------+----------------------+----------------------
+# IE6 | ie6 | IE6 | ie6
+# Opera | opera | Opera | opera
+# Safari | safari | Safari | safari
+# -- | gecko1_8 | Mozilla | mozilla
+# -- | gecko | OldMoz | oldmoz
+# Standard | all | (default code) | all
+# Mozilla | gecko1_8, gecko | -- | --
+# Old | safari, gecko, opera | -- | --
+
+version = "%prog pyjamas version 2006-08-19"
+
+# these names in lowercase need match the strings
+# returned by "provider$user.agent" in order to be selected corretly
+app_platforms = ['IE6', 'Opera', 'OldMoz', 'Safari', 'Mozilla']
+
+# usually defaults to e.g. /usr/share/pyjamas
+_data_dir = os.path.join(pyjs.prefix, "share/pyjamas")
+
+
+# .cache.html files produces look like this
+CACHE_HTML_PAT=re.compile('^[a-z]*.[0-9a-f]{32}\.cache\.html$')
+
+# ok these are the three "default" library directories, containing
+# the builtins (str, List, Dict, ord, round, len, range etc.)
+# the main pyjamas libraries (pyjamas.ui, pyjamas.Window etc.)
+# and the contributed addons
+
+for p in ["library/builtins",
+ "library",
+ "addons"]:
+ p = os.path.join(_data_dir, p)
+ if os.path.isdir(p):
+ pyjs.path.append(p)
+
+
+def read_boilerplate(data_dir, filename):
+ return open(join(data_dir, "builder/boilerplate", filename)).read()
+
+def copy_boilerplate(data_dir, filename, output_dir):
+ filename = join(data_dir, "builder/boilerplate", filename)
+ shutil.copy(filename, output_dir)
+
+
+# taken and modified from python2.4
+def copytree_exists(src, dst, symlinks=False):
+ if not os.path.exists(src):
+ return
+
+ names = os.listdir(src)
+ try:
+ os.mkdir(dst)
+ except:
+ pass
+
+ errors = []
+ for name in names:
+ if name.startswith('CVS'):
+ continue
+ if name.startswith('.git'):
+ continue
+ if name.startswith('.svn'):
+ continue
+
+ srcname = os.path.join(src, name)
+ dstname = os.path.join(dst, name)
+ try:
+ if symlinks and os.path.islink(srcname):
+ linkto = os.readlink(srcname)
+ os.symlink(linkto, dstname)
+ elif isdir(srcname):
+ copytree_exists(srcname, dstname, symlinks)
+ else:
+ shutil.copy2(srcname, dstname)
+ except (IOError, os.error), why:
+ errors.append((srcname, dstname, why))
+ if errors:
+ print errors
+
+def check_html_file(source_file, dest_path):
+ """ Checks if a base HTML-file is available in the PyJamas
+ output directory.
+ If the HTML-file isn't available, it will be created.
+
+ If a CSS-file with the same name is available
+ in the output directory, a reference to this CSS-file
+ is included.
+
+ If no CSS-file is found, this function will look for a special
+ CSS-file in the output directory, with the name
+ "pyjamas_default.css", and if found it will be referenced
+ in the generated HTML-file.
+
+ [thank you to stef mientki for contributing this function]
+ """
+
+ base_html = """\
+
+
+
+
+ %(css)s
+ %(title)s
+
+
+
+
+
+"""
+
+ filename = os.path.split ( source_file )[1]
+ mod_name = os.path.splitext ( filename )[0]
+ file_name = os.path.join ( dest_path, mod_name + '.html' )
+
+ # if html file in output directory exists, leave it alone.
+ if os.path.exists ( file_name ):
+ return 0
+
+ if os.path.exists (
+ os.path.join ( dest_path, mod_name + '.css' ) ) :
+ css = ""
+ elif os.path.exists (
+ os.path.join ( dest_path, 'pyjamas_default.css' ) ) :
+ css = ""
+
+ else:
+ css = ''
+
+ title = 'PyJamas Auto-Generated HTML file ' + mod_name
+
+ base_html = base_html % {'modulename': mod_name, 'title': title, 'css': css}
+
+ fh = open (file_name, 'w')
+ fh.write (base_html)
+ fh.close ()
+
+ return 1
+
+
+def build(app_name, output, js_includes=(), debug=False, dynamic=0,
+ data_dir=None, cache_buster=False, optimize=False):
+
+ # make sure the output directory is always created in the current working
+ # directory or at the place given if it is an absolute path.
+ output = os.path.abspath(output)
+ msg = "Building '%(app_name)s' to output directory '%(output)s'" % locals()
+ if debug:
+ msg += " with debugging statements"
+ print msg
+
+ # check the output directory
+ if os.path.exists(output) and not os.path.isdir(output):
+ print >>sys.stderr, "Output destination %s exists and is not a directory" % output
+ return
+ if not os.path.isdir(output):
+ try:
+ print "Creating output directory"
+ os.mkdir(output)
+ except StandardError, e:
+ print >>sys.stderr, "Exception creating output directory %s: %s" % (output, e)
+
+ ## public dir
+ for p in pyjs.path:
+ pub_dir = join(p, 'public')
+ if isdir(pub_dir):
+ print "Copying: public directory of library %r" % p
+ copytree_exists(pub_dir, output)
+
+ ## AppName.html - can be in current or public directory
+ html_input_filename = app_name + ".html"
+ html_output_filename = join(output, basename(html_input_filename))
+ if os.path.isfile(html_input_filename):
+ if not os.path.isfile(html_output_filename) or \
+ os.path.getmtime(html_input_filename) > \
+ os.path.getmtime(html_output_filename):
+ try:
+ shutil.copy(html_input_filename, html_output_filename)
+ except:
+ print >>sys.stderr, "Warning: Missing module HTML file %s" % html_input_filename
+
+ print "Copying: %(html_input_filename)s" % locals()
+
+ if check_html_file(html_input_filename, output):
+ print >>sys.stderr, "Warning: Module HTML file %s has been auto-generated" % html_input_filename
+
+ ## pygwt.js
+
+ print "Copying: pygwt.js"
+
+ pygwt_js_template = read_boilerplate(data_dir, "pygwt.js")
+ pygwt_js_output = open(join(output, "pygwt.js"), "w")
+
+ print >>pygwt_js_output, pygwt_js_template
+
+ pygwt_js_output.close()
+
+ ## Images
+
+ print "Copying: Images and History"
+ copy_boilerplate(data_dir, "corner_dialog_topleft_black.png", output)
+ copy_boilerplate(data_dir, "corner_dialog_topright_black.png", output)
+ copy_boilerplate(data_dir, "corner_dialog_bottomright_black.png", output)
+ copy_boilerplate(data_dir, "corner_dialog_bottomleft_black.png", output)
+ copy_boilerplate(data_dir, "corner_dialog_edge_black.png", output)
+ copy_boilerplate(data_dir, "corner_dialog_topleft.png", output)
+ copy_boilerplate(data_dir, "corner_dialog_topright.png", output)
+ copy_boilerplate(data_dir, "corner_dialog_bottomright.png", output)
+ copy_boilerplate(data_dir, "corner_dialog_bottomleft.png", output)
+ copy_boilerplate(data_dir, "corner_dialog_edge.png", output)
+ copy_boilerplate(data_dir, "tree_closed.gif", output)
+ copy_boilerplate(data_dir, "tree_open.gif", output)
+ copy_boilerplate(data_dir, "tree_white.gif", output)
+ copy_boilerplate(data_dir, "history.html", output)
+
+
+ ## all.cache.html
+ app_files = generateAppFiles(data_dir, js_includes, app_name, debug,
+ output, dynamic, cache_buster, optimize)
+
+ ## AppName.nocache.html
+
+ print "Creating: %(app_name)s.nocache.html" % locals()
+
+ home_nocache_html_template = read_boilerplate(data_dir, "home.nocache.html")
+ home_nocache_html_output = open(join(output, app_name + ".nocache.html"),
+ "w")
+
+ # the selector templ is added to the selectScript function
+ select_tmpl = """O(["true","%s"],"%s");"""
+ script_selectors = StringIO()
+
+ for platform, file_prefix in app_files:
+ print >> script_selectors, select_tmpl % (platform, file_prefix)
+
+ print >>home_nocache_html_output, home_nocache_html_template % dict(
+ app_name = app_name,
+ script_selectors = script_selectors.getvalue(),
+ )
+
+ home_nocache_html_output.close()
+
+ print "Done. You can run your app by opening '%(html_output_filename)s' in a browser" % locals()
+
+
+def generateAppFiles(data_dir, js_includes, app_name, debug, output, dynamic,
+ cache_buster, optimize):
+
+ all_cache_html_template = read_boilerplate(data_dir, "all.cache.html")
+ mod_cache_html_template = read_boilerplate(data_dir, "mod.cache.html")
+
+ # clean out the old ones first
+ for name in os.listdir(output):
+ if CACHE_HTML_PAT.match(name):
+ p = join(output, name)
+ print "Deleting existing app file %s" % p
+ os.unlink(p)
+
+ app_files = []
+ tmpl = read_boilerplate(data_dir, "all.cache.html")
+ parser = pyjs.PlatformParser("platform")
+ app_headers = ''
+ scripts = [''%script \
+ for script in js_includes]
+ app_body = '\n'.join(scripts)
+
+ mod_code = {}
+ mod_libs = {}
+ modules = {}
+ app_libs = {}
+ early_app_libs = {}
+ app_code = {}
+ overrides = {}
+ pover = {}
+ app_modnames = {}
+ mod_levels = {}
+
+ # First, generate all the code.
+ # Second, (dynamic only), post-analyse the places where modules
+ # haven't changed
+ # Third, write everything out.
+
+ for platform in app_platforms:
+
+ mod_code[platform] = {}
+ mod_libs[platform] = {}
+ modules[platform] = []
+ pover[platform] = {}
+ app_libs[platform] = ''
+ early_app_libs[platform] = ''
+ app_code[platform] = {}
+ app_modnames[platform] = {}
+
+ # Application.Platform.cache.html
+
+ parser.setPlatform(platform)
+ app_translator = pyjs.AppTranslator(
+ parser=parser, dynamic=dynamic, optimize=optimize)
+ early_app_libs[platform], appcode = \
+ app_translator.translate(None, is_app=False,
+ debug=debug,
+ library_modules=['dynamicajax.js',
+ '_pyjs.js', 'sys',
+ 'pyjslib'])
+ pover[platform].update(app_translator.overrides.items())
+ for mname, name in app_translator.overrides.items():
+ pd = overrides.setdefault(mname, {})
+ pd[platform] = name
+
+ print appcode
+ #mod_code[platform][app_name] = appcode
+
+ # platform.Module.cache.js
+
+ modules_done = ['pyjslib', 'sys', '_pyjs.js']
+ #modules_to_do = [app_name] + app_translator.library_modules
+ modules_to_do = [app_name] + app_translator.library_modules
+
+ dependencies = {}
+
+ deps = map(pyjs.strip_py, modules_to_do)
+ for d in deps:
+ sublist = add_subdeps(dependencies, d)
+ modules_to_do += sublist
+ deps = uniquify(deps)
+ #dependencies[app_name] = deps
+
+ modules[platform] = modules_done + modules_to_do
+
+ while modules_to_do:
+
+ #print "modules to do", modules_to_do
+
+ mn = modules_to_do.pop()
+ mod_name = pyjs.strip_py(mn)
+
+ if mod_name in modules_done:
+ continue
+
+ modules_done.append(mod_name)
+
+ mod_cache_name = "%s.%s.cache.js" % (platform.lower(), mod_name)
+
+ parser.setPlatform(platform)
+ mod_translator = pyjs.AppTranslator(parser=parser, optimize=optimize)
+ mod_libs[platform][mod_name], mod_code[platform][mod_name] = \
+ mod_translator.translate(mod_name,
+ is_app=False,
+ debug=debug)
+ pover[platform].update(mod_translator.overrides.items())
+ for mname, name in mod_translator.overrides.items():
+ pd = overrides.setdefault(mname, {})
+ pd[platform] = name
+
+ mods = mod_translator.library_modules
+ modules_to_do += mods
+ modules[platform] += mods
+
+ deps = map(pyjs.strip_py, mods)
+ sd = subdeps(mod_name)
+ if len(sd) > 1:
+ deps += sd[:-1]
+ while mod_name in deps:
+ deps.remove(mod_name)
+
+ #print
+ #print
+ #print "modname preadd:", mod_name, deps
+ #print
+ #print
+ for d in deps:
+ sublist = add_subdeps(dependencies, d)
+ modules_to_do += sublist
+ modules_to_do += add_subdeps(dependencies, mod_name)
+ #print "modname:", mod_name, deps
+ deps = uniquify(deps)
+ #print "modname:", mod_name, deps
+ dependencies[mod_name] = deps
+
+ # work out the dependency ordering of the modules
+
+ mod_levels[platform] = make_deps(None, dependencies, modules_done)
+
+ # now write everything out
+
+ for platform in app_platforms:
+
+ early_app_libs_ = early_app_libs[platform]
+ app_libs_ = app_libs[platform]
+ app_code_ = app_code[platform]
+ #modules_ = filter_mods(app_name, modules[platform])
+ mods = flattenlist(mod_levels[platform])
+ mods.reverse()
+ modules_ = filter_mods(None, mods)
+
+ for mod_name in modules_:
+
+ mod_code_ = mod_code[platform][mod_name]
+
+ mod_name = pyjs.strip_py(mod_name)
+
+ override_name = "%s.%s" % (platform.lower(), mod_name)
+ if pover[platform].has_key(override_name):
+ mod_cache_name = "%s.cache.js" % (override_name)
+ else:
+ mod_cache_name = "%s.cache.js" % (mod_name)
+
+ print "Creating: " + mod_cache_name
+
+ modlevels = make_deps(None, dependencies, dependencies[mod_name])
+
+ modnames = []
+
+ for md in modlevels:
+ mnames = map(lambda x: "'%s'" % x, md)
+ mnames = "new pyjslib.List([\n\t\t\t%s])" % ',\n\t\t\t'.join(mnames)
+ modnames.append(mnames)
+
+ modnames.reverse()
+ modnames = "new pyjslib.List([\n\t\t%s\n\t])" % ',\n\t\t'.join(modnames)
+
+ # convert the overrides
+
+ overnames = map(lambda x: "'%s': '%s'" % x, pover[platform].items())
+ overnames = "new pyjslib.Dict({\n\t\t%s\n\t})" % ',\n\t\t'.join(overnames)
+
+ if dynamic:
+ mod_cache_html_output = open(join(output, mod_cache_name), "w")
+ else:
+ mod_cache_html_output = StringIO()
+
+ print >>mod_cache_html_output, mod_cache_html_template % dict(
+ mod_name = mod_name,
+ app_name = app_name,
+ modnames = modnames,
+ overrides = overnames,
+ mod_libs = mod_libs[platform][mod_name],
+ dynamic = dynamic,
+ mod_code = mod_code_,
+ )
+
+ if dynamic:
+ mod_cache_html_output.close()
+ else:
+ mod_cache_html_output.seek(0)
+ app_libs_ += mod_cache_html_output.read()
+
+ # write out the dependency ordering of the modules
+
+ app_modnames = []
+
+ for md in mod_levels[platform]:
+ mnames = map(lambda x: "'%s'" % x, md)
+ mnames = "new pyjslib.List([\n\t\t\t%s])" % ',\n\t\t\t'.join(mnames)
+ app_modnames.append(mnames)
+
+ app_modnames.reverse()
+ app_modnames = "new pyjslib.List([\n\t\t%s\n\t])" % ',\n\t\t'.join(app_modnames)
+
+ # convert the overrides
+
+ overnames = map(lambda x: "'%s': '%s'" % x, pover[platform].items())
+ overnames = "new pyjslib.Dict({\n\t\t%s\n\t})" % ',\n\t\t'.join(overnames)
+
+ #print "platform names", platform, overnames
+ #print pover
+
+ # now write app.allcache including dependency-ordered list of
+ # library modules
+
+ file_contents = all_cache_html_template % dict(
+ app_name = app_name,
+ early_app_libs = early_app_libs_,
+ app_libs = app_libs_,
+ app_code = app_code_,
+ app_body = app_body,
+ overrides = overnames,
+ platform = platform.lower(),
+ dynamic = dynamic,
+ app_modnames = app_modnames,
+ app_headers = app_headers
+ )
+ if cache_buster:
+ digest = md5.new(file_contents).hexdigest()
+ file_name = "%s.%s.%s" % (platform.lower(), app_name, digest)
+ else:
+ file_name = "%s.%s" % (platform.lower(), app_name)
+ file_name += ".cache.html"
+ out_path = join(output, file_name)
+ out_file = open(out_path, 'w')
+ out_file.write(file_contents)
+ out_file.close()
+ app_files.append((platform.lower(), file_name))
+ print "Created app file %s:%s: %s" % (
+ app_name, platform, out_path)
+
+ return app_files
+
+def flattenlist(ll):
+ res = []
+ for l in ll:
+ res += l
+ return res
+
+# creates sub-dependencies e.g. pyjamas.ui.Widget
+# creates pyjamas.ui.Widget, pyjamas.ui and pyjamas.
+def subdeps(m):
+ d = []
+ m = m.split(".")
+ for i in range(0, len(m)):
+ d.append('.'.join(m[:i+1]))
+ return d
+
+import time
+
+def add_subdeps(deps, mod_name):
+ sd = subdeps(mod_name)
+ if len(sd) == 1:
+ return []
+ #print "subdeps", mod_name, sd
+ #print "deps", deps
+ res = []
+ for i in range(0, len(sd)-1):
+ parent = sd[i]
+ child = sd[i+1]
+ l = deps.get(child, [])
+ l.append(parent)
+ deps[child] = l
+ if parent not in res:
+ res.append(parent)
+ #print deps
+ return res
+
+# makes unique and preserves list order
+def uniquify(md):
+ res = []
+ for m in md:
+ if m not in res:
+ res.append(m)
+ return res
+
+def filter_mods(app_name, md):
+ while 'sys' in md:
+ md.remove('sys')
+ while 'pyjslib' in md:
+ md.remove('pyjslib')
+ while app_name in md:
+ md.remove(app_name)
+ md = filter(lambda x: not x.endswith('.js'), md)
+ md = map(pyjs.strip_py, md)
+
+ return uniquify(md)
+
+def filter_deps(app_name, deps):
+
+ res = {}
+ for (k, l) in deps.items():
+ mods = filter_mods(k, l)
+ while k in mods:
+ mods.remove(k)
+ res[k] = mods
+ return res
+
+def has_nodeps(mod, deps):
+ if not deps.has_key(mod) or not deps[mod]:
+ return True
+ return False
+
+def nodeps_list(mod_list, deps):
+ res = []
+ for mod in mod_list:
+ if has_nodeps(mod, deps):
+ res.append(mod)
+ return res
+
+# this function takes a dictionary of dependent modules and
+# creates a list of lists. the first list will be modules
+# that have no dependencies; the second list will be those
+# modules that have the first list as dependencies; the
+# third will be those modules that have the first and second...
+# etc.
+
+
+def make_deps(app_name, deps, mod_list):
+ print "Calculating Dependencies ..."
+ mod_list = filter_mods(app_name, mod_list)
+ deps = filter_deps(app_name, deps)
+
+ if not mod_list:
+ return []
+
+ #print mod_list
+ #print deps
+
+ ordered_deps = []
+ last_len = -1
+ while deps:
+ l_deps = len(deps)
+ #print l_deps
+ if l_deps==last_len:
+ for m, dl in deps.items():
+ for d in dl:
+ if m in deps.get(d, []):
+ raise Exception('Circular Imports found: \n%s %s -> %s %s'
+ % (m, dl, d, deps[d]))
+ #raise Exception('Could not calculate dependencies: \n%s' % deps)
+ break
+ last_len = l_deps
+ #print "modlist", mod_list
+ nodeps = nodeps_list(mod_list, deps)
+ #print "nodeps", nodeps
+ mod_list = filter(lambda x: x not in nodeps, mod_list)
+ newdeps = {}
+ for k in deps.keys():
+ depslist = deps[k]
+ depslist = filter(lambda x: x not in nodeps, depslist)
+ if depslist:
+ newdeps[k] = depslist
+ #print "newdeps", newdeps
+ deps = newdeps
+ ordered_deps.append(nodeps)
+ #time.sleep(0)
+
+ if mod_list:
+ ordered_deps.append(mod_list) # last dependencies - usually the app(s)
+
+ ordered_deps.reverse()
+
+ return ordered_deps
+
+def main():
+ global app_platforms
+
+ parser = OptionParser(usage = usage, version = version)
+ parser.add_option("-o", "--output", dest="output",
+ help="directory to which the webapp should be written")
+ parser.add_option("-j", "--include-js", dest="js_includes", action="append",
+ help="javascripts to load into the same frame as the rest of the script")
+ parser.add_option("-I", "--library_dir", dest="library_dirs",
+ action="append", help="additional paths appended to PYJSPATH")
+ parser.add_option("-D", "--data_dir", dest="data_dir",
+ help="path for data directory")
+ parser.add_option("-m", "--dynamic-modules", action="store_true",
+ dest="dynamic", default=False,
+ help="Split output into separate dynamically-loaded modules (experimental)")
+ parser.add_option("-P", "--platforms", dest="platforms",
+ help="platforms to build for, comma-separated")
+ parser.add_option("-d", "--debug", action="store_true", dest="debug")
+ parser.add_option("-O", "--optimize", action="store_true",
+ dest="optimize", default=False,
+ help="Optimize generated code (removes all print statements)",
+ )
+ parser.add_option("-c", "--cache_buster", action="store_true",
+ dest="cache_buster",
+ help="Enable browser cache-busting (MD5 hash added to output filenames)")
+
+ parser.set_defaults(output = "output", js_includes=[], library_dirs=[],
+ platforms=(','.join(app_platforms)),
+ data_dir=os.path.join(sys.prefix, "share/pyjamas"),
+ dynamic=False,
+ cache_buster=False,
+ debug=False)
+ (options, args) = parser.parse_args()
+ if len(args) != 1:
+ parser.error("incorrect number of arguments")
+
+ data_dir = abspath(options.data_dir)
+
+ app_path = args[0]
+ if app_path.endswith('.py'):
+ app_path = abspath(app_path)
+ if not isfile(app_path):
+ parser.error("Application file not found %r" % app_path)
+ app_path, app_name = split(app_path)
+ app_name = app_name[:-3]
+ pyjs.path.append(app_path)
+ elif os.path.sep in app_path:
+ parser.error("Not a valid module declaration %r" % app_path)
+ else:
+ app_name = app_path
+
+ for d in options.library_dirs:
+ pyjs.path.append(abspath(d))
+
+ if options.platforms:
+ app_platforms = options.platforms.split(',')
+
+ # this is mostly for getting boilerplate stuff
+ data_dir = os.path.abspath(options.data_dir)
+
+ build(app_name, options.output, options.js_includes,
+ options.debug, options.dynamic and 1 or 0, data_dir,
+ options.cache_buster, options.optimize)
+
+if __name__ == "__main__":
+ main()
+
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/svgui/pyjs/jsonrpc/README.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/jsonrpc/README.txt Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,12 @@
+These classes are intended for use server-side.
+
+e.g. in a django view.py :
+
+ from pyjs.jsonrpc.django import JSONService, jsonremote
+
+ jsonservice = JSONRPCService()
+
+ @jsonremote(jsonservice)
+ def test(request, echo_param):
+ return "echoing the param back: %s" % echo_param
+
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/svgui/pyjs/jsonrpc/django/jsonrpc.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/jsonrpc/django/jsonrpc.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,226 @@
+# jsonrpc.py
+# original code: http://trac.pyworks.org/pyjamas/wiki/DjangoWithPyJamas
+# also from: http://www.pimentech.fr/technologies/outils
+from django.utils import simplejson
+from django.http import HttpResponse
+import sys
+
+from pyjs.jsonrpc import JSONRPCServiceBase
+# JSONRPCService and jsonremote are used in combination to drastically
+# simplify the provision of JSONRPC services. use as follows:
+#
+# jsonservice = JSONRPCService()
+#
+# @jsonremote(jsonservice)
+# def test(request, echo_param):
+# return "echoing the param back: %s" % echo_param
+#
+# dump jsonservice into urlpatterns:
+# (r'^service1/$', 'djangoapp.views.jsonservice'),
+
+class JSONRPCService(JSONRPCServiceBase):
+
+ def __call__(self, request, extra=None):
+ return self.process(request.raw_post_data)
+
+def jsonremote(service):
+ """Make JSONRPCService a decorator so that you can write :
+
+ from jsonrpc import JSONRPCService
+ chatservice = JSONRPCService()
+
+ @jsonremote(chatservice)
+ def login(request, user_name):
+ (...)
+ """
+ def remotify(func):
+ if isinstance(service, JSONRPCService):
+ service.add_method(func.__name__, func)
+ else:
+ emsg = 'Service "%s" not found' % str(service.__name__)
+ raise NotImplementedError, emsg
+ return func
+ return remotify
+
+
+# FormProcessor provides a mechanism for turning Django Forms into JSONRPC
+# Services. If you have an existing Django app which makes prevalent
+# use of Django Forms it will save you rewriting the app.
+# use as follows. in djangoapp/views.py :
+#
+# class SimpleForm(forms.Form):
+# testfield = forms.CharField(max_length=100)
+#
+# class SimpleForm2(forms.Form):
+# testfield = forms.CharField(max_length=20)
+#
+# processor = FormProcessor({'processsimpleform': SimpleForm,
+# 'processsimpleform2': SimpleForm2})
+#
+# this will result in a JSONRPC service being created with two
+# RPC functions. dump "processor" into urlpatterns to make it
+# part of the app:
+# (r'^formsservice/$', 'djangoapp.views.processor'),
+
+from django import forms
+
+def builderrors(form):
+ d = {}
+ for error in form.errors.keys():
+ if error not in d:
+ d[error] = []
+ for errorval in form.errors[error]:
+ d[error].append(unicode(errorval))
+ return d
+
+
+# contains the list of arguments in each field
+field_names = {
+ 'CharField': ['max_length', 'min_length'],
+ 'IntegerField': ['max_value', 'min_value'],
+ 'FloatField': ['max_value', 'min_value'],
+ 'DecimalField': ['max_value', 'min_value', 'max_digits', 'decimal_places'],
+ 'DateField': ['input_formats'],
+ 'DateTimeField': ['input_formats'],
+ 'TimeField': ['input_formats'],
+ 'RegexField': ['max_length', 'min_length'], # sadly we can't get the expr
+ 'EmailField': ['max_length', 'min_length'],
+ 'URLField': ['max_length', 'min_length', 'verify_exists', 'user_agent'],
+ 'ChoiceField': ['choices'],
+ 'FilePathField': ['path', 'match', 'recursive', 'choices'],
+ 'IPAddressField': ['max_length', 'min_length'],
+ }
+
+def describe_field_errors(field):
+ res = {}
+ field_type = field.__class__.__name__
+ msgs = {}
+ for n, m in field.error_messages.items():
+ msgs[n] = unicode(m)
+ res['error_messages'] = msgs
+ if field_type in ['ComboField', 'MultiValueField', 'SplitDateTimeField']:
+ res['fields'] = map(describe_field, field.fields)
+ return res
+
+def describe_fields_errors(fields, field_names):
+ res = {}
+ if not field_names:
+ field_names = fields.keys()
+ for name in field_names:
+ field = fields[name]
+ res[name] = describe_field_errors(field)
+ return res
+
+def describe_field(field):
+ res = {}
+ field_type = field.__class__.__name__
+ for fname in field_names.get(field_type, []) + \
+ ['help_text', 'label', 'initial', 'required']:
+ res[fname] = getattr(field, fname)
+ if field_type in ['ComboField', 'MultiValueField', 'SplitDateTimeField']:
+ res['fields'] = map(describe_field, field.fields)
+ return res
+
+def describe_fields(fields, field_names):
+ res = {}
+ if not field_names:
+ field_names = fields.keys()
+ for name in field_names:
+ field = fields[name]
+ res[name] = describe_field(field)
+ return res
+
+class FormProcessor(JSONRPCService):
+ def __init__(self, forms, _formcls=None):
+
+ if _formcls is None:
+ JSONRPCService.__init__(self)
+ for k in forms.keys():
+ s = FormProcessor({}, forms[k])
+ self.add_method(k, s.__process)
+ else:
+ JSONRPCService.__init__(self, forms)
+ self.formcls = _formcls
+
+ def __process(self, request, params, command=None):
+
+ f = self.formcls(params)
+
+ if command is None: # just validate
+ if not f.is_valid():
+ return {'success':False, 'errors': builderrors(f)}
+ return {'success':True}
+
+ elif command.has_key('describe_errors'):
+ field_names = command['describe_errors']
+ return describe_fields_errors(f.fields, field_names)
+
+ elif command.has_key('describe'):
+ field_names = command['describe']
+ return describe_fields(f.fields, field_names)
+
+ elif command.has_key('save'):
+ if not f.is_valid():
+ return {'success':False, 'errors': builderrors(f)}
+ instance = f.save() # XXX: if you want more, over-ride save.
+ return {'success': True, 'instance': json_convert(instance) }
+
+ elif command.has_key('html'):
+ return {'success': True, 'html': f.as_table()}
+
+ return "unrecognised command"
+
+
+
+
+# The following is incredibly convenient for saving vast amounts of
+# coding, avoiding doing silly things like this:
+# jsonresult = {'field1': djangoobject.field1,
+# 'field2': djangoobject.date.strftime('%Y.%M'),
+# ..... }
+#
+# The date/time flatten function is there because JSONRPC doesn't
+# support date/time objects or formats, so conversion to a string
+# is the most logical choice. pyjamas, being python, can easily
+# be used to parse the string result at the other end.
+#
+# use as follows:
+#
+# jsonservice = JSONRPCService()
+#
+# @jsonremote(jsonservice)
+# def list_some_model(request, start=0, count=10):
+# l = SomeDjangoModelClass.objects.filter()
+# res = json_convert(l[start:end])
+#
+# @jsonremote(jsonservice)
+# def list_another_model(request, start=0, count=10):
+# l = AnotherDjangoModelClass.objects.filter()
+# res = json_convert(l[start:end])
+#
+# dump jsonservice into urlpatterns to make the two RPC functions,
+# list_some_model and list_another_model part of the django app:
+# (r'^service1/$', 'djangoapp.views.jsonservice'),
+
+from django.core.serializers import serialize
+import datetime
+from datetime import date
+
+def dict_datetimeflatten(item):
+ d = {}
+ for k, v in item.items():
+ k = str(k)
+ if isinstance(v, datetime.date):
+ d[k] = str(v)
+ elif isinstance(v, dict):
+ d[k] = dict_datetimeflatten(v)
+ else:
+ d[k] = v
+ return d
+
+def json_convert(l, fields=None):
+ res = []
+ for item in serialize('python', l, fields=fields):
+ res.append(dict_datetimeflatten(item))
+ return res
+
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/svgui/pyjs/jsonrpc/jsonrpc.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/jsonrpc/jsonrpc.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,43 @@
+import gluon.contrib.simplejson as simplejson
+import types
+import sys
+
+class JSONRPCServiceBase:
+
+ def __init__(self):
+ self.methods={}
+
+ def response(self, id, result):
+ return simplejson.dumps({'version': '1.1', 'id':id,
+ 'result':result, 'error':None})
+ def error(self, id, code, message):
+ return simplejson.dumps({'id': id,
+ 'version': '1.1',
+ 'error': {'name': 'JSONRPCError',
+ 'code': code,
+ 'message': message
+ }
+ })
+
+ def add_method(self, name, method):
+ self.methods[name] = method
+
+ def process(self, data):
+ data = simplejson.loads(data)
+ id, method, params = data["id"], data["method"], data["params"]
+ if method in self.methods:
+ try:
+ result =self.methods[method](*params)
+ return self.response(id, result)
+ except BaseException:
+ etype, eval, etb = sys.exc_info()
+ return self.error(id, 100, '%s: %s' %(etype.__name__, eval))
+ except:
+ etype, eval, etb = sys.exc_info()
+ return self.error(id, 100, 'Exception %s: %s' %(etype, eval))
+ else:
+ return self.error(id, 100, 'method "%s" does not exist' % method)
+
+ def listmethods(self):
+ return self.methods.keys()
+
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/svgui/pyjs/jsonrpc/web2py/jsonrpc.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/jsonrpc/web2py/jsonrpc.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,11 @@
+from pyjs.jsonrpc import JSONRPCServiceBase
+
+class JSONRPCService(JSONRPCServiceBase):
+
+ def serve(self):
+ return self.process(request.body.read())
+
+ def __call__(self,func):
+ self.methods[func.__name__]=func
+ return func
+
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/svgui/pyjs/lib/_pyjs.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/lib/_pyjs.js Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,160 @@
+function pyjs_extend(klass, base) {
+ function klass_object_inherit() {}
+ klass_object_inherit.prototype = base.prototype;
+ klass_object = new klass_object_inherit();
+ for (var i in base.prototype.__class__) {
+ v = base.prototype.__class__[i];
+ if (typeof v == "function" && (v.class_method || v.static_method || v.unbound_method))
+ {
+ klass_object[i] = v;
+ }
+ }
+
+ function klass_inherit() {}
+ klass_inherit.prototype = klass_object;
+ klass.prototype = new klass_inherit();
+ klass_object.constructor = klass;
+ klass.prototype.__class__ = klass_object;
+
+ for (var i in base.prototype) {
+ v = base.prototype[i];
+ if (typeof v == "function" && v.instance_method)
+ {
+ klass.prototype[i] = v;
+ }
+ }
+}
+
+/* creates a class, derived from bases, with methods and variables */
+function pyjs_type(clsname, bases, methods)
+{
+ var fn_cls = function() {};
+ fn_cls.__name__ = clsname;
+ var fn = function() {
+ var instance = new fn_cls();
+ if(instance.__init__) instance.__init__.apply(instance, arguments);
+ return instance;
+ }
+ fn_cls.__initialize__ = function() {
+ if (fn_cls.__was_initialized__) return;
+ fn_cls.__was_initialized__ = true;
+ fn_cls.__extend_baseclasses();
+ fn_cls.prototype.__class__.__new__ = fn;
+ fn_cls.prototype.__class__.__name__ = clsname;
+ }
+ fn_cls.__extend_baseclasses = function() {
+ var bi;
+ for (bi in fn_cls.__baseclasses)
+ {
+ var b = fn_cls.__baseclasses[bi];
+ if (b.__was_initialized__)
+ {
+ continue;
+ }
+ b.__initialize__();
+ }
+ for (bi in fn_cls.__baseclasses)
+ {
+ var b = fn_cls.__baseclasses[bi];
+ pyjs_extend(fn_cls, b);
+ }
+ }
+ if (!bases) {
+ bases = [pyjslib.__Object];
+ }
+ fn_cls.__baseclasses = bases;
+
+ fn_cls.__initialize__();
+
+ for (k in methods) {
+ var mth = methods[k];
+ var mtype = typeof mth;
+ if (mtype == "function" ) {
+ fn_cls.prototype[k] = mth;
+ fn_cls.prototype.__class__[k] = function () {
+ return fn_cls.prototype[k].call.apply(
+ fn_cls.prototype[k], arguments);
+ };
+ fn_cls.prototype.__class__[k].unbound_method = true;
+ fn_cls.prototype.instance_method = true;
+ fn_cls.prototype.__class__[k].__name__ = k;
+ fn_cls.prototype[k].__name__ = k;
+ } else {
+ fn_cls.prototype.__class__[k] = mth;
+ }
+ }
+ return fn;
+}
+function pyjs_kwargs_call(obj, func, star_args, args)
+{
+ var call_args;
+
+ if (star_args)
+ {
+ if (!pyjslib.isIteratable(star_args))
+ {
+ throw (pyjslib.TypeError(func.__name__ + "() arguments after * must be a sequence" + pyjslib.repr(star_args)));
+ }
+ call_args = Array();
+ var __i = star_args.__iter__();
+ var i = 0;
+ try {
+ while (true) {
+ call_args[i]=__i.next();
+ i++;
+ }
+ } catch (e) {
+ if (e != pyjslib.StopIteration) {
+ throw e;
+ }
+ }
+
+ if (args)
+ {
+ var n = star_args.length;
+ for (var i=0; i < args.length; i++) {
+ call_args[n+i]=args[i];
+ }
+ }
+ }
+ else
+ {
+ call_args = args;
+ }
+ return func.apply(obj, call_args);
+}
+
+function pyjs_kwargs_function_call(func, star_args, args)
+{
+ return pyjs_kwargs_call(null, func, star_args, args);
+}
+
+function pyjs_kwargs_method_call(obj, method_name, star_args, args)
+{
+ var method = obj[method_name];
+ if (method.parse_kwargs)
+ {
+ args = method.parse_kwargs.apply(null, args);
+ }
+ return pyjs_kwargs_call(obj, method, star_args, args);
+}
+
+//String.prototype.__getitem__ = String.prototype.charAt;
+//String.prototype.upper = String.prototype.toUpperCase;
+//String.prototype.lower = String.prototype.toLowerCase;
+//String.prototype.find=pyjslib.String_find;
+//String.prototype.join=pyjslib.String_join;
+//String.prototype.isdigit=pyjslib.String_isdigit;
+//String.prototype.__iter__=pyjslib.String___iter__;
+//
+//String.prototype.__replace=String.prototype.replace;
+//String.prototype.replace=pyjslib.String_replace;
+//
+//String.prototype.split=pyjslib.String_split;
+//String.prototype.strip=pyjslib.String_strip;
+//String.prototype.lstrip=pyjslib.String_lstrip;
+//String.prototype.rstrip=pyjslib.String_rstrip;
+//String.prototype.startswith=pyjslib.String_startswith;
+
+var str = String;
+
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/svgui/pyjs/lib/json.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/lib/json.js Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,293 @@
+json_parse = (function () {
+
+// This is a function that can parse a JSON text, producing a JavaScript
+// data structure. It is a simple, recursive descent parser. It does not use
+// eval or regular expressions, so it can be used as a model for implementing
+// a JSON parser in other languages.
+
+// We are defining the function inside of another function to avoid creating
+// global variables.
+
+ var at, // The index of the current character
+ ch, // The current character
+ escapee = {
+ '"': '"',
+ '\\': '\\',
+ '/': '/',
+ b: '\b',
+ f: '\f',
+ n: '\n',
+ r: '\r',
+ t: '\t'
+ },
+ text,
+
+ error = function (m) {
+
+// Call error when something is wrong.
+
+ throw {
+ name: 'SyntaxError',
+ message: m,
+ at: at,
+ text: text
+ };
+ },
+
+ next = function (c) {
+
+// If a c parameter is provided, verify that it matches the current character.
+
+ if (c && c !== ch) {
+ error("Expected '" + c + "' instead of '" + ch + "'");
+ }
+
+// Get the next character. When there are no more characters,
+// return the empty string.
+
+ ch = text.charAt(at);
+ at += 1;
+ return ch;
+ },
+
+ number = function () {
+
+// Parse a number value.
+
+ var number,
+ string = '';
+
+ if (ch === '-') {
+ string = '-';
+ next('-');
+ }
+ while (ch >= '0' && ch <= '9') {
+ string += ch;
+ next();
+ }
+ if (ch === '.') {
+ string += '.';
+ while (next() && ch >= '0' && ch <= '9') {
+ string += ch;
+ }
+ }
+ if (ch === 'e' || ch === 'E') {
+ string += ch;
+ next();
+ if (ch === '-' || ch === '+') {
+ string += ch;
+ next();
+ }
+ while (ch >= '0' && ch <= '9') {
+ string += ch;
+ next();
+ }
+ }
+ number = +string;
+ if (isNaN(number)) {
+ error("Bad number");
+ } else {
+ return number;
+ }
+ },
+
+ string = function () {
+
+// Parse a string value.
+
+ var hex,
+ i,
+ string = '',
+ uffff;
+
+// When parsing for string values, we must look for " and \ characters.
+
+ if (ch === '"') {
+ while (next()) {
+ if (ch === '"') {
+ next();
+ return string;
+ } else if (ch === '\\') {
+ next();
+ if (ch === 'u') {
+ uffff = 0;
+ for (i = 0; i < 4; i += 1) {
+ hex = parseInt(next(), 16);
+ if (!isFinite(hex)) {
+ break;
+ }
+ uffff = uffff * 16 + hex;
+ }
+ string += String.fromCharCode(uffff);
+ } else if (typeof escapee[ch] === 'string') {
+ string += escapee[ch];
+ } else {
+ break;
+ }
+ } else {
+ string += ch;
+ }
+ }
+ }
+ error("Bad string");
+ },
+
+ white = function () {
+
+// Skip whitespace.
+
+ while (ch && ch <= ' ') {
+ next();
+ }
+ },
+
+ word = function () {
+
+// true, false, or null.
+
+ switch (ch) {
+ case 't':
+ next('t');
+ next('r');
+ next('u');
+ next('e');
+ return true;
+ case 'f':
+ next('f');
+ next('a');
+ next('l');
+ next('s');
+ next('e');
+ return false;
+ case 'n':
+ next('n');
+ next('u');
+ next('l');
+ next('l');
+ return null;
+ }
+ error("Unexpected '" + ch + "'");
+ },
+
+ value, // Place holder for the value function.
+
+ array = function () {
+
+// Parse an array value.
+
+ var array = [];
+
+ if (ch === '[') {
+ next('[');
+ white();
+ if (ch === ']') {
+ next(']');
+ return array; // empty array
+ }
+ while (ch) {
+ array.push(value());
+ white();
+ if (ch === ']') {
+ next(']');
+ return array;
+ }
+ next(',');
+ white();
+ }
+ }
+ error("Bad array");
+ },
+
+ object = function () {
+
+// Parse an object value.
+
+ var key,
+ object = {};
+
+ if (ch === '{') {
+ next('{');
+ white();
+ if (ch === '}') {
+ next('}');
+ return object; // empty object
+ }
+ while (ch) {
+ key = string();
+ white();
+ next(':');
+ if (Object.hasOwnProperty.call(object, key)) {
+ error('Duplicate key "' + key + '"');
+ }
+ object[key] = value();
+ white();
+ if (ch === '}') {
+ next('}');
+ return object;
+ }
+ next(',');
+ white();
+ }
+ }
+ error("Bad object");
+ };
+
+ value = function () {
+
+// Parse a JSON value. It could be an object, an array, a string, a number,
+// or a word.
+
+ white();
+ switch (ch) {
+ case '{':
+ return object();
+ case '[':
+ return array();
+ case '"':
+ return string();
+ case '-':
+ return number();
+ default:
+ return ch >= '0' && ch <= '9' ? number() : word();
+ }
+ };
+
+// Return the json_parse function. It will have access to all of the above
+// functions and variables.
+
+ return function (source, reviver) {
+ var result;
+
+ text = source;
+ at = 0;
+ ch = ' ';
+ result = value();
+ white();
+ if (ch) {
+ error("Syntax error");
+ }
+
+// If there is a reviver function, we recursively walk the new structure,
+// passing each name/value pair to the reviver function for possible
+// transformation, starting with a temporary root object that holds the result
+// in an empty key. If there is not a reviver function, we simply return the
+// result.
+
+ return typeof reviver === 'function' ? (function walk(holder, key) {
+ var k, v, value = holder[key];
+ if (value && typeof value === 'object') {
+ for (k in value) {
+ if (Object.hasOwnProperty.call(value, k)) {
+ v = walk(value, k);
+ if (v !== undefined) {
+ value[k] = v;
+ } else {
+ delete value[k];
+ }
+ }
+ }
+ }
+ return reviver.call(holder, key, value);
+ }({'': result}, '')) : result;
+ };
+}());
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/svgui/pyjs/lib/pyjslib.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/lib/pyjslib.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1365 @@
+# Copyright 2006 James Tauber and contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+# iteration from Bob Ippolito's Iteration in JavaScript
+
+from __pyjamas__ import JS
+
+# must declare import _before_ importing sys
+
+def import_module(path, parent_module, module_name, dynamic=1, async=False):
+ """
+ """
+
+ JS("""
+ var cache_file;
+
+ if (module_name == "sys" || module_name == 'pyjslib')
+ {
+ /*module_load_request[module_name] = 1;*/
+ return;
+ }
+
+ if (path == null)
+ {
+ path = './';
+ }
+
+ var override_name = sys.platform + "." + module_name;
+ if (((sys.overrides != null) &&
+ (sys.overrides.has_key(override_name))))
+ {
+ cache_file = sys.overrides.__getitem__(override_name) ;
+ }
+ else
+ {
+ cache_file = module_name ;
+ }
+
+ cache_file = (path + cache_file + '.cache.js' ) ;
+
+ //alert("cache " + cache_file + " " + module_name + " " + parent_module);
+
+ /* already loaded? */
+ if (module_load_request[module_name])
+ {
+ if (module_load_request[module_name] >= 3 && parent_module != null)
+ {
+ //onload_fn = parent_module + '.' + module_name + ' = ' + module_name + ';';
+ //pyjs_eval(onload_fn); /* set up the parent-module namespace */
+ }
+ return;
+ }
+ if (typeof (module_load_request[module_name]) == 'undefined')
+ {
+ module_load_request[module_name] = 1;
+ }
+
+ /* following a load, this first executes the script
+ * "preparation" function MODULENAME_loaded_fn()
+ * and then sets up the loaded module in the namespace
+ * of the parent.
+ */
+
+ onload_fn = ''; // module_name + "_loaded_fn();"
+
+ if (parent_module != null)
+ {
+ //onload_fn += parent_module + '.' + module_name + ' = ' + module_name + ';';
+ /*pmod = parent_module + '.' + module_name;
+ onload_fn += 'alert("' + pmod + '"+' + pmod+');';*/
+ }
+
+
+ if (dynamic)
+ {
+ /* this one tacks the script onto the end of the DOM
+ */
+
+ pyjs_load_script(cache_file, onload_fn, async);
+
+ /* this one actually RUNS the script (eval) into the page.
+ my feeling is that this would be better for non-async
+ but i can't get it to work entirely yet.
+ */
+ /*pyjs_ajax_eval(cache_file, onload_fn, async);*/
+ }
+ else
+ {
+ if (module_name != "pyjslib" &&
+ module_name != "sys")
+ pyjs_eval(onload_fn);
+ }
+
+ """)
+
+JS("""
+function import_wait(proceed_fn, parent_mod, dynamic) {
+
+ var data = '';
+ var element = $doc.createElement("div");
+ $doc.body.appendChild(element);
+ function write_dom(txt) {
+ element.innerHTML = txt + '
';
+ }
+
+ var timeoutperiod = 1;
+ if (dynamic)
+ var timeoutperiod = 1;
+
+ var wait = function() {
+
+ var status = '';
+ for (l in module_load_request)
+ {
+ var m = module_load_request[l];
+ if (l == "sys" || l == 'pyjslib')
+ continue;
+ status += l + m + " ";
+ }
+
+ //write_dom( " import wait " + wait_count + " " + status + " parent_mod " + parent_mod);
+ wait_count += 1;
+
+ if (status == '')
+ {
+ setTimeout(wait, timeoutperiod);
+ return;
+ }
+
+ for (l in module_load_request)
+ {
+ var m = module_load_request[l];
+ if (l == "sys" || l == 'pyjslib')
+ {
+ module_load_request[l] = 4;
+ continue;
+ }
+ if ((parent_mod != null) && (l == parent_mod))
+ {
+ if (m == 1)
+ {
+ setTimeout(wait, timeoutperiod);
+ return;
+ }
+ if (m == 2)
+ {
+ /* cheat and move app on to next stage */
+ module_load_request[l] = 3;
+ }
+ }
+ if (m == 1 || m == 2)
+ {
+ setTimeout(wait, timeoutperiod);
+ return;
+ }
+ if (m == 3)
+ {
+ //alert("waited for module " + l + ": loaded");
+ module_load_request[l] = 4;
+ mod_fn = modules[l];
+ }
+ }
+ //alert("module wait done");
+
+ if (proceed_fn.importDone)
+ proceed_fn.importDone(proceed_fn);
+ else
+ proceed_fn();
+ }
+
+ wait();
+}
+""")
+
+class Object:
+ pass
+
+object = Object
+
+class Modload:
+
+ def __init__(self, path, app_modlist, app_imported_fn, dynamic,
+ parent_mod):
+ self.app_modlist = app_modlist
+ self.app_imported_fn = app_imported_fn
+ self.path = path
+ self.idx = 0;
+ self.dynamic = dynamic
+ self.parent_mod = parent_mod
+
+ def next(self):
+
+ for i in range(len(self.app_modlist[self.idx])):
+ app = self.app_modlist[self.idx][i]
+ import_module(self.path, self.parent_mod, app, self.dynamic, True);
+ self.idx += 1
+
+ if self.idx >= len(self.app_modlist):
+ import_wait(self.app_imported_fn, self.parent_mod, self.dynamic)
+ else:
+ import_wait(getattr(self, "next"), self.parent_mod, self.dynamic)
+
+def get_module(module_name):
+ ev = "__mod = %s;" % module_name
+ JS("pyjs_eval(ev);")
+ return __mod
+
+def preload_app_modules(path, app_modnames, app_imported_fn, dynamic,
+ parent_mod=None):
+
+ loader = Modload(path, app_modnames, app_imported_fn, dynamic, parent_mod)
+ loader.next()
+
+import sys
+
+class BaseException:
+
+ name = "BaseException"
+
+ def __init__(self, *args):
+ self.args = args
+
+ def __str__(self):
+ if len(self.args) is 0:
+ return ''
+ elif len(self.args) is 1:
+ return repr(self.args[0])
+ return repr(self.args)
+
+ def toString(self):
+ return str(self)
+
+class Exception(BaseException):
+
+ name = "Exception"
+
+class TypeError(BaseException):
+ name = "TypeError"
+
+class StandardError(Exception):
+ name = "StandardError"
+
+class LookupError(StandardError):
+ name = "LookupError"
+
+ def toString(self):
+ return self.name + ": " + self.args[0]
+
+class KeyError(LookupError):
+ name = "KeyError"
+
+class AttributeError(StandardError):
+
+ name = "AttributeError"
+
+ def toString(self):
+ return "AttributeError: %s of %s" % (self.args[1], self.args[0])
+
+JS("""
+pyjslib.StopIteration = function () { };
+pyjslib.StopIteration.prototype = new Error();
+pyjslib.StopIteration.name = 'StopIteration';
+pyjslib.StopIteration.message = 'StopIteration';
+
+pyjslib.String_find = function(sub, start, end) {
+ var pos=this.indexOf(sub, start);
+ if (pyjslib.isUndefined(end)) return pos;
+
+ if (pos + sub.length>end) return -1;
+ return pos;
+}
+
+pyjslib.String_join = function(data) {
+ var text="";
+
+ if (pyjslib.isArray(data)) {
+ return data.join(this);
+ }
+ else if (pyjslib.isIteratable(data)) {
+ var iter=data.__iter__();
+ try {
+ text+=iter.next();
+ while (true) {
+ var item=iter.next();
+ text+=this + item;
+ }
+ }
+ catch (e) {
+ if (e != pyjslib.StopIteration) throw e;
+ }
+ }
+
+ return text;
+}
+
+pyjslib.String_isdigit = function() {
+ return (this.match(/^\d+$/g) != null);
+}
+
+pyjslib.String_replace = function(old, replace, count) {
+ var do_max=false;
+ var start=0;
+ var new_str="";
+ var pos=0;
+
+ if (!pyjslib.isString(old)) return this.__replace(old, replace);
+ if (!pyjslib.isUndefined(count)) do_max=true;
+
+ while (start= s.length) {
+ throw pyjslib.StopIteration;
+ }
+ return s.substring(i++, i, 1);
+ },
+ '__iter__': function() {
+ return this;
+ }
+ };
+}
+
+pyjslib.String_strip = function(chars) {
+ return this.lstrip(chars).rstrip(chars);
+}
+
+pyjslib.String_lstrip = function(chars) {
+ if (pyjslib.isUndefined(chars)) return this.replace(/^\s+/, "");
+
+ return this.replace(new RegExp("^[" + chars + "]+"), "");
+}
+
+pyjslib.String_rstrip = function(chars) {
+ if (pyjslib.isUndefined(chars)) return this.replace(/\s+$/, "");
+
+ return this.replace(new RegExp("[" + chars + "]+$"), "");
+}
+
+pyjslib.String_startswith = function(prefix, start) {
+ if (pyjslib.isUndefined(start)) start = 0;
+
+ if (this.substring(start, prefix.length) == prefix) return true;
+ return false;
+}
+
+pyjslib.abs = Math.abs;
+
+""")
+
+class Class:
+ def __init__(self, name):
+ self.name = name
+
+ def __str___(self):
+ return self.name
+
+def eq(a,b):
+ JS("""
+ if (pyjslib.hasattr(a, "__cmp__")) {
+ return a.__cmp__(b) == 0;
+ } else if (pyjslib.hasattr(b, "__cmp__")) {
+ return b.__cmp__(a) == 0;
+ }
+ return a == b;
+ """)
+
+def cmp(a,b):
+ if hasattr(a, "__cmp__"):
+ return a.__cmp__(b)
+ elif hasattr(b, "__cmp__"):
+ return -b.__cmp__(a)
+ if a > b:
+ return 1
+ elif b > a:
+ return -1
+ else:
+ return 0
+
+def bool(v):
+ # this needs to stay in native code without any dependencies here,
+ # because this is used by if and while, we need to prevent
+ # recursion
+ JS("""
+ if (!v) return false;
+ switch(typeof v){
+ case 'boolean':
+ return v;
+ case 'object':
+ if (v.__nonzero__){
+ return v.__nonzero__();
+ }else if (v.__len__){
+ return v.__len__()>0;
+ }
+ return true;
+ }
+ return Boolean(v);
+ """)
+
+class List:
+ def __init__(self, data=None):
+ JS("""
+ this.l = [];
+ this.extend(data);
+ """)
+
+ def append(self, item):
+ JS(""" this.l[this.l.length] = item;""")
+
+ def extend(self, data):
+ JS("""
+ if (pyjslib.isArray(data)) {
+ n = this.l.length;
+ for (var i=0; i < data.length; i++) {
+ this.l[n+i]=data[i];
+ }
+ }
+ else if (pyjslib.isIteratable(data)) {
+ var iter=data.__iter__();
+ var i=this.l.length;
+ try {
+ while (true) {
+ var item=iter.next();
+ this.l[i++]=item;
+ }
+ }
+ catch (e) {
+ if (e != pyjslib.StopIteration) throw e;
+ }
+ }
+ """)
+
+ def remove(self, value):
+ JS("""
+ var index=this.index(value);
+ if (index<0) return false;
+ this.l.splice(index, 1);
+ return true;
+ """)
+
+ def index(self, value, start=0):
+ JS("""
+ var length=this.l.length;
+ for (var i=start; i= 0
+
+ def __iter__(self):
+ JS("""
+ var i = 0;
+ var l = this.l;
+ return {
+ 'next': function() {
+ if (i >= l.length) {
+ throw pyjslib.StopIteration;
+ }
+ return l[i++];
+ },
+ '__iter__': function() {
+ return this;
+ }
+ };
+ """)
+
+ def reverse(self):
+ JS(""" this.l.reverse();""")
+
+ def sort(self, compareFunc=None, keyFunc=None, reverse=False):
+ if not compareFunc:
+ global cmp
+ compareFunc = cmp
+ if keyFunc and reverse:
+ def thisSort1(a,b):
+ return -compareFunc(keyFunc(a), keyFunc(b))
+ self.l.sort(thisSort1)
+ elif keyFunc:
+ def thisSort2(a,b):
+ return compareFunc(keyFunc(a), keyFunc(b))
+ self.l.sort(thisSort2)
+ elif reverse:
+ def thisSort3(a,b):
+ return -compareFunc(a, b)
+ self.l.sort(thisSort3)
+ else:
+ self.l.sort(compareFunc)
+
+ def getArray(self):
+ """
+ Access the javascript Array that is used internally by this list
+ """
+ return self.l
+
+ def __str__(self):
+ return repr(self)
+
+list = List
+
+class Tuple:
+ def __init__(self, data=None):
+ JS("""
+ this.l = [];
+ this.extend(data);
+ """)
+
+ def append(self, item):
+ JS(""" this.l[this.l.length] = item;""")
+
+ def extend(self, data):
+ JS("""
+ if (pyjslib.isArray(data)) {
+ n = this.l.length;
+ for (var i=0; i < data.length; i++) {
+ this.l[n+i]=data[i];
+ }
+ }
+ else if (pyjslib.isIteratable(data)) {
+ var iter=data.__iter__();
+ var i=this.l.length;
+ try {
+ while (true) {
+ var item=iter.next();
+ this.l[i++]=item;
+ }
+ }
+ catch (e) {
+ if (e != pyjslib.StopIteration) throw e;
+ }
+ }
+ """)
+
+ def remove(self, value):
+ JS("""
+ var index=this.index(value);
+ if (index<0) return false;
+ this.l.splice(index, 1);
+ return true;
+ """)
+
+ def index(self, value, start=0):
+ JS("""
+ var length=this.l.length;
+ for (var i=start; i= 0
+
+ def __iter__(self):
+ JS("""
+ var i = 0;
+ var l = this.l;
+ return {
+ 'next': function() {
+ if (i >= l.length) {
+ throw pyjslib.StopIteration;
+ }
+ return l[i++];
+ },
+ '__iter__': function() {
+ return this;
+ }
+ };
+ """)
+
+ def reverse(self):
+ JS(""" this.l.reverse();""")
+
+ def sort(self, compareFunc=None, keyFunc=None, reverse=False):
+ if not compareFunc:
+ global cmp
+ compareFunc = cmp
+ if keyFunc and reverse:
+ def thisSort1(a,b):
+ return -compareFunc(keyFunc(a), keyFunc(b))
+ self.l.sort(thisSort1)
+ elif keyFunc:
+ def thisSort2(a,b):
+ return compareFunc(keyFunc(a), keyFunc(b))
+ self.l.sort(thisSort2)
+ elif reverse:
+ def thisSort3(a,b):
+ return -compareFunc(a, b)
+ self.l.sort(thisSort3)
+ else:
+ self.l.sort(compareFunc)
+
+ def getArray(self):
+ """
+ Access the javascript Array that is used internally by this list
+ """
+ return self.l
+
+ def __str__(self):
+ return repr(self)
+
+tuple = Tuple
+
+
+class Dict:
+ def __init__(self, data=None):
+ JS("""
+ this.d = {};
+
+ if (pyjslib.isArray(data)) {
+ for (var i in data) {
+ var item=data[i];
+ this.__setitem__(item[0], item[1]);
+ //var sKey=pyjslib.hash(item[0]);
+ //this.d[sKey]=item[1];
+ }
+ }
+ else if (pyjslib.isIteratable(data)) {
+ var iter=data.__iter__();
+ try {
+ while (true) {
+ var item=iter.next();
+ this.__setitem__(item.__getitem__(0), item.__getitem__(1));
+ }
+ }
+ catch (e) {
+ if (e != pyjslib.StopIteration) throw e;
+ }
+ }
+ else if (pyjslib.isObject(data)) {
+ for (var key in data) {
+ this.__setitem__(key, data[key]);
+ }
+ }
+ """)
+
+ def __setitem__(self, key, value):
+ JS("""
+ var sKey = pyjslib.hash(key);
+ this.d[sKey]=[key, value];
+ """)
+
+ def __getitem__(self, key):
+ JS("""
+ var sKey = pyjslib.hash(key);
+ var value=this.d[sKey];
+ if (pyjslib.isUndefined(value)){
+ throw pyjslib.KeyError(key);
+ }
+ return value[1];
+ """)
+
+ def __nonzero__(self):
+ JS("""
+ for (var i in this.d){
+ return true;
+ }
+ return false;
+ """)
+
+ def __len__(self):
+ JS("""
+ var size=0;
+ for (var i in this.d) size++;
+ return size;
+ """)
+
+ def has_key(self, key):
+ return self.__contains__(key)
+
+ def __delitem__(self, key):
+ JS("""
+ var sKey = pyjslib.hash(key);
+ delete this.d[sKey];
+ """)
+
+ def __contains__(self, key):
+ JS("""
+ var sKey = pyjslib.hash(key);
+ return (pyjslib.isUndefined(this.d[sKey])) ? false : true;
+ """)
+
+ def keys(self):
+ JS("""
+ var keys=new pyjslib.List();
+ for (var key in this.d) {
+ keys.append(this.d[key][0]);
+ }
+ return keys;
+ """)
+
+ def values(self):
+ JS("""
+ var values=new pyjslib.List();
+ for (var key in this.d) values.append(this.d[key][1]);
+ return values;
+ """)
+
+ def items(self):
+ JS("""
+ var items = new pyjslib.List();
+ for (var key in this.d) {
+ var kv = this.d[key];
+ items.append(new pyjslib.List(kv))
+ }
+ return items;
+ """)
+
+ def __iter__(self):
+ return self.keys().__iter__()
+
+ def iterkeys(self):
+ return self.__iter__()
+
+ def itervalues(self):
+ return self.values().__iter__();
+
+ def iteritems(self):
+ return self.items().__iter__();
+
+ def setdefault(self, key, default_value):
+ if not self.has_key(key):
+ self[key] = default_value
+
+ def get(self, key, default_=None):
+ if not self.has_key(key):
+ return default_
+ return self[key]
+
+ def update(self, d):
+ for k,v in d.iteritems():
+ self[k] = v
+
+ def getObject(self):
+ """
+ Return the javascript Object which this class uses to store
+ dictionary keys and values
+ """
+ return self.d
+
+ def copy(self):
+ return Dict(self.items())
+
+ def __str__(self):
+ return repr(self)
+
+dict = Dict
+
+# taken from mochikit: range( [start,] stop[, step] )
+def range():
+ JS("""
+ var start = 0;
+ var stop = 0;
+ var step = 1;
+
+ if (arguments.length == 2) {
+ start = arguments[0];
+ stop = arguments[1];
+ }
+ else if (arguments.length == 3) {
+ start = arguments[0];
+ stop = arguments[1];
+ step = arguments[2];
+ }
+ else if (arguments.length>0) stop = arguments[0];
+
+ return {
+ 'next': function() {
+ if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) throw pyjslib.StopIteration;
+ var rval = start;
+ start += step;
+ return rval;
+ },
+ '__iter__': function() {
+ return this;
+ }
+ }
+ """)
+
+def slice(object, lower, upper):
+ JS("""
+ if (pyjslib.isString(object)) {
+ if (lower < 0) {
+ lower = object.length + lower;
+ }
+ if (upper < 0) {
+ upper = object.length + upper;
+ }
+ if (pyjslib.isNull(upper)) upper=object.length;
+ return object.substring(lower, upper);
+ }
+ if (pyjslib.isObject(object) && object.slice)
+ return object.slice(lower, upper);
+
+ return null;
+ """)
+
+def str(text):
+ JS("""
+ if (pyjslib.hasattr(text,"__str__")) {
+ return text.__str__();
+ }
+ return String(text);
+ """)
+
+def ord(x):
+ if(isString(x) and len(x) is 1):
+ JS("""
+ return x.charCodeAt(0);
+ """)
+ else:
+ JS("""
+ throw pyjslib.TypeError();
+ """)
+ return None
+
+def chr(x):
+ JS("""
+ return String.fromCharCode(x)
+ """)
+
+def is_basetype(x):
+ JS("""
+ var t = typeof(x);
+ return t == 'boolean' ||
+ t == 'function' ||
+ t == 'number' ||
+ t == 'string' ||
+ t == 'undefined'
+ ;
+ """)
+
+def get_pyjs_classtype(x):
+ JS("""
+ if (pyjslib.hasattr(x, "__class__"))
+ if (pyjslib.hasattr(x.__class__, "__new__"))
+ var src = x.__class__.__name__;
+ return src;
+ return null;
+ """)
+
+def repr(x):
+ """ Return the string representation of 'x'.
+ """
+ JS("""
+ if (x === null)
+ return "null";
+
+ if (x === undefined)
+ return "undefined";
+
+ var t = typeof(x);
+
+ //alert("repr typeof " + t + " : " + x);
+
+ if (t == "boolean")
+ return x.toString();
+
+ if (t == "function")
+ return "";
+
+ if (t == "number")
+ return x.toString();
+
+ if (t == "string") {
+ if (x.indexOf("'") == -1)
+ return "'" + x + "'";
+ if (x.indexOf('"') == -1)
+ return '"' + x + '"';
+ var s = x.replace(new RegExp('"', "g"), '\\\\"');
+ return '"' + s + '"';
+ };
+
+ if (t == "undefined")
+ return "undefined";
+
+ // If we get here, x is an object. See if it's a Pyjamas class.
+
+ if (!pyjslib.hasattr(x, "__init__"))
+ return "<" + x.toString() + ">";
+
+ // Handle the common Pyjamas data types.
+
+ var constructor = "UNKNOWN";
+
+ constructor = pyjslib.get_pyjs_classtype(x);
+
+ //alert("repr constructor: " + constructor);
+
+ if (constructor == "Tuple") {
+ var contents = x.getArray();
+ var s = "(";
+ for (var i=0; i < contents.length; i++) {
+ s += pyjslib.repr(contents[i]);
+ if (i < contents.length - 1)
+ s += ", ";
+ };
+ s += ")"
+ return s;
+ };
+
+ if (constructor == "List") {
+ var contents = x.getArray();
+ var s = "[";
+ for (var i=0; i < contents.length; i++) {
+ s += pyjslib.repr(contents[i]);
+ if (i < contents.length - 1)
+ s += ", ";
+ };
+ s += "]"
+ return s;
+ };
+
+ if (constructor == "Dict") {
+ var keys = new Array();
+ for (var key in x.d)
+ keys.push(key);
+
+ var s = "{";
+ for (var i=0; i return the class name.
+ // Note that we replace underscores with dots so that the name will
+ // (hopefully!) look like the original Python name.
+
+ //var s = constructor.replace(new RegExp('_', "g"), '.');
+ return "<" + constructor + " object>";
+ """)
+
+def float(text):
+ JS("""
+ return parseFloat(text);
+ """)
+
+def int(text, radix=0):
+ JS("""
+ return parseInt(text, radix);
+ """)
+
+def len(object):
+ JS("""
+ if (object==null) return 0;
+ if (pyjslib.isObject(object) && object.__len__) return object.__len__();
+ return object.length;
+ """)
+
+def isinstance(object_, classinfo):
+ if pyjslib.isUndefined(object_):
+ return False
+ if not pyjslib.isObject(object_):
+
+ return False
+ if _isinstance(classinfo, Tuple):
+ for ci in classinfo:
+ if isinstance(object_, ci):
+ return True
+ return False
+ else:
+ return _isinstance(object_, classinfo)
+
+def _isinstance(object_, classinfo):
+ if not pyjslib.isObject(object_):
+ return False
+ JS("""
+ if (object_.__class__){
+ var res = object_ instanceof classinfo.constructor;
+ return res;
+ }
+ return false;
+ """)
+
+def getattr(obj, name, default_):
+ JS("""
+ if ((!pyjslib.isObject(obj))||(pyjslib.isUndefined(obj[name]))){
+ if (pyjslib.isUndefined(default_)){
+ throw pyjslib.AttributeError(obj, name);
+ }else{
+ return default_;
+ }
+ }
+ if (!pyjslib.isFunction(obj[name])) return obj[name];
+ var fnwrap = function() {
+ var args = [];
+ for (var i = 0; i < arguments.length; i++) {
+ args.push(arguments[i]);
+ }
+ return obj[name].apply(obj,args);
+ }
+ fnwrap.__name__ = name;
+ return fnwrap;
+ """)
+
+def setattr(obj, name, value):
+ JS("""
+ if (!pyjslib.isObject(obj)) return null;
+
+ obj[name] = value;
+
+ """)
+
+def hasattr(obj, name):
+ JS("""
+ if (!pyjslib.isObject(obj)) return false;
+ if (pyjslib.isUndefined(obj[name])) return false;
+
+ return true;
+ """)
+
+def dir(obj):
+ JS("""
+ var properties=new pyjslib.List();
+ for (property in obj) properties.append(property);
+ return properties;
+ """)
+
+def filter(obj, method, sequence=None):
+ # object context is LOST when a method is passed, hence object must be passed separately
+ # to emulate python behaviour, should generate this code inline rather than as a function call
+ items = []
+ if sequence is None:
+ sequence = method
+ method = obj
+
+ for item in sequence:
+ if method(item):
+ items.append(item)
+ else:
+ for item in sequence:
+ if method.call(obj, item):
+ items.append(item)
+
+ return items
+
+
+def map(obj, method, sequence=None):
+ items = []
+
+ if sequence is None:
+ sequence = method
+ method = obj
+
+ for item in sequence:
+ items.append(method(item))
+ else:
+ for item in sequence:
+ items.append(method.call(obj, item))
+
+ return items
+
+
+def enumerate(sequence):
+ enumeration = []
+ nextIndex = 0
+ for item in sequence:
+ enumeration.append([nextIndex, item])
+ nextIndex = nextIndex + 1
+ return enumeration
+
+
+def min(*sequence):
+ minValue = None
+ for item in sequence:
+ if minValue is None:
+ minValue = item
+ elif item < minValue:
+ minValue = item
+ return minValue
+
+
+def max(*sequence):
+ maxValue = None
+ for item in sequence:
+ if maxValue is None:
+ maxValue = item
+ elif item > maxValue:
+ maxValue = item
+ return maxValue
+
+
+next_hash_id = 0
+
+def hash(obj):
+ JS("""
+ if (obj == null) return null;
+
+ if (obj.$H) return obj.$H;
+ if (obj.__hash__) return obj.__hash__();
+ if (obj.constructor == String || obj.constructor == Number || obj.constructor == Date) return obj;
+
+ obj.$H = ++pyjslib.next_hash_id;
+ return obj.$H;
+ """)
+
+
+# type functions from Douglas Crockford's Remedial Javascript: http://www.crockford.com/javascript/remedial.html
+def isObject(a):
+ JS("""
+ return (a != null && (typeof a == 'object')) || pyjslib.isFunction(a);
+ """)
+
+def isFunction(a):
+ JS("""
+ return typeof a == 'function';
+ """)
+
+def isString(a):
+ JS("""
+ return typeof a == 'string';
+ """)
+
+def isNull(a):
+ JS("""
+ return typeof a == 'object' && !a;
+ """)
+
+def isArray(a):
+ JS("""
+ return pyjslib.isObject(a) && a.constructor == Array;
+ """)
+
+def isUndefined(a):
+ JS("""
+ return typeof a == 'undefined';
+ """)
+
+def isIteratable(a):
+ JS("""
+ return pyjslib.isString(a) || (pyjslib.isObject(a) && a.__iter__);
+ """)
+
+def isNumber(a):
+ JS("""
+ return typeof a == 'number' && isFinite(a);
+ """)
+
+def toJSObjects(x):
+ """
+ Convert the pyjs pythonic List and Dict objects into javascript Object and Array
+ objects, recursively.
+ """
+ if isArray(x):
+ JS("""
+ var result = [];
+ for(var k=0; k < x.length; k++) {
+ var v = x[k];
+ var tv = pyjslib.toJSObjects(v);
+ result.push(tv);
+ }
+ return result;
+ """)
+ if isObject(x):
+ if isinstance(x, Dict):
+ JS("""
+ var o = x.getObject();
+ var result = {};
+ for (var i in o) {
+ result[o[i][0].toString()] = o[i][1];
+ }
+ return pyjslib.toJSObjects(result)
+ """)
+ elif isinstance(x, List):
+ return toJSObjects(x.l)
+ elif hasattr(x, '__class__'):
+ # we do not have a special implementation for custom
+ # classes, just pass it on
+ return x
+ if isObject(x):
+ JS("""
+ var result = {};
+ for(var k in x) {
+ var v = x[k];
+ var tv = pyjslib.toJSObjects(v)
+ result[k] = tv;
+ }
+ return result;
+ """)
+ return x
+
+def printFunc(objs):
+ JS("""
+ if ($wnd.console==undefined) return;
+ var s = "";
+ for(var i=0; i < objs.length; i++) {
+ if(s != "") s += " ";
+ s += objs[i];
+ }
+ console.debug(s)
+ """)
+
+def type(clsname, bases=None, methods=None):
+ """ creates a class, derived from bases, with methods and variables
+ """
+
+ JS(" var mths = {}; ")
+ if methods:
+ for k in methods.keys():
+ mth = methods[k]
+ JS(" mths[k] = mth; ")
+
+ JS(" var bss = null; ")
+ if bases:
+ JS("bss = bases.l;")
+ JS(" return pyjs_type(clsname, bss, mths); ")
+
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/svgui/pyjs/lib/sys.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/lib/sys.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,59 @@
+# the platform name (PyV8, smjs, Mozilla, IE6, Opera, Safari etc.)
+platform = '' # to be updated by app, on compile
+
+# a dictionary of module override names (platform-specific)
+overrides = None # to be updated by app, on compile
+
+# the remote path for loading modules
+loadpath = None
+
+stacktrace = None
+
+appname = None
+
+def setloadpath(lp):
+ global loadpath
+ loadpath = lp
+
+def setappname(an):
+ global appname
+ appname = an
+
+def getloadpath():
+ global loadpath
+ return loadpath
+
+def addoverride(module_name, path):
+ global overrides
+ overrides[module_name] = path
+
+def addstack(linedebug):
+ JS("""
+ if (pyjslib.bool((sys.stacktrace === null))) {
+ sys.stacktrace = new pyjslib.List([]);
+ }
+ sys.stacktrace.append(linedebug);
+ """)
+def popstack():
+ JS("""
+ sys.stacktrace.pop()
+ """)
+
+def printstack():
+ JS("""
+ var res = '';
+
+ var __l = sys.stacktrace.__iter__();
+ try {
+ while (true) {
+ var l = __l.next();
+ res += ( l + '\\n' ) ;
+ }
+ } catch (e) {
+ if (e != pyjslib.StopIteration) {
+ throw e;
+ }
+ }
+
+ return res;
+ """)
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/svgui/pyjs/pyjs.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/pyjs.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1777 @@
+#!/usr/bin/env python
+# Copyright 2006 James Tauber and contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+import sys
+from types import StringType
+import compiler
+from compiler import ast
+import os
+import copy
+
+# the standard location for builtins (e.g. pyjslib) can be
+# over-ridden by changing this. it defaults to sys.prefix
+# so that on a system-wide install of pyjamas the builtins
+# can be found in e.g. {sys.prefix}/share/pyjamas
+#
+# over-rides can be done by either explicitly modifying
+# pyjs.prefix or by setting an environment variable, PYJSPREFIX.
+
+prefix = sys.prefix
+
+if os.environ.has_key('PYJSPREFIX'):
+ prefix = os.environ['PYJSPREFIX']
+
+# pyjs.path is the list of paths, just like sys.path, from which
+# library modules will be searched for, for compile purposes.
+# obviously we don't want to use sys.path because that would result
+# in compiling standard python modules into javascript!
+
+path = [os.path.abspath('')]
+
+if os.environ.has_key('PYJSPATH'):
+ for p in os.environ['PYJSPATH'].split(os.pathsep):
+ p = os.path.abspath(p)
+ if os.path.isdir(p):
+ path.append(p)
+
+# this is the python function used to wrap native javascript
+NATIVE_JS_FUNC_NAME = "JS"
+
+UU = ""
+
+PYJSLIB_BUILTIN_FUNCTIONS=("cmp",
+ "map",
+ "filter",
+ "dir",
+ "getattr",
+ "setattr",
+ "hasattr",
+ "int",
+ "float",
+ "str",
+ "repr",
+ "range",
+ "len",
+ "hash",
+ "abs",
+ "ord",
+ "chr",
+ "enumerate",
+ "min",
+ "max",
+ "bool",
+ "type",
+ "isinstance")
+
+PYJSLIB_BUILTIN_CLASSES=("BaseException",
+ "Exception",
+ "StandardError",
+ "StopIteration",
+ "AttributeError",
+ "TypeError",
+ "KeyError",
+ "LookupError",
+ "list",
+ "dict",
+ "object",
+ "tuple",
+ )
+
+def pyjs_builtin_remap(name):
+ # XXX HACK!
+ if name == 'list':
+ name = 'List'
+ if name == 'object':
+ name = '__Object'
+ if name == 'dict':
+ name = 'Dict'
+ if name == 'tuple':
+ name = 'Tuple'
+ return name
+
+# XXX: this is a hack: these should be dealt with another way
+# however, console is currently the only global name which is causing
+# problems.
+PYJS_GLOBAL_VARS=("console")
+
+# This is taken from the django project.
+# Escape every ASCII character with a value less than 32.
+JS_ESCAPES = (
+ ('\\', r'\x5C'),
+ ('\'', r'\x27'),
+ ('"', r'\x22'),
+ ('>', r'\x3E'),
+ ('<', r'\x3C'),
+ ('&', r'\x26'),
+ (';', r'\x3B')
+ ) + tuple([('%c' % z, '\\x%02X' % z) for z in range(32)])
+
+def escapejs(value):
+ """Hex encodes characters for use in JavaScript strings."""
+ for bad, good in JS_ESCAPES:
+ value = value.replace(bad, good)
+ return value
+
+def uuprefix(name, leave_alone=0):
+ name = name.split(".")
+ name = name[:leave_alone] + map(lambda x: "__%s" % x, name[leave_alone:])
+ return '.'.join(name)
+
+class Klass:
+
+ klasses = {}
+
+ def __init__(self, name, name_):
+ self.name = name
+ self.name_ = name_
+ self.klasses[name] = self
+ self.functions = set()
+
+ def set_base(self, base_name):
+ self.base = self.klasses.get(base_name)
+
+ def add_function(self, function_name):
+ self.functions.add(function_name)
+
+
+class TranslationError(Exception):
+ def __init__(self, message, node):
+ self.message = "line %s:\n%s\n%s" % (node.lineno, message, node)
+
+ def __str__(self):
+ return self.message
+
+def strip_py(name):
+ return name
+
+def mod_var_name_decl(raw_module_name):
+ """ function to get the last component of the module e.g.
+ pyjamas.ui.DOM into the "namespace". i.e. doing
+ "import pyjamas.ui.DOM" actually ends up with _two_
+ variables - one pyjamas.ui.DOM, the other just "DOM".
+ but "DOM" is actually local, hence the "var" prefix.
+
+ for PyV8, this might end up causing problems - we'll have
+ to see: gen_mod_import and mod_var_name_decl might have
+ to end up in a library-specific module, somewhere.
+ """
+ name = raw_module_name.split(".")
+ if len(name) == 1:
+ return ''
+ child_name = name[-1]
+ return "var %s = %s;\n" % (child_name, raw_module_name)
+
+def gen_mod_import(parentName, importName, dynamic=1):
+ #pyjs_ajax_eval("%(n)s.cache.js", null, true);
+ return """
+ pyjslib.import_module(sys.loadpath, '%(p)s', '%(n)s', %(d)d, false);
+ """ % ({'p': parentName, 'd': dynamic, 'n': importName}) + \
+ mod_var_name_decl(importName)
+
+class Translator:
+
+ def __init__(self, mn, module_name, raw_module_name, src, debug, mod, output,
+ dynamic=0, optimize=False,
+ findFile=None):
+
+ if module_name:
+ self.module_prefix = module_name + "."
+ else:
+ self.module_prefix = ""
+ self.raw_module_name = raw_module_name
+ src = src.replace("\r\n", "\n")
+ src = src.replace("\n\r", "\n")
+ src = src.replace("\r", "\n")
+ self.src = src.split("\n")
+ self.debug = debug
+ self.imported_modules = []
+ self.imported_modules_as = []
+ self.imported_js = set()
+ self.top_level_functions = set()
+ self.top_level_classes = set()
+ self.top_level_vars = set()
+ self.local_arg_stack = [[]]
+ self.output = output
+ self.imported_classes = {}
+ self.method_imported_globals = set()
+ self.method_self = None
+ self.nextTupleAssignID = 1
+ self.dynamic = dynamic
+ self.optimize = optimize
+ self.findFile = findFile
+
+ if module_name.find(".") >= 0:
+ vdec = ''
+ else:
+ vdec = 'var '
+ print >>self.output, UU+"%s%s = function (__mod_name__) {" % (vdec, module_name)
+
+ print >>self.output, " if("+module_name+".__was_initialized__) return;"
+ print >>self.output, " "+UU+module_name+".__was_initialized__ = true;"
+ print >>self.output, UU+"if (__mod_name__ == null) __mod_name__ = '%s';" % (mn)
+ print >>self.output, UU+"%s.__name__ = __mod_name__;" % (raw_module_name)
+
+ decl = mod_var_name_decl(raw_module_name)
+ if decl:
+ print >>self.output, decl
+
+
+ if self.debug:
+ haltException = self.module_prefix + "HaltException"
+ print >>self.output, haltException + ' = function () {'
+ print >>self.output, ' this.message = "Program Halted";'
+ print >>self.output, ' this.name = "' + haltException + '";'
+ print >>self.output, '}'
+ print >>self.output, ''
+ print >>self.output, haltException + ".prototype.__str__ = function()"
+ print >>self.output, '{'
+ print >>self.output, 'return this.message ;'
+ print >>self.output, '}'
+
+ print >>self.output, haltException + ".prototype.toString = function()"
+ print >>self.output, '{'
+ print >>self.output, 'return this.name + ": \\"" + this.message + "\\"";'
+ print >>self.output, '}'
+
+ isHaltFunction = self.module_prefix + "IsHaltException"
+ print >>self.output, """
+ %s = function (s) {
+ var suffix="HaltException";
+ if (s.length < suffix.length) {
+ //alert(s + " " + suffix);
+ return false;
+ } else {
+ var ss = s.substring(s.length, (s.length - suffix.length));
+ //alert(s + " " + suffix + " " + ss);
+ return ss == suffix;
+ }
+ }
+ """ % isHaltFunction
+ for child in mod.node:
+ if isinstance(child, ast.Function):
+ self.top_level_functions.add(child.name)
+ elif isinstance(child, ast.Class):
+ self.top_level_classes.add(child.name)
+
+ for child in mod.node:
+ if isinstance(child, ast.Function):
+ self._function(child, False)
+ elif isinstance(child, ast.Class):
+ self._class(child)
+ elif isinstance(child, ast.Import):
+ importName = child.names[0][0]
+ if importName == '__pyjamas__': # special module to help make pyjamas modules loadable in the python interpreter
+ pass
+ elif importName.endswith('.js'):
+ self.imported_js.add(importName)
+ else:
+ self.add_imported_module(strip_py(importName))
+ elif isinstance(child, ast.From):
+ if child.modname == '__pyjamas__': # special module to help make pyjamas modules loadable in the python interpreter
+ pass
+ else:
+ self.add_imported_module(child.modname)
+ self._from(child)
+ elif isinstance(child, ast.Discard):
+ self._discard(child, None)
+ elif isinstance(child, ast.Assign):
+ self._assign(child, None, True)
+ elif isinstance(child, ast.AugAssign):
+ self._augassign(child, None)
+ elif isinstance(child, ast.If):
+ self._if(child, None)
+ elif isinstance(child, ast.For):
+ self._for(child, None)
+ elif isinstance(child, ast.While):
+ self._while(child, None)
+ elif isinstance(child, ast.Subscript):
+ self._subscript_stmt(child, None)
+ elif isinstance(child, ast.Global):
+ self._global(child, None)
+ elif isinstance(child, ast.Printnl):
+ self._print(child, None)
+ elif isinstance(child, ast.Print):
+ self._print(child, None)
+ elif isinstance(child, ast.TryExcept):
+ self._tryExcept(child, None)
+ elif isinstance(child, ast.Raise):
+ self._raise(child, None)
+ elif isinstance(child, ast.Stmt):
+ self._stmt(child, None)
+ else:
+ raise TranslationError("unsupported type (in __init__)", child)
+
+ # Initialize all classes for this module
+ #print >> self.output, "__"+self.modpfx()+\
+ # "classes_initialize = function() {\n"
+ #for className in self.top_level_classes:
+ # print >> self.output, "\t"+UU+self.modpfx()+"__"+className+"_initialize();"
+ #print >> self.output, "};\n"
+
+ print >> self.output, "return this;\n"
+ print >> self.output, "}; /* end %s */ \n" % module_name
+
+ def module_imports(self):
+ return self.imported_modules + self.imported_modules_as
+
+ def add_local_arg(self, varname):
+ local_vars = self.local_arg_stack[-1]
+ if varname not in local_vars:
+ local_vars.append(varname)
+
+ def add_imported_module(self, importName):
+
+ if importName in self.imported_modules:
+ return
+ self.imported_modules.append(importName)
+ name = importName.split(".")
+ if len(name) != 1:
+ # add the name of the module to the namespace,
+ # but don't add the short name to imported_modules
+ # because then the short name would be attempted to be
+ # added to the dependencies, and it's half way up the
+ # module import directory structure!
+ child_name = name[-1]
+ self.imported_modules_as.append(child_name)
+ print >> self.output, gen_mod_import(self.raw_module_name,
+ strip_py(importName),
+ self.dynamic)
+
+ def _default_args_handler(self, node, arg_names, current_klass,
+ output=None):
+ if len(node.defaults):
+ output = output or self.output
+ default_pos = len(arg_names) - len(node.defaults)
+ if arg_names and arg_names[0] == self.method_self:
+ default_pos -= 1
+ for default_node in node.defaults:
+ if isinstance(default_node, ast.Const):
+ default_value = self._const(default_node)
+ elif isinstance(default_node, ast.Name):
+ default_value = self._name(default_node, current_klass)
+ elif isinstance(default_node, ast.UnarySub):
+ default_value = self._unarysub(default_node, current_klass)
+ else:
+ raise TranslationError("unsupported type (in _method)", default_node)
+
+ default_name = arg_names[default_pos]
+ default_pos += 1
+ print >> output, " if (typeof %s == 'undefined') %s=%s;" % (default_name, default_name, default_value)
+
+ def _varargs_handler(self, node, varargname, arg_names, current_klass):
+ print >>self.output, " var", varargname, '= new pyjslib.Tuple();'
+ print >>self.output, " for(var __va_arg="+str(len(arg_names))+"; __va_arg < arguments.length; __va_arg++) {"
+ print >>self.output, " var __arg = arguments[__va_arg];"
+ print >>self.output, " "+varargname+".append(__arg);"
+ print >>self.output, " }"
+
+ def _kwargs_parser(self, node, function_name, arg_names, current_klass):
+ if len(node.defaults) or node.kwargs:
+ default_pos = len(arg_names) - len(node.defaults)
+ if arg_names and arg_names[0] == self.method_self:
+ default_pos -= 1
+ print >>self.output, function_name+'.parse_kwargs = function (', ", ".join(["__kwargs"]+arg_names), ") {"
+ for default_node in node.defaults:
+ default_value = self.expr(default_node, current_klass)
+# if isinstance(default_node, ast.Const):
+# default_value = self._const(default_node)
+# elif isinstance(default_node, ast.Name):
+# default_value = self._name(default_node)
+# elif isinstance(default_node, ast.UnarySub):
+# default_value = self._unarysub(default_node, current_klass)
+# else:
+# raise TranslationError("unsupported type (in _method)", default_node)
+
+ default_name = arg_names[default_pos]
+ print >>self.output, " if (typeof %s == 'undefined')"%(default_name)
+ print >>self.output, " %s=__kwargs.%s;"% (default_name, default_name)
+ default_pos += 1
+
+ #self._default_args_handler(node, arg_names, current_klass)
+ if node.kwargs: arg_names += ["pyjslib.Dict(__kwargs)"]
+ print >>self.output, " var __r = "+"".join(["[", ", ".join(arg_names), "]"])+";"
+ if node.varargs:
+ self._varargs_handler(node, "__args", arg_names, current_klass)
+ print >>self.output, " __r.push.apply(__r, __args.getArray())"
+ print >>self.output, " return __r;"
+ print >>self.output, "};"
+
+ def _function(self, node, local=False):
+ if local:
+ function_name = node.name
+ self.add_local_arg(function_name)
+ else:
+ function_name = UU + self.modpfx() + node.name
+
+ arg_names = list(node.argnames)
+ normal_arg_names = list(arg_names)
+ if node.kwargs: kwargname = normal_arg_names.pop()
+ if node.varargs: varargname = normal_arg_names.pop()
+ declared_arg_names = list(normal_arg_names)
+ if node.kwargs: declared_arg_names.append(kwargname)
+
+ function_args = "(" + ", ".join(declared_arg_names) + ")"
+ print >>self.output, "%s = function%s {" % (function_name, function_args)
+ self._default_args_handler(node, normal_arg_names, None)
+
+ local_arg_names = normal_arg_names + declared_arg_names
+
+ if node.varargs:
+ self._varargs_handler(node, varargname, declared_arg_names, None)
+ local_arg_names.append(varargname)
+
+ # stack of local variable names for this function call
+ self.local_arg_stack.append(local_arg_names)
+
+ for child in node.code:
+ self._stmt(child, None)
+
+ # remove the top local arg names
+ self.local_arg_stack.pop()
+
+ # we need to return null always, so it is not undefined
+ lastStmt = [p for p in node.code][-1]
+ if not isinstance(lastStmt, ast.Return):
+ if not self._isNativeFunc(lastStmt):
+ print >>self.output, " return null;"
+
+ print >>self.output, "};"
+ print >>self.output, "%s.__name__ = '%s';\n" % (function_name, node.name)
+
+
+ self._kwargs_parser(node, function_name, normal_arg_names, None)
+
+
+ def _return(self, node, current_klass):
+ expr = self.expr(node.value, current_klass)
+ # in python a function call always returns None, so we do it
+ # here too
+ print >>self.output, " return " + expr + ";"
+
+
+ def _break(self, node, current_klass):
+ print >>self.output, " break;"
+
+
+ def _continue(self, node, current_klass):
+ print >>self.output, " continue;"
+
+
+ def _callfunc(self, v, current_klass):
+
+ if isinstance(v.node, ast.Name):
+ if v.node.name in self.top_level_functions:
+ call_name = self.modpfx() + v.node.name
+ elif v.node.name in self.top_level_classes:
+ call_name = self.modpfx() + v.node.name
+ elif self.imported_classes.has_key(v.node.name):
+ call_name = self.imported_classes[v.node.name] + '.' + v.node.name
+ elif v.node.name in PYJSLIB_BUILTIN_FUNCTIONS:
+ call_name = 'pyjslib.' + v.node.name
+ elif v.node.name in PYJSLIB_BUILTIN_CLASSES:
+ name = pyjs_builtin_remap(v.node.name)
+ call_name = 'pyjslib.' + name
+ elif v.node.name == "callable":
+ call_name = "pyjslib.isFunction"
+ else:
+ call_name = v.node.name
+ call_args = []
+ elif isinstance(v.node, ast.Getattr):
+ attr_name = v.node.attrname
+
+ if isinstance(v.node.expr, ast.Name):
+ call_name = self._name2(v.node.expr, current_klass, attr_name)
+ call_args = []
+ elif isinstance(v.node.expr, ast.Getattr):
+ call_name = self._getattr2(v.node.expr, current_klass, attr_name)
+ call_args = []
+ elif isinstance(v.node.expr, ast.CallFunc):
+ call_name = self._callfunc(v.node.expr, current_klass) + "." + v.node.attrname
+ call_args = []
+ elif isinstance(v.node.expr, ast.Subscript):
+ call_name = self._subscript(v.node.expr, current_klass) + "." + v.node.attrname
+ call_args = []
+ elif isinstance(v.node.expr, ast.Const):
+ call_name = self.expr(v.node.expr, current_klass) + "." + v.node.attrname
+ call_args = []
+ else:
+ raise TranslationError("unsupported type (in _callfunc)", v.node.expr)
+ else:
+ raise TranslationError("unsupported type (in _callfunc)", v.node)
+
+ call_name = strip_py(call_name)
+
+ kwargs = []
+ star_arg_name = None
+ if v.star_args:
+ star_arg_name = self.expr(v.star_args, current_klass)
+
+ for ch4 in v.args:
+ if isinstance(ch4, ast.Keyword):
+ kwarg = ch4.name + ":" + self.expr(ch4.expr, current_klass)
+ kwargs.append(kwarg)
+ else:
+ arg = self.expr(ch4, current_klass)
+ call_args.append(arg)
+
+ if kwargs:
+ fn_args = ", ".join(['{' + ', '.join(kwargs) + '}']+call_args)
+ else:
+ fn_args = ", ".join(call_args)
+
+ if kwargs or star_arg_name:
+ if not star_arg_name:
+ star_arg_name = 'null'
+ try: call_this, method_name = call_name.rsplit(".", 1)
+ except ValueError:
+ # Must be a function call ...
+ return ("pyjs_kwargs_function_call("+call_name+", "
+ + star_arg_name
+ + ", ["+fn_args+"]"
+ + ")" )
+ else:
+ return ("pyjs_kwargs_method_call("+call_this+", '"+method_name+"', "
+ + star_arg_name
+ + ", ["+fn_args+"]"
+ + ")")
+ else:
+ return call_name + "(" + ", ".join(call_args) + ")"
+
+ def _print(self, node, current_klass):
+ if self.optimize:
+ return
+ call_args = []
+ for ch4 in node.nodes:
+ arg = self.expr(ch4, current_klass)
+ call_args.append(arg)
+
+ print >>self.output, "pyjslib.printFunc([", ', '.join(call_args), "],", int(isinstance(node, ast.Printnl)), ");"
+
+ def _tryExcept(self, node, current_klass):
+ if len(node.handlers) != 1:
+ raise TranslationError("except statements in this form are" +
+ " not supported", node)
+
+ expr = node.handlers[0][0]
+ as_ = node.handlers[0][1]
+ if as_:
+ errName = as_.name
+ else:
+ errName = 'err'
+
+ # XXX TODO: check that this should instead be added as a _separate_
+ # local scope, temporary to the function. oh dearie me.
+ self.add_local_arg(errName)
+
+ print >>self.output, " try {"
+ for stmt in node.body.nodes:
+ self._stmt(stmt, current_klass)
+ print >> self.output, " } catch(%s) {" % errName
+ if expr:
+ l = []
+ if isinstance(expr, ast.Tuple):
+ for x in expr.nodes:
+ l.append("(%(err)s.__name__ == %(expr)s.__name__)" % dict (err=errName, expr=self.expr(x, current_klass)))
+ else:
+ l = [ " (%(err)s.__name__ == %(expr)s.__name__) " % dict (err=errName, expr=self.expr(expr, current_klass)) ]
+ print >> self.output, " if(%s) {" % '||\n\t\t'.join(l)
+ for stmt in node.handlers[0][2]:
+ self._stmt(stmt, current_klass)
+ if expr:
+ #print >> self.output, "} else { throw(%s); } " % errName
+ print >> self.output, "}"
+ if node.else_ != None:
+ print >>self.output, " } finally {"
+ for stmt in node.else_:
+ self._stmt(stmt, current_klass)
+ print >>self.output, " }"
+
+ # XXX: change use_getattr to True to enable "strict" compilation
+ # but incurring a 100% performance penalty. oops.
+ def _getattr(self, v, current_klass, use_getattr=False):
+ attr_name = v.attrname
+ if isinstance(v.expr, ast.Name):
+ obj = self._name(v.expr, current_klass, return_none_for_module=True)
+ if obj == None and v.expr.name in self.module_imports():
+ # XXX TODO: distinguish between module import classes
+ # and variables. right now, this is a hack to get
+ # the sys module working.
+ #if v.expr.name == 'sys':
+ return v.expr.name+'.'+attr_name
+ #return v.expr.name+'.__'+attr_name+'.prototype.__class__'
+ if not use_getattr or attr_name == '__class__' or \
+ attr_name == '__name__':
+ return obj + "." + attr_name
+ return "pyjslib.getattr(%s, '%s')" % (obj, attr_name)
+ elif isinstance(v.expr, ast.Getattr):
+ return self._getattr(v.expr, current_klass) + "." + attr_name
+ elif isinstance(v.expr, ast.Subscript):
+ return self._subscript(v.expr, self.modpfx()) + "." + attr_name
+ elif isinstance(v.expr, ast.CallFunc):
+ return self._callfunc(v.expr, self.modpfx()) + "." + attr_name
+ else:
+ raise TranslationError("unsupported type (in _getattr)", v.expr)
+
+
+ def modpfx(self):
+ return strip_py(self.module_prefix)
+
+ def _name(self, v, current_klass, top_level=False,
+ return_none_for_module=False):
+
+ if v.name == 'ilikesillynamesfornicedebugcode':
+ print top_level, current_klass, repr(v)
+ print self.top_level_vars
+ print self.top_level_functions
+ print self.local_arg_stack
+ print "error..."
+
+ local_var_names = None
+ las = len(self.local_arg_stack)
+ if las > 0:
+ local_var_names = self.local_arg_stack[-1]
+
+ if v.name == "True":
+ return "true"
+ elif v.name == "False":
+ return "false"
+ elif v.name == "None":
+ return "null"
+ elif v.name == '__name__' and current_klass is None:
+ return self.modpfx() + v.name
+ elif v.name == self.method_self:
+ return "this"
+ elif v.name in self.top_level_functions:
+ return UU+self.modpfx() + v.name
+ elif v.name in self.method_imported_globals:
+ return UU+self.modpfx() + v.name
+ elif not current_klass and las == 1 and v.name in self.top_level_vars:
+ return UU+self.modpfx() + v.name
+ elif v.name in local_var_names:
+ return v.name
+ elif self.imported_classes.has_key(v.name):
+ return UU+self.imported_classes[v.name] + '.__' + v.name + ".prototype.__class__"
+ elif v.name in self.top_level_classes:
+ return UU+self.modpfx() + "__" + v.name + ".prototype.__class__"
+ elif v.name in self.module_imports() and return_none_for_module:
+ return None
+ elif v.name in PYJSLIB_BUILTIN_CLASSES:
+ return "pyjslib." + pyjs_builtin_remap( v.name )
+ elif current_klass:
+ if v.name not in local_var_names and \
+ v.name not in self.top_level_vars and \
+ v.name not in PYJS_GLOBAL_VARS and \
+ v.name not in self.top_level_functions:
+
+ cls_name = current_klass
+ if hasattr(cls_name, "name"):
+ cls_name_ = cls_name.name_
+ cls_name = cls_name.name
+ else:
+ cls_name_ = current_klass + "_" # XXX ???
+ name = UU+cls_name_ + ".prototype.__class__." \
+ + v.name
+ if v.name == 'listener':
+ name = 'listener+' + name
+ return name
+
+ return v.name
+
+ def _name2(self, v, current_klass, attr_name):
+ obj = v.name
+
+ if obj in self.method_imported_globals:
+ call_name = UU+self.modpfx() + obj + "." + attr_name
+ elif self.imported_classes.has_key(obj):
+ #attr_str = ""
+ #if attr_name != "__init__":
+ attr_str = ".prototype.__class__." + attr_name
+ call_name = UU+self.imported_classes[obj] + '.__' + obj + attr_str
+ elif obj in self.module_imports():
+ call_name = obj + "." + attr_name
+ elif obj[0] == obj[0].upper(): # XXX HACK ALERT
+ call_name = UU + self.modpfx() + "__" + obj + ".prototype.__class__." + attr_name
+ else:
+ call_name = UU+self._name(v, current_klass) + "." + attr_name
+
+ return call_name
+
+
+ def _getattr2(self, v, current_klass, attr_name):
+ if isinstance(v.expr, ast.Getattr):
+ call_name = self._getattr2(v.expr, current_klass, v.attrname + "." + attr_name)
+ elif isinstance(v.expr, ast.Name) and v.expr.name in self.module_imports():
+ call_name = UU+v.expr.name + '.__' +v.attrname+".prototype.__class__."+attr_name
+ else:
+ obj = self.expr(v.expr, current_klass)
+ call_name = obj + "." + v.attrname + "." + attr_name
+
+ return call_name
+
+
+ def _class(self, node):
+ """
+ Handle a class definition.
+
+ In order to translate python semantics reasonably well, the following
+ structure is used:
+
+ A special object is created for the class, which inherits attributes
+ from the superclass, or Object if there's no superclass. This is the
+ class object; the object which you refer to when specifying the
+ class by name. Static, class, and unbound methods are copied
+ from the superclass object.
+
+ A special constructor function is created with the same name as the
+ class, which is used to create instances of that class.
+
+ A javascript class (e.g. a function with a prototype attribute) is
+ created which is the javascript class of created instances, and
+ which inherits attributes from the class object. Bound methods are
+ copied from the superclass into this class rather than inherited,
+ because the class object contains unbound, class, and static methods
+ that we don't necessarily want to inherit.
+
+ The type of a method can now be determined by inspecting its
+ static_method, unbound_method, class_method, or instance_method
+ attribute; only one of these should be true.
+
+ Much of this work is done in pyjs_extend, is pyjslib.py
+ """
+ class_name = self.modpfx() + uuprefix(node.name, 1)
+ class_name_ = self.modpfx() + uuprefix(node.name)
+ current_klass = Klass(class_name, class_name_)
+ init_method = None
+ for child in node.code:
+ if isinstance(child, ast.Function):
+ current_klass.add_function(child.name)
+ if child.name == "__init__":
+ init_method = child
+
+
+ if len(node.bases) == 0:
+ base_class = "pyjslib.__Object"
+ elif len(node.bases) == 1:
+ if isinstance(node.bases[0], ast.Name):
+ if self.imported_classes.has_key(node.bases[0].name):
+ base_class_ = self.imported_classes[node.bases[0].name] + '.__' + node.bases[0].name
+ base_class = self.imported_classes[node.bases[0].name] + '.' + node.bases[0].name
+ else:
+ base_class_ = self.modpfx() + "__" + node.bases[0].name
+ base_class = self.modpfx() + node.bases[0].name
+ elif isinstance(node.bases[0], ast.Getattr):
+ # the bases are not in scope of the class so do not
+ # pass our class to self._name
+ base_class_ = self._name(node.bases[0].expr, None) + \
+ ".__" + node.bases[0].attrname
+ base_class = self._name(node.bases[0].expr, None) + \
+ "." + node.bases[0].attrname
+ else:
+ raise TranslationError("unsupported type (in _class)", node.bases[0])
+
+ current_klass.set_base(base_class)
+ else:
+ raise TranslationError("more than one base (in _class)", node)
+
+ print >>self.output, UU+class_name_ + " = function () {"
+ # call superconstructor
+ #if base_class:
+ # print >>self.output, " __" + base_class + ".call(this);"
+ print >>self.output, "}"
+
+ if not init_method:
+ init_method = ast.Function([], "__init__", ["self"], [], 0, None, [])
+ #self._method(init_method, current_klass, class_name)
+
+ # Generate a function which constructs the object
+ clsfunc = ast.Function([],
+ node.name,
+ init_method.argnames[1:],
+ init_method.defaults,
+ init_method.flags,
+ None,
+ [ast.Discard(ast.CallFunc(ast.Name("JS"), [ast.Const(
+# I attempted lazy initialization, but then you can't access static class members
+# " if(!__"+base_class+".__was_initialized__)"+
+# " __" + class_name + "_initialize();\n" +
+ " var instance = new " + UU + class_name_ + "();\n" +
+ " if(instance.__init__) instance.__init__.apply(instance, arguments);\n" +
+ " return instance;"
+ )]))])
+
+ self._function(clsfunc, False)
+ print >>self.output, UU+class_name_ + ".__initialize__ = function () {"
+ print >>self.output, " if("+UU+class_name_+".__was_initialized__) return;"
+ print >>self.output, " "+UU+class_name_+".__was_initialized__ = true;"
+ cls_obj = UU+class_name_ + '.prototype.__class__'
+
+ if class_name == "pyjslib.__Object":
+ print >>self.output, " "+cls_obj+" = {};"
+ else:
+ if base_class and base_class not in ("object", "pyjslib.__Object"):
+ print >>self.output, " if(!"+UU+base_class_+".__was_initialized__)"
+ print >>self.output, " "+UU+base_class_+".__initialize__();"
+ print >>self.output, " pyjs_extend(" + UU+class_name_ + ", "+UU+base_class_+");"
+ else:
+ print >>self.output, " pyjs_extend(" + UU+class_name_ + ", "+UU+"pyjslib.__Object);"
+
+ print >>self.output, " "+cls_obj+".__new__ = "+UU+class_name+";"
+ print >>self.output, " "+cls_obj+".__name__ = '"+UU+node.name+"';"
+
+ for child in node.code:
+ if isinstance(child, ast.Pass):
+ pass
+ elif isinstance(child, ast.Function):
+ self._method(child, current_klass, class_name, class_name_)
+ elif isinstance(child, ast.Assign):
+ self.classattr(child, current_klass)
+ elif isinstance(child, ast.Discard) and isinstance(child.expr, ast.Const):
+ # Probably a docstring, turf it
+ pass
+ else:
+ raise TranslationError("unsupported type (in _class)", child)
+ print >>self.output, "}"
+
+ print >> self.output, class_name_+".__initialize__();"
+
+
+ def classattr(self, node, current_klass):
+ self._assign(node, current_klass, True)
+
+ def _raise(self, node, current_klass):
+ if node.expr2:
+ raise TranslationError("More than one expression unsupported",
+ node)
+ print >> self.output, "throw (%s);" % self.expr(
+ node.expr1, current_klass)
+
+ def _method(self, node, current_klass, class_name, class_name_):
+ # reset global var scope
+ self.method_imported_globals = set()
+
+ arg_names = list(node.argnames)
+
+ classmethod = False
+ staticmethod = False
+ if node.decorators:
+ for d in node.decorators:
+ if d.name == "classmethod":
+ classmethod = True
+ elif d.name == "staticmethod":
+ staticmethod = True
+
+ if staticmethod:
+ staticfunc = ast.Function([], class_name_+"."+node.name, node.argnames, node.defaults, node.flags, node.doc, node.code, node.lineno)
+ self._function(staticfunc, True)
+ print >>self.output, " " + UU+class_name_ + ".prototype.__class__." + node.name + " = " + class_name_+"."+node.name+";";
+ print >>self.output, " " + UU+class_name_ + ".prototype.__class__." + node.name + ".static_method = true;";
+ return
+ else:
+ if len(arg_names) == 0:
+ raise TranslationError("methods must take an argument 'self' (in _method)", node)
+ self.method_self = arg_names[0]
+
+ #if not classmethod and arg_names[0] != "self":
+ # raise TranslationError("first arg not 'self' (in _method)", node)
+
+ normal_arg_names = arg_names[1:]
+ if node.kwargs: kwargname = normal_arg_names.pop()
+ if node.varargs: varargname = normal_arg_names.pop()
+ declared_arg_names = list(normal_arg_names)
+ if node.kwargs: declared_arg_names.append(kwargname)
+
+ function_args = "(" + ", ".join(declared_arg_names) + ")"
+
+ if classmethod:
+ fexpr = UU + class_name_ + ".prototype.__class__." + node.name
+ else:
+ fexpr = UU + class_name_ + ".prototype." + node.name
+ print >>self.output, " "+fexpr + " = function" + function_args + " {"
+
+ # default arguments
+ self._default_args_handler(node, normal_arg_names, current_klass)
+
+ local_arg_names = normal_arg_names + declared_arg_names
+
+ if node.varargs:
+ self._varargs_handler(node, varargname, declared_arg_names, current_klass)
+ local_arg_names.append(varargname)
+
+
+ # stack of local variable names for this function call
+ self.local_arg_stack.append(local_arg_names)
+
+ for child in node.code:
+ self._stmt(child, current_klass)
+
+ # remove the top local arg names
+ self.local_arg_stack.pop()
+
+ print >>self.output, " };"
+
+ self._kwargs_parser(node, fexpr, normal_arg_names, current_klass)
+
+ if classmethod:
+ # Have to create a version on the instances which automatically passes the
+ # class as "self"
+ altexpr = UU + class_name_ + ".prototype." + node.name
+ print >>self.output, " "+altexpr + " = function() {"
+ print >>self.output, " return " + fexpr + ".apply(this.__class__, arguments);"
+ print >>self.output, " };"
+ print >>self.output, " "+fexpr+".class_method = true;"
+ print >>self.output, " "+altexpr+".instance_method = true;"
+ else:
+ # For instance methods, we need an unbound version in the class object
+ altexpr = UU + class_name_ + ".prototype.__class__." + node.name
+ print >>self.output, " "+altexpr + " = function() {"
+ print >>self.output, " return " + fexpr + ".call.apply("+fexpr+", arguments);"
+ print >>self.output, " };"
+ print >>self.output, " "+altexpr+".unbound_method = true;"
+ print >>self.output, " "+fexpr+".instance_method = true;"
+ print >>self.output, " "+altexpr+".__name__ = '%s';" % node.name
+
+ print >>self.output, UU + class_name_ + ".prototype.%s.__name__ = '%s';" % \
+ (node.name, node.name)
+
+ if node.kwargs or len(node.defaults):
+ print >>self.output, " "+altexpr + ".parse_kwargs = " + fexpr + ".parse_kwargs;"
+
+ self.method_self = None
+ self.method_imported_globals = set()
+
+ def _isNativeFunc(self, node):
+ if isinstance(node, ast.Discard):
+ if isinstance(node.expr, ast.CallFunc):
+ if isinstance(node.expr.node, ast.Name) and \
+ node.expr.node.name == NATIVE_JS_FUNC_NAME:
+ return True
+ return False
+
+ def _stmt(self, node, current_klass):
+ debugStmt = self.debug and not self._isNativeFunc(node)
+ if debugStmt:
+ print >>self.output, ' try {'
+
+ if isinstance(node, ast.Return):
+ self._return(node, current_klass)
+ elif isinstance(node, ast.Break):
+ self._break(node, current_klass)
+ elif isinstance(node, ast.Continue):
+ self._continue(node, current_klass)
+ elif isinstance(node, ast.Assign):
+ self._assign(node, current_klass)
+ elif isinstance(node, ast.AugAssign):
+ self._augassign(node, current_klass)
+ elif isinstance(node, ast.Discard):
+ self._discard(node, current_klass)
+ elif isinstance(node, ast.If):
+ self._if(node, current_klass)
+ elif isinstance(node, ast.For):
+ self._for(node, current_klass)
+ elif isinstance(node, ast.While):
+ self._while(node, current_klass)
+ elif isinstance(node, ast.Subscript):
+ self._subscript_stmt(node, current_klass)
+ elif isinstance(node, ast.Global):
+ self._global(node, current_klass)
+ elif isinstance(node, ast.Pass):
+ pass
+ elif isinstance(node, ast.Function):
+ self._function(node, True)
+ elif isinstance(node, ast.Printnl):
+ self._print(node, current_klass)
+ elif isinstance(node, ast.Print):
+ self._print(node, current_klass)
+ elif isinstance(node, ast.TryExcept):
+ self._tryExcept(node, current_klass)
+ elif isinstance(node, ast.Raise):
+ self._raise(node, current_klass)
+ else:
+ raise TranslationError("unsupported type (in _stmt)", node)
+
+ if debugStmt:
+
+ lt = self.get_line_trace(node)
+
+ haltException = self.module_prefix + "HaltException"
+ isHaltFunction = self.module_prefix + "IsHaltException"
+
+ print >>self.output, ' } catch (__err) {'
+ print >>self.output, ' if (' + isHaltFunction + '(__err.name)) {'
+ print >>self.output, ' throw __err;'
+ print >>self.output, ' } else {'
+ print >>self.output, " st = sys.printstack() + "\
+ + '"%s"' % lt + "+ '\\n' ;"
+ print >>self.output, ' alert("' + "Error in " \
+ + lt + '"' \
+ + '+"\\n"+__err.name+": "+__err.message'\
+ + '+"\\n\\nStack trace:\\n"' \
+ + '+st' \
+ + ');'
+ print >>self.output, ' debugger;'
+
+ print >>self.output, ' throw new ' + self.module_prefix + "HaltException();"
+ print >>self.output, ' }'
+ print >>self.output, ' }'
+
+
+ def get_line_trace(self, node):
+ lineNum = "Unknown"
+ srcLine = ""
+ if hasattr(node, "lineno"):
+ if node.lineno != None:
+ lineNum = node.lineno
+ srcLine = self.src[min(lineNum, len(self.src))-1]
+ srcLine = srcLine.replace('\\', '\\\\')
+ srcLine = srcLine.replace('"', '\\"')
+ srcLine = srcLine.replace("'", "\\'")
+
+ return self.raw_module_name + ".py, line " \
+ + str(lineNum) + ":"\
+ + "\\n" \
+ + " " + srcLine
+
+ def _augassign(self, node, current_klass):
+ v = node.node
+ if isinstance(v, ast.Getattr):
+ # XXX HACK! don't allow += on return result of getattr.
+ # TODO: create a temporary variable or something.
+ lhs = self._getattr(v, current_klass, False)
+ else:
+ lhs = self._name(node.node, current_klass)
+ op = node.op
+ rhs = self.expr(node.expr, current_klass)
+ print >>self.output, " " + lhs + " " + op + " " + rhs + ";"
+
+
+ def _assign(self, node, current_klass, top_level = False):
+ if len(node.nodes) != 1:
+ tempvar = '__temp'+str(node.lineno)
+ tnode = ast.Assign([ast.AssName(tempvar, "OP_ASSIGN", node.lineno)], node.expr, node.lineno)
+ self._assign(tnode, current_klass, top_level)
+ for v in node.nodes:
+ tnode2 = ast.Assign([v], ast.Name(tempvar, node.lineno), node.lineno)
+ self._assign(tnode2, current_klass, top_level)
+ return
+
+ local_var_names = None
+ if len(self.local_arg_stack) > 0:
+ local_var_names = self.local_arg_stack[-1]
+
+ def _lhsFromAttr(v, current_klass):
+ attr_name = v.attrname
+ if isinstance(v.expr, ast.Name):
+ obj = v.expr.name
+ lhs = self._name(v.expr, current_klass) + "." + attr_name
+ elif isinstance(v.expr, ast.Getattr):
+ lhs = self._getattr(v, current_klass)
+ elif isinstance(v.expr, ast.Subscript):
+ lhs = self._subscript(v.expr, current_klass) + "." + attr_name
+ else:
+ raise TranslationError("unsupported type (in _assign)", v.expr)
+ return lhs
+
+ def _lhsFromName(v, top_level, current_klass):
+ if top_level:
+ if current_klass:
+ lhs = UU+current_klass.name_ + ".prototype.__class__." \
+ + v.name
+ else:
+ self.top_level_vars.add(v.name)
+ vname = self.modpfx() + v.name
+ if not self.modpfx() and v.name not in\
+ self.method_imported_globals:
+ lhs = "var " + vname
+ else:
+ lhs = UU + vname
+ self.add_local_arg(v.name)
+ else:
+ if v.name in local_var_names:
+ lhs = v.name
+ elif v.name in self.method_imported_globals:
+ lhs = self.modpfx() + v.name
+ else:
+ lhs = "var " + v.name
+ self.add_local_arg(v.name)
+ return lhs
+
+ dbg = 0
+ v = node.nodes[0]
+ if isinstance(v, ast.AssAttr):
+ lhs = _lhsFromAttr(v, current_klass)
+ if v.flags == "OP_ASSIGN":
+ op = "="
+ else:
+ raise TranslationError("unsupported flag (in _assign)", v)
+
+ elif isinstance(v, ast.AssName):
+ lhs = _lhsFromName(v, top_level, current_klass)
+ if v.flags == "OP_ASSIGN":
+ op = "="
+ else:
+ raise TranslationError("unsupported flag (in _assign)", v)
+ elif isinstance(v, ast.Subscript):
+ if v.flags == "OP_ASSIGN":
+ obj = self.expr(v.expr, current_klass)
+ if len(v.subs) != 1:
+ raise TranslationError("must have one sub (in _assign)", v)
+ idx = self.expr(v.subs[0], current_klass)
+ value = self.expr(node.expr, current_klass)
+ print >>self.output, " " + obj + ".__setitem__(" + idx + ", " + value + ");"
+ return
+ else:
+ raise TranslationError("unsupported flag (in _assign)", v)
+ elif isinstance(v, (ast.AssList, ast.AssTuple)):
+ uniqueID = self.nextTupleAssignID
+ self.nextTupleAssignID += 1
+ tempName = "__tupleassign" + str(uniqueID) + "__"
+ print >>self.output, " var " + tempName + " = " + \
+ self.expr(node.expr, current_klass) + ";"
+ for index,child in enumerate(v.getChildNodes()):
+ rhs = tempName + ".__getitem__(" + str(index) + ")"
+
+ if isinstance(child, ast.AssAttr):
+ lhs = _lhsFromAttr(child, current_klass)
+ elif isinstance(child, ast.AssName):
+ lhs = _lhsFromName(child, top_level, current_klass)
+ elif isinstance(child, ast.Subscript):
+ if child.flags == "OP_ASSIGN":
+ obj = self.expr(child.expr, current_klass)
+ if len(child.subs) != 1:
+ raise TranslationError("must have one sub " +
+ "(in _assign)", child)
+ idx = self.expr(child.subs[0], current_klass)
+ value = self.expr(node.expr, current_klass)
+ print >>self.output, " " + obj + ".__setitem__(" \
+ + idx + ", " + rhs + ");"
+ continue
+ print >>self.output, " " + lhs + " = " + rhs + ";"
+ return
+ else:
+ raise TranslationError("unsupported type (in _assign)", v)
+
+ rhs = self.expr(node.expr, current_klass)
+ if dbg:
+ print "b", repr(node.expr), rhs
+ print >>self.output, " " + lhs + " " + op + " " + rhs + ";"
+
+
+ def _discard(self, node, current_klass):
+
+ if isinstance(node.expr, ast.CallFunc):
+ debugStmt = self.debug and not self._isNativeFunc(node)
+ if debugStmt and isinstance(node.expr.node, ast.Name) and \
+ node.expr.node.name == 'import_wait':
+ debugStmt = False
+ if debugStmt:
+ st = self.get_line_trace(node)
+ print >>self.output, "sys.addstack('%s');\n" % st
+ if isinstance(node.expr.node, ast.Name) and node.expr.node.name == NATIVE_JS_FUNC_NAME:
+ if len(node.expr.args) != 1:
+ raise TranslationError("native javascript function %s must have one arg" % NATIVE_JS_FUNC_NAME, node.expr)
+ if not isinstance(node.expr.args[0], ast.Const):
+ raise TranslationError("native javascript function %s must have constant arg" % NATIVE_JS_FUNC_NAME, node.expr)
+ raw_js = node.expr.args[0].value
+ print >>self.output, raw_js
+ else:
+ expr = self._callfunc(node.expr, current_klass)
+ print >>self.output, " " + expr + ";"
+
+ if debugStmt:
+ print >>self.output, "sys.popstack();\n"
+
+ elif isinstance(node.expr, ast.Const):
+ if node.expr.value is not None: # Empty statements generate ignore None
+ print >>self.output, self._const(node.expr)
+ else:
+ raise TranslationError("unsupported type (in _discard)", node.expr)
+
+
+ def _if(self, node, current_klass):
+ for i in range(len(node.tests)):
+ test, consequence = node.tests[i]
+ if i == 0:
+ keyword = "if"
+ else:
+ keyword = "else if"
+
+ self._if_test(keyword, test, consequence, current_klass)
+
+ if node.else_:
+ keyword = "else"
+ test = None
+ consequence = node.else_
+
+ self._if_test(keyword, test, consequence, current_klass)
+
+
+ def _if_test(self, keyword, test, consequence, current_klass):
+ if test:
+ expr = self.expr(test, current_klass)
+
+ print >>self.output, " " + keyword + " (pyjslib.bool(" + expr + ")) {"
+ else:
+ print >>self.output, " " + keyword + " {"
+
+ if isinstance(consequence, ast.Stmt):
+ for child in consequence.nodes:
+ self._stmt(child, current_klass)
+ else:
+ raise TranslationError("unsupported type (in _if_test)", consequence)
+
+ print >>self.output, " }"
+
+
+ def _from(self, node):
+ for name in node.names:
+ # look up "hack" in AppTranslator as to how findFile gets here
+ module_name = node.modname + "." + name[0]
+ try:
+ ff = self.findFile(module_name + ".py")
+ except Exception:
+ ff = None
+ if ff:
+ self.add_imported_module(module_name)
+ else:
+ self.imported_classes[name[0]] = node.modname
+
+
+ def _compare(self, node, current_klass):
+ lhs = self.expr(node.expr, current_klass)
+
+ if len(node.ops) != 1:
+ raise TranslationError("only one ops supported (in _compare)", node)
+
+ op = node.ops[0][0]
+ rhs_node = node.ops[0][1]
+ rhs = self.expr(rhs_node, current_klass)
+
+ if op == "==":
+ return "pyjslib.eq(%s, %s)" % (lhs, rhs)
+ if op == "in":
+ return rhs + ".__contains__(" + lhs + ")"
+ elif op == "not in":
+ return "!" + rhs + ".__contains__(" + lhs + ")"
+ elif op == "is":
+ op = "==="
+ elif op == "is not":
+ op = "!=="
+
+ return "(" + lhs + " " + op + " " + rhs + ")"
+
+
+ def _not(self, node, current_klass):
+ expr = self.expr(node.expr, current_klass)
+
+ return "!(" + expr + ")"
+
+ def _or(self, node, current_klass):
+ expr = "("+(") || (".join([self.expr(child, current_klass) for child in node.nodes]))+')'
+ return expr
+
+ def _and(self, node, current_klass):
+ expr = "("+(") && (".join([self.expr(child, current_klass) for child in node.nodes]))+")"
+ return expr
+
+ def _for(self, node, current_klass):
+ assign_name = ""
+ assign_tuple = ""
+
+ # based on Bob Ippolito's Iteration in Javascript code
+ if isinstance(node.assign, ast.AssName):
+ assign_name = node.assign.name
+ self.add_local_arg(assign_name)
+ if node.assign.flags == "OP_ASSIGN":
+ op = "="
+ elif isinstance(node.assign, ast.AssTuple):
+ op = "="
+ i = 0
+ for child in node.assign:
+ child_name = child.name
+ if assign_name == "":
+ assign_name = "temp_" + child_name
+ self.add_local_arg(child_name)
+ assign_tuple += """
+ var %(child_name)s %(op)s %(assign_name)s.__getitem__(%(i)i);
+ """ % locals()
+ i += 1
+ else:
+ raise TranslationError("unsupported type (in _for)", node.assign)
+
+ if isinstance(node.list, ast.Name):
+ list_expr = self._name(node.list, current_klass)
+ elif isinstance(node.list, ast.Getattr):
+ list_expr = self._getattr(node.list, current_klass)
+ elif isinstance(node.list, ast.CallFunc):
+ list_expr = self._callfunc(node.list, current_klass)
+ else:
+ raise TranslationError("unsupported type (in _for)", node.list)
+
+ lhs = "var " + assign_name
+ iterator_name = "__" + assign_name
+
+ print >>self.output, """
+ var %(iterator_name)s = %(list_expr)s.__iter__();
+ try {
+ while (true) {
+ %(lhs)s %(op)s %(iterator_name)s.next();
+ %(assign_tuple)s
+ """ % locals()
+ for node in node.body.nodes:
+ self._stmt(node, current_klass)
+ print >>self.output, """
+ }
+ } catch (e) {
+ if (e.__name__ != pyjslib.StopIteration.__name__) {
+ throw e;
+ }
+ }
+ """ % locals()
+
+
+ def _while(self, node, current_klass):
+ test = self.expr(node.test, current_klass)
+ print >>self.output, " while (pyjslib.bool(" + test + ")) {"
+ if isinstance(node.body, ast.Stmt):
+ for child in node.body.nodes:
+ self._stmt(child, current_klass)
+ else:
+ raise TranslationError("unsupported type (in _while)", node.body)
+ print >>self.output, " }"
+
+
+ def _const(self, node):
+ if isinstance(node.value, int):
+ return str(node.value)
+ elif isinstance(node.value, float):
+ return str(node.value)
+ elif isinstance(node.value, basestring):
+ v = node.value
+ if isinstance(node.value, unicode):
+ v = v.encode('utf-8')
+ return "String('%s')" % escapejs(v)
+ elif node.value is None:
+ return "null"
+ else:
+ raise TranslationError("unsupported type (in _const)", node)
+
+ def _unaryadd(self, node, current_klass):
+ return self.expr(node.expr, current_klass)
+
+ def _unarysub(self, node, current_klass):
+ return "-" + self.expr(node.expr, current_klass)
+
+ def _add(self, node, current_klass):
+ return self.expr(node.left, current_klass) + " + " + self.expr(node.right, current_klass)
+
+ def _sub(self, node, current_klass):
+ return self.expr(node.left, current_klass) + " - " + self.expr(node.right, current_klass)
+
+ def _div(self, node, current_klass):
+ return self.expr(node.left, current_klass) + " / " + self.expr(node.right, current_klass)
+
+ def _mul(self, node, current_klass):
+ return self.expr(node.left, current_klass) + " * " + self.expr(node.right, current_klass)
+
+ def _mod(self, node, current_klass):
+ if isinstance(node.left, ast.Const) and isinstance(node.left.value, StringType):
+ self.imported_js.add("sprintf.js") # Include the sprintf functionality if it is used
+ return "sprintf("+self.expr(node.left, current_klass) + ", " + self.expr(node.right, current_klass)+")"
+ return self.expr(node.left, current_klass) + " % " + self.expr(node.right, current_klass)
+
+ def _invert(self, node, current_klass):
+ return "~" + self.expr(node.expr, current_klass)
+
+ def _bitand(self, node, current_klass):
+ return " & ".join([self.expr(child, current_klass) for child in node.nodes])
+
+ def _bitshiftleft(self, node, current_klass):
+ return self.expr(node.left, current_klass) + " << " + self.expr(node.right, current_klass)
+
+ def _bitshiftright(self, node, current_klass):
+ return self.expr(node.left, current_klass) + " >>> " + self.expr(node.right, current_klass)
+
+ def _bitxor(self,node, current_klass):
+ return " ^ ".join([self.expr(child, current_klass) for child in node.nodes])
+
+ def _bitor(self, node, current_klass):
+ return " | ".join([self.expr(child, current_klass) for child in node.nodes])
+
+ def _subscript(self, node, current_klass):
+ if node.flags == "OP_APPLY":
+ if len(node.subs) == 1:
+ return self.expr(node.expr, current_klass) + ".__getitem__(" + self.expr(node.subs[0], current_klass) + ")"
+ else:
+ raise TranslationError("must have one sub (in _subscript)", node)
+ else:
+ raise TranslationError("unsupported flag (in _subscript)", node)
+
+ def _subscript_stmt(self, node, current_klass):
+ if node.flags == "OP_DELETE":
+ print >>self.output, " " + self.expr(node.expr, current_klass) + ".__delitem__(" + self.expr(node.subs[0], current_klass) + ");"
+ else:
+ raise TranslationError("unsupported flag (in _subscript)", node)
+
+ def _list(self, node, current_klass):
+ return "new pyjslib.List([" + ", ".join([self.expr(x, current_klass) for x in node.nodes]) + "])"
+
+ def _dict(self, node, current_klass):
+ items = []
+ for x in node.items:
+ key = self.expr(x[0], current_klass)
+ value = self.expr(x[1], current_klass)
+ items.append("[" + key + ", " + value + "]")
+ return "new pyjslib.Dict([" + ", ".join(items) + "])"
+
+ def _tuple(self, node, current_klass):
+ return "new pyjslib.Tuple([" + ", ".join([self.expr(x, current_klass) for x in node.nodes]) + "])"
+
+ def _lambda(self, node, current_klass):
+ if node.varargs:
+ raise TranslationError("varargs are not supported in Lambdas", node)
+ if node.kwargs:
+ raise TranslationError("kwargs are not supported in Lambdas", node)
+ res = cStringIO.StringIO()
+ arg_names = list(node.argnames)
+ function_args = ", ".join(arg_names)
+ for child in node.getChildNodes():
+ expr = self.expr(child, None)
+ print >> res, "function (%s){" % function_args
+ self._default_args_handler(node, arg_names, None,
+ output=res)
+ print >> res, 'return %s;}' % expr
+ return res.getvalue()
+
+ def _slice(self, node, current_klass):
+ if node.flags == "OP_APPLY":
+ lower = "null"
+ upper = "null"
+ if node.lower != None:
+ lower = self.expr(node.lower, current_klass)
+ if node.upper != None:
+ upper = self.expr(node.upper, current_klass)
+ return "pyjslib.slice(" + self.expr(node.expr, current_klass) + ", " + lower + ", " + upper + ")"
+ else:
+ raise TranslationError("unsupported flag (in _slice)", node)
+
+ def _global(self, node, current_klass):
+ for name in node.names:
+ self.method_imported_globals.add(name)
+
+ def expr(self, node, current_klass):
+ if isinstance(node, ast.Const):
+ return self._const(node)
+ # @@@ not sure if the parentheses should be here or in individual operator functions - JKT
+ elif isinstance(node, ast.Mul):
+ return " ( " + self._mul(node, current_klass) + " ) "
+ elif isinstance(node, ast.Add):
+ return " ( " + self._add(node, current_klass) + " ) "
+ elif isinstance(node, ast.Sub):
+ return " ( " + self._sub(node, current_klass) + " ) "
+ elif isinstance(node, ast.Div):
+ return " ( " + self._div(node, current_klass) + " ) "
+ elif isinstance(node, ast.Mod):
+ return self._mod(node, current_klass)
+ elif isinstance(node, ast.UnaryAdd):
+ return self._unaryadd(node, current_klass)
+ elif isinstance(node, ast.UnarySub):
+ return self._unarysub(node, current_klass)
+ elif isinstance(node, ast.Not):
+ return self._not(node, current_klass)
+ elif isinstance(node, ast.Or):
+ return self._or(node, current_klass)
+ elif isinstance(node, ast.And):
+ return self._and(node, current_klass)
+ elif isinstance(node, ast.Invert):
+ return self._invert(node, current_klass)
+ elif isinstance(node, ast.Bitand):
+ return "("+self._bitand(node, current_klass)+")"
+ elif isinstance(node,ast.LeftShift):
+ return self._bitshiftleft(node, current_klass)
+ elif isinstance(node, ast.RightShift):
+ return self._bitshiftright(node, current_klass)
+ elif isinstance(node, ast.Bitxor):
+ return "("+self._bitxor(node, current_klass)+")"
+ elif isinstance(node, ast.Bitor):
+ return "("+self._bitor(node, current_klass)+")"
+ elif isinstance(node, ast.Compare):
+ return self._compare(node, current_klass)
+ elif isinstance(node, ast.CallFunc):
+ return self._callfunc(node, current_klass)
+ elif isinstance(node, ast.Name):
+ return self._name(node, current_klass)
+ elif isinstance(node, ast.Subscript):
+ return self._subscript(node, current_klass)
+ elif isinstance(node, ast.Getattr):
+ return self._getattr(node, current_klass)
+ elif isinstance(node, ast.List):
+ return self._list(node, current_klass)
+ elif isinstance(node, ast.Dict):
+ return self._dict(node, current_klass)
+ elif isinstance(node, ast.Tuple):
+ return self._tuple(node, current_klass)
+ elif isinstance(node, ast.Slice):
+ return self._slice(node, current_klass)
+ elif isinstance(node, ast.Lambda):
+ return self._lambda(node, current_klass)
+ else:
+ raise TranslationError("unsupported type (in expr)", node)
+
+
+
+import cStringIO
+
+def translate(file_name, module_name, debug=False):
+ f = file(file_name, "r")
+ src = f.read()
+ f.close()
+ output = cStringIO.StringIO()
+ mod = compiler.parseFile(file_name)
+ t = Translator(module_name, module_name, module_name, src, debug, mod, output)
+ return output.getvalue()
+
+
+class PlatformParser:
+ def __init__(self, platform_dir = "", verbose=True):
+ self.platform_dir = platform_dir
+ self.parse_cache = {}
+ self.platform = ""
+ self.verbose = verbose
+
+ def setPlatform(self, platform):
+ self.platform = platform
+
+ def parseModule(self, module_name, file_name):
+
+ importing = False
+ if not self.parse_cache.has_key(file_name):
+ importing = True
+ mod = compiler.parseFile(file_name)
+ self.parse_cache[file_name] = mod
+ else:
+ mod = self.parse_cache[file_name]
+
+ override = False
+ platform_file_name = self.generatePlatformFilename(file_name)
+ if self.platform and os.path.isfile(platform_file_name):
+ mod = copy.deepcopy(mod)
+ mod_override = compiler.parseFile(platform_file_name)
+ self.merge(mod, mod_override)
+ override = True
+
+ if self.verbose:
+ if override:
+ print "Importing %s (Platform %s)" % (module_name, self.platform)
+ elif importing:
+ print "Importing %s" % (module_name)
+
+ return mod, override
+
+ def generatePlatformFilename(self, file_name):
+ (module_name, extension) = os.path.splitext(os.path.basename(file_name))
+ platform_file_name = module_name + self.platform + extension
+
+ return os.path.join(os.path.dirname(file_name), self.platform_dir, platform_file_name)
+
+ def merge(self, tree1, tree2):
+ for child in tree2.node:
+ if isinstance(child, ast.Function):
+ self.replaceFunction(tree1, child.name, child)
+ elif isinstance(child, ast.Class):
+ self.replaceClassMethods(tree1, child.name, child)
+
+ return tree1
+
+ def replaceFunction(self, tree, function_name, function_node):
+ # find function to replace
+ for child in tree.node:
+ if isinstance(child, ast.Function) and child.name == function_name:
+ self.copyFunction(child, function_node)
+ return
+ raise TranslationError("function not found: " + function_name, function_node)
+
+ def replaceClassMethods(self, tree, class_name, class_node):
+ # find class to replace
+ old_class_node = None
+ for child in tree.node:
+ if isinstance(child, ast.Class) and child.name == class_name:
+ old_class_node = child
+ break
+
+ if not old_class_node:
+ raise TranslationError("class not found: " + class_name, class_node)
+
+ # replace methods
+ for function_node in class_node.code:
+ if isinstance(function_node, ast.Function):
+ found = False
+ for child in old_class_node.code:
+ if isinstance(child, ast.Function) and child.name == function_node.name:
+ found = True
+ self.copyFunction(child, function_node)
+ break
+
+ if not found:
+ raise TranslationError("class method not found: " + class_name + "." + function_node.name, function_node)
+
+ def copyFunction(self, target, source):
+ target.code = source.code
+ target.argnames = source.argnames
+ target.defaults = source.defaults
+ target.doc = source.doc # @@@ not sure we need to do this any more
+
+def dotreplace(fname):
+ path, ext = os.path.splitext(fname)
+ return path.replace(".", "/") + ext
+
+class AppTranslator:
+
+ def __init__(self, library_dirs=[], parser=None, dynamic=False,
+ optimize=False, verbose=True):
+ self.extension = ".py"
+ self.optimize = optimize
+ self.library_modules = []
+ self.overrides = {}
+ self.library_dirs = path + library_dirs
+ self.dynamic = dynamic
+ self.verbose = verbose
+
+ if not parser:
+ self.parser = PlatformParser()
+ else:
+ self.parser = parser
+
+ self.parser.dynamic = dynamic
+
+ def findFile(self, file_name):
+ if os.path.isfile(file_name):
+ return file_name
+
+ for library_dir in self.library_dirs:
+ file_name = dotreplace(file_name)
+ full_file_name = os.path.join(
+ os.path.abspath(os.path.dirname(__file__)), library_dir, file_name)
+ if os.path.isfile(full_file_name):
+ return full_file_name
+
+ fnameinit, ext = os.path.splitext(file_name)
+ fnameinit = fnameinit + "/__init__.py"
+
+ full_file_name = os.path.join(
+ os.path.abspath(os.path.dirname(__file__)), library_dir, fnameinit)
+ if os.path.isfile(full_file_name):
+ return full_file_name
+
+ raise Exception("file not found: " + file_name)
+
+ def _translate(self, module_name, is_app=True, debug=False,
+ imported_js=set()):
+ if module_name not in self.library_modules:
+ self.library_modules.append(module_name)
+
+ file_name = self.findFile(module_name + self.extension)
+
+ output = cStringIO.StringIO()
+
+ f = file(file_name, "r")
+ src = f.read()
+ f.close()
+
+ mod, override = self.parser.parseModule(module_name, file_name)
+ if override:
+ override_name = "%s.%s" % (self.parser.platform.lower(),
+ module_name)
+ self.overrides[override_name] = override_name
+ if is_app:
+ mn = '__main__'
+ else:
+ mn = module_name
+ t = Translator(mn, module_name, module_name,
+ src, debug, mod, output, self.dynamic, self.optimize,
+ self.findFile)
+
+ module_str = output.getvalue()
+ imported_js.update(set(t.imported_js))
+ imported_modules_str = ""
+ for module in t.imported_modules:
+ if module not in self.library_modules:
+ self.library_modules.append(module)
+ #imported_js.update(set(t.imported_js))
+ #imported_modules_str += self._translate(
+ # module, False, debug=debug, imported_js=imported_js)
+
+ return imported_modules_str + module_str
+
+
+ def translate(self, module_name, is_app=True, debug=False,
+ library_modules=[]):
+ app_code = cStringIO.StringIO()
+ lib_code = cStringIO.StringIO()
+ imported_js = set()
+ self.library_modules = []
+ self.overrides = {}
+ for library in library_modules:
+ if library.endswith(".js"):
+ imported_js.add(library)
+ continue
+ self.library_modules.append(library)
+ if self.verbose:
+ print 'Including LIB', library
+ print >> lib_code, '\n//\n// BEGIN LIB '+library+'\n//\n'
+ print >> lib_code, self._translate(
+ library, False, debug=debug, imported_js=imported_js)
+
+ print >> lib_code, "/* initialize static library */"
+ print >> lib_code, "%s%s();\n" % (UU, library)
+
+ print >> lib_code, '\n//\n// END LIB '+library+'\n//\n'
+ if module_name:
+ print >> app_code, self._translate(
+ module_name, is_app, debug=debug, imported_js=imported_js)
+ for js in imported_js:
+ path = self.findFile(js)
+ if os.path.isfile(path):
+ if self.verbose:
+ print 'Including JS', js
+ print >> lib_code, '\n//\n// BEGIN JS '+js+'\n//\n'
+ print >> lib_code, file(path).read()
+ print >> lib_code, '\n//\n// END JS '+js+'\n//\n'
+ else:
+ print >>sys.stderr, 'Warning: Unable to find imported javascript:', js
+ return lib_code.getvalue(), app_code.getvalue()
+
+usage = """
+ usage: %s file_name [module_name]
+"""
+
+def main():
+ import sys
+ if len(sys.argv)<2:
+ print >> sys.stderr, usage % sys.argv[0]
+ sys.exit(1)
+ file_name = os.path.abspath(sys.argv[1])
+ if not os.path.isfile(file_name):
+ print >> sys.stderr, "File not found %s" % file_name
+ sys.exit(1)
+ if len(sys.argv) > 2:
+ module_name = sys.argv[2]
+ else:
+ module_name = None
+ print translate(file_name, module_name),
+
+if __name__ == "__main__":
+ main()
+
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/svgui/svgui.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/svgui.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,112 @@
+import wx
+import os, sys, shutil
+
+from ConfigTree import opjimg
+from confnodes.python import PythonCodeTemplate
+
+from pyjs import translate
+
+from docutils import *
+
+class RootClass:
+
+ ConfNodeMethods = [
+ {"bitmap" : os.path.join("images","ImportSVG"),
+ "name" : _("Import SVG"),
+ "tooltip" : _("Import SVG"),
+ "method" : "_ImportSVG"},
+ {"bitmap" : os.path.join("images","ImportSVG"),
+ "name" : _("Inkscape"),
+ "tooltip" : _("Create HMI"),
+ "method" : "_StartInkscape"},
+ ]
+
+ def ConfNodePath(self):
+ return os.path.join(self.PlugParent.ConfNodePath(), "modules", self.PlugType)
+
+ def _getSVGpath(self):
+ # define name for IEC raw code file
+ return os.path.join(self.PlugPath(), "gui.svg")
+
+ def _getSVGUIserverpath(self):
+ return os.path.join(os.path.dirname(__file__), "svgui_server.py")
+
+ def PlugGenerate_C(self, buildpath, locations):
+ """
+ Return C code generated by iec2c compiler
+ when _generate_softPLC have been called
+ @param locations: ignored
+ @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
+ """
+
+ current_location = self.GetCurrentLocation()
+ # define a unique name for the generated C file
+ location_str = "_".join(map(lambda x:str(x), current_location))
+
+ res = ([], "", False)
+
+ svgfile=self._getSVGpath()
+ if os.path.exists(svgfile):
+ res += (("gui.svg", file(svgfile,"rb")),)
+
+ svguiserverfile = open(self._getSVGUIserverpath(), 'r')
+ svguiservercode = svguiserverfile.read()
+ svguiserverfile.close()
+
+ svguilibpath = os.path.join(self._getBuildPath(), "svguilib.js")
+ svguilibfile = open(svguilibpath, 'w')
+ svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "sys.py"), "sys"))
+ svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "_pyjs.js"), 'r').read())
+ svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "pyjslib.py"), "pyjslib"))
+ svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "svguilib.py"), "svguilib"))
+ svguilibfile.write("pyjslib();\nsvguilib();\n")
+ svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "json.js"), 'r').read())
+ svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "livesvg.js"), 'r').read())
+ svguilibfile.close()
+ jsmodules = {"LiveSVGPage": "svguilib.js"}
+ res += (("svguilib.js", file(svguilibpath,"rb")),)
+
+ runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
+ runtimefile = open(runtimefile_path, 'w')
+ runtimefile.write(svguiservercode % {"svgfile" : "gui.svg"})
+ runtimefile.write("""
+def _runtime_%(location)s_begin():
+ website.LoadHMI(%(svgui_class)s, %(jsmodules)s)
+
+def _runtime_%(location)s_cleanup():
+ website.UnLoadHMI()
+
+""" % {"location": location_str,
+ "svgui_class": "SVGUI_HMI",
+ "jsmodules" : str(jsmodules),
+ })
+ runtimefile.close()
+
+ res += (("runtime_%s.py"%location_str, file(runtimefile_path,"rb")),)
+
+ return res
+
+ def _ImportSVG(self):
+ dialog = wx.FileDialog(self.GetPlugRoot().AppFrame, _("Choose a SVG file"), os.getcwd(), "", _("SVG files (*.svg)|*.svg|All files|*.*"), wx.OPEN)
+ if dialog.ShowModal() == wx.ID_OK:
+ svgpath = dialog.GetPath()
+ if os.path.isfile(svgpath):
+ shutil.copy(svgpath, self._getSVGpath())
+ else:
+ self.GetPlugRoot().logger.write_error(_("No such SVG file: %s\n")%svgpath)
+ dialog.Destroy()
+
+ def _StartInkscape(self):
+ svgfile = self._getSVGpath()
+ open_inkscape = True
+ if not self.GetPlugRoot().CheckProjectPathPerm():
+ dialog = wx.MessageDialog(self.GetPlugRoot().AppFrame,
+ _("You don't have write permissions.\nOpen Inkscape anyway ?"),
+ _("Open Inkscape"),
+ wx.YES_NO|wx.ICON_QUESTION)
+ open_inkscape = dialog.ShowModal() == wx.ID_YES
+ dialog.Destroy()
+ if open_inkscape:
+ if not os.path.isfile(svgfile):
+ svgfile = None
+ open_svg(svgfile)
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/svgui/svgui_server.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/svgui_server.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,130 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import os
+
+from nevow import rend, appserver, inevow, tags, loaders, athena
+import simplejson as json
+
+svgfile = '%(svgfile)s'
+
+svguiWidgets = {}
+
+currentId = 0
+def getNewId():
+ global currentId
+ currentId += 1
+ return currentId
+
+class SvguiWidget:
+
+ def __init__(self, classname, id, **kwargs):
+ self.classname = classname
+ self.id = id
+ self.attrs = kwargs.copy()
+ self.inputs = {}
+ self.outputs = {}
+ self.inhibit = False
+ self.changed = False
+
+ def setinput(self, attrname, value):
+ self.inputs[attrname] = value
+
+ def getinput(self, attrname, default=None):
+ if not self.inputs.has_key(attrname):
+ self.inputs[attrname] = default
+ return self.inputs[attrname]
+
+ def setoutput(self, attrname, value):
+ if self.outputs.get(attrname) != value:
+ self.outputs[attrname] = value
+ self.changed = True
+ self.RefreshInterface()
+
+ def updateoutputs(self, **kwargs):
+ for attrname, value in kwargs.iteritems():
+ if self.outputs.get(attrname) != value:
+ self.outputs[attrname] = value
+ self.changed = True
+ self.RefreshInterface()
+
+ def RefreshInterface(self):
+ interface = website.getHMI()
+ if isinstance(interface, SVGUI_HMI) and self.changed and not self.inhibit:
+ self.changed = False
+ d = interface.sendData(self)
+ if d is not None:
+ self.inhibit = True
+ d.addCallback(self.InterfaceRefreshed)
+
+ def InterfaceRefreshed(self, result):
+ self.inhibit = False
+ if self.changed:
+ self.RefreshInterface()
+
+def get_object_init_state(obj):
+ # Convert objects to a dictionary of their representation
+ attrs = obj.attrs.copy()
+ attrs.update(obj.inputs)
+ d = { '__class__': obj.classname,
+ 'id': obj.id,
+ 'kwargs': json.dumps(attrs),
+ }
+ return d
+
+def get_object_current_state(obj):
+ # Convert objects to a dictionary of their representation
+ d = { '__class__': obj.classname,
+ 'id': obj.id,
+ 'kwargs': json.dumps(obj.outputs),
+ }
+ return d
+
+class SVGUI_HMI(website.PLCHMI):
+ jsClass = u"LiveSVGPage.LiveSVGWidget"
+
+ docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[
+ tags.xml(loaders.xmlfile(os.path.join(WorkingDir, svgfile))),
+ ])
+
+ def HMIinitialisation(self):
+ gadgets = []
+ for gadget in svguiWidgets.values():
+ gadgets.append(unicode(json.dumps(gadget, default=get_object_init_state, indent=2), 'ascii'))
+ d = self.callRemote('init', gadgets)
+ d.addCallback(self.HMIinitialised)
+
+ def sendData(self,data):
+ if self.initialised:
+ return self.callRemote('receiveData',unicode(json.dumps(data, default=get_object_current_state, indent=2), 'ascii'))
+ return None
+
+ def setattr(self, id, attrname, value):
+ svguiWidgets[id].setinput(attrname, value)
+
+def createSVGUIControl(*args, **kwargs):
+ id = getNewId()
+ gad = SvguiWidget(args[0], id, **kwargs)
+ svguiWidgets[id] = gad
+ gadget = [unicode(json.dumps(gad, default=get_object_init_state, indent=2), 'ascii')]
+ interface = website.getHMI()
+ if isinstance(interface, SVGUI_HMI) and interface.initialised:
+ interface.callRemote('init', gadget)
+ return id
+
+def setAttr(id, attrname, value):
+ gad = svguiWidgets.get(id, None)
+ if gad is not None:
+ gad.setoutput(attrname, value)
+
+def updateAttr(id, **kwargs):
+ gad = svguiWidgets.get(id, None)
+ if gad is not None:
+ gad.updateoutput(**kwargs)
+
+def getAttr(id, attrname, default=None):
+ gad = svguiWidgets.get(id, None)
+ if gad is not None:
+ return gad.getinput(attrname, default)
+ return default
+
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/svgui/svguilib.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/svguilib.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,117 @@
+
+class button:
+
+ def __init__(self, parent, id, args):
+ self.parent = parent
+ self.id = id
+ self.back_elt = getSVGElementById(args.back_id)
+ self.sele_elt = getSVGElementById(args.sele_id)
+ self.toggle = args.toggle
+ self.active = args.active
+ if args.state != undefined:
+ self.state = args.state
+ else:
+ self.state = False
+ self.dragging = False
+ if self.toggle:
+ self.up = not self.state
+ else:
+ self.up = True
+
+ # Add event on each element of the button
+ if self.active:
+ self.back_elt.addEventListener("mouseup", self, False)
+ self.back_elt.addEventListener("mousedown", self, False)
+ self.back_elt.addEventListener("mouseover", self, False)
+ self.back_elt.addEventListener("mouseout", self, False)
+
+ self.sele_elt.addEventListener("mouseup", self, False)
+ self.sele_elt.addEventListener("mousedown", self, False)
+ self.sele_elt.addEventListener("mouseover", self, False)
+ self.sele_elt.addEventListener("mouseout", self, False)
+
+ blockSVGElementDrag(self.back_elt)
+ blockSVGElementDrag(self.sele_elt)
+
+ self.updateElements()
+
+ # method to display the current state of interface
+ def updateElements(self):
+ if self.up:
+ self.sele_elt.setAttribute("display", "none")
+ self.back_elt.removeAttribute("display")
+ else:
+ self.sele_elt.removeAttribute("display")
+ self.back_elt.setAttribute("display", "none")
+
+ def updateValues(self, values):
+ if values.state != self.state:
+ self.state = values.state
+ self.up = not self.state
+ updateAttr(self.id, 'state', self.state)
+ self.updateElements()
+
+ def handleEvent(self, evt):
+ # Quand le bouton de la souris est presse
+ if evt.type == "mousedown":
+ evt.stopPropagation()
+ setCurrentObject(self)
+
+ self.dragging = True
+
+ if self.toggle:
+ self.up = self.state
+ else:
+ self.up = False
+ self.state = True
+ updateAttr(self.id, 'state', self.state)
+ self.updateElements()
+
+ if isCurrentObject(self) and self.dragging:
+ # Quand le bouton est survole
+ if evt.type == "mouseover" and self.toggle:
+ self.up = self.state
+ self.updateElements()
+
+ # Quand le curseur quitte la zone du bouton
+ elif evt.type == "mouseout" and self.toggle:
+ self.up = not self.state
+ self.updateElements()
+
+ # Quand le bouton de la souris est relache
+ elif evt.type == "mouseup":
+ evt.stopPropagation()
+ if self.toggle and self.up == self.state:
+ self.state = not self.state
+ updateAttr(self.id, 'state', self.state)
+ elif not self.toggle:
+ self.up = True
+ self.state = False
+ updateAttr(self.id, 'state', self.state)
+ self.updateElements()
+ self.dragging = False
+
+class textControl:
+
+ def __init__(self, parent, id, args):
+ self.parent = parent
+ self.id = id
+ self.back_elt = getSVGElementById(args.back_id)
+ if args.text != undefined:
+ self.text = args.text
+ else:
+ self.text = ""
+ self.updateElements()
+
+ def updateValues(self, values):
+ if values.text != self.value:
+ self.text = values.text
+ updateAttr(self.id, 'text', self.text)
+ self.updateElements()
+
+ def updateElements(self):
+ self.back_elt.firstChild.firstChild.textContent = self.text
+
+ def handleEvent(self, evt):
+ pass
+
\ No newline at end of file
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/wxglade_hmi/README
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/wxglade_hmi/README Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+WxGlade HMI
\ No newline at end of file
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/wxglade_hmi/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/wxglade_hmi/__init__.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+from wxglade_hmi import *
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/modules/wxglade_hmi/wxglade_hmi.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/wxglade_hmi/wxglade_hmi.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,124 @@
+import wx
+import os, sys
+from xml.dom import minidom
+
+from ConfigTree import opjimg
+from confnodes.python import PythonCodeTemplate
+
+class RootClass(PythonCodeTemplate):
+
+ ConfNodeMethods = [
+ {"bitmap" : opjimg("editWXGLADE"),
+ "name" : _("WXGLADE GUI"),
+ "tooltip" : _("Edit a WxWidgets GUI with WXGlade"),
+ "method" : "_editWXGLADE"},
+ ]
+
+ def _getWXGLADEpath(self):
+ # define name for IEC raw code file
+ return os.path.join(self.PlugPath(), "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 PlugGenerate_C(self, buildpath, locations):
+ """
+ Return C code generated by iec2c compiler
+ when _generate_softPLC have been called
+ @param locations: ignored
+ @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
+ """
+
+ current_location = self.GetCurrentLocation()
+ # define a unique name for the generated C file
+ location_str = "_".join(map(lambda x:str(x), current_location))
+
+ runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
+ runtimefile = open(runtimefile_path, 'w')
+
+ 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[node._attrs["name"].value] = node._attrs["class"].value
+
+ 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')
+ runtimefile.write(hmipyfile.read())
+ hmipyfile.close()
+
+ runtimefile.write(self.GetPythonCode())
+ runtimefile.write("""
+%(declare)s
+
+def _runtime_%(location)s_begin():
+ global %(global)s
+
+ def OnCloseFrame(evt):
+ wx.MessageBox(_("Please stop PLC to close"))
+
+ %(init)s
+
+def _runtime_%(location)s_cleanup():
+ global %(global)s
+
+ %(cleanup)s
+
+""" % {"location": location_str,
+ "declare": "\n".join(map(lambda x:"%s = None" % x, hmi_frames.keys())),
+ "global": ",".join(hmi_frames.keys()),
+ "init": "\n".join(map(lambda x: """
+ %(name)s = %(class)s(None)
+ %(name)s.Bind(wx.EVT_CLOSE, OnCloseFrame)
+ %(name)s.Show()
+""" % {"name": x[0], "class": x[1]},
+ hmi_frames.items())),
+ "cleanup": "\n ".join(map(lambda x:"%s.Destroy()" % x, hmi_frames.keys()))})
+ runtimefile.close()
+
+ return [], "", False, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb"))
+
+ def _editWXGLADE(self):
+ wxg_filename = self._getWXGLADEpath()
+ open_wxglade = True
+ if not self.GetPlugRoot().CheckProjectPathPerm():
+ dialog = wx.MessageDialog(self.GetPlugRoot().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("""
+
+
+
+ """ % {"name": hmi_name, "class": "Class_%s" % hmi_name})
+ if wx.Platform == '__WXMSW__':
+ wxg_filename = "\"%s\""%wxg_filename
+ self.launch_wxglade([wxg_filename])
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/plc_python.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/plc_python.c Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,216 @@
+/*
+ * Python Asynchronous execution code
+ *
+ * PLC put python commands in a fifo, respecting execution order
+ * with the help of C pragmas inserted in python_eval FB code
+ *
+ * Buffer content is read asynchronously, (from non real time part),
+ * commands are executed and result stored for later use by PLC.
+ *
+ * In this implementation, fifo is a list of pointer to python_eval
+ * function blocks structures. Some local variables have been added in
+ * python_eval interface. We use those local variables as buffer and state
+ * flags.
+ *
+ * */
+
+#include "iec_types_all.h"
+#include "POUS.h"
+#include
+
+/* The fifo (fixed size, as number of FB is fixed) */
+static PYTHON_EVAL* EvalFBs[%(python_eval_fb_count)d];
+/* Producer and consumer cursors */
+static int Current_PLC_EvalFB;
+static int Current_Python_EvalFB;
+
+/* A global IEC-Python gateway state, for use inside python_eval FBs*/
+static int PythonState;
+#define PYTHON_LOCKED_BY_PYTHON 0
+#define PYTHON_LOCKED_BY_PLC 1
+#define PYTHON_MUSTWAKEUP 2
+#define PYTHON_FINISHED 4
+
+/* Each python_eval FunctionBlock have it own state */
+#define PYTHON_FB_FREE 0
+#define PYTHON_FB_REQUESTED 1
+#define PYTHON_FB_PROCESSING 2
+#define PYTHON_FB_ANSWERED 3
+
+int WaitPythonCommands(void);
+void UnBlockPythonCommands(void);
+int TryLockPython(void);
+void UnLockPython(void);
+void LockPython(void);
+
+int __init_%(location)s()
+{
+ int i;
+ /* Initialize cursors */
+ Current_Python_EvalFB = 0;
+ Current_PLC_EvalFB = 0;
+ PythonState = PYTHON_LOCKED_BY_PYTHON;
+ for(i = 0; i < %(python_eval_fb_count)d; i++)
+ EvalFBs[i] = NULL;
+ return 0;
+}
+
+void __cleanup_%(location)s()
+{
+ PythonState = PYTHON_FINISHED;
+ UnBlockPythonCommands();
+}
+
+void __retrieve_%(location)s()
+{
+ /* Check Python thread is not being
+ * modifying internal python_eval data */
+ PythonState = TryLockPython() ?
+ PYTHON_LOCKED_BY_PLC :
+ PYTHON_LOCKED_BY_PYTHON;
+ /* If python thread _is_ in, then PythonState remains PYTHON_LOCKED_BY_PYTHON
+ * and python_eval will no do anything */
+}
+
+void __publish_%(location)s()
+{
+ if(PythonState & PYTHON_LOCKED_BY_PLC){
+ /* If runnig PLC did push something in the fifo*/
+ if(PythonState & PYTHON_MUSTWAKEUP){
+ /* WakeUp python thread */
+ UnBlockPythonCommands();
+ }
+ UnLockPython();
+ }
+}
+/**
+ * Called by the PLC, each time a python_eval
+ * FB instance is executed
+ */
+void __PythonEvalFB(int poll, PYTHON_EVAL* data__)
+{
+ /* detect rising edge on TRIG to trigger evaluation */
+ if(((__GET_VAR(data__->TRIG) && !__GET_VAR(data__->TRIGM1)) ||
+ /* polling is equivalent to trig on value rather than on rising edge*/
+ (poll && __GET_VAR(data__->TRIG) )) &&
+ /* trig only if not already trigged */
+ __GET_VAR(data__->TRIGGED) == 0){
+ /* mark as trigged */
+ __SET_VAR(data__->, TRIGGED, 1);
+ /* make a safe copy of the code */
+ __SET_VAR(data__->, PREBUFFER, __GET_VAR(data__->CODE));
+ }
+ /* retain value for next rising edge detection */
+ __SET_VAR(data__->, TRIGM1, __GET_VAR(data__->TRIG));
+
+ /* python thread is not in ? */
+ if( PythonState & PYTHON_LOCKED_BY_PLC){
+ /* if some answer are waiting, publish*/
+ if(__GET_VAR(data__->STATE) == PYTHON_FB_ANSWERED){
+ /* Copy buffer content into result*/
+ __SET_VAR(data__->, RESULT, __GET_VAR(data__->BUFFER));
+ /* signal result presece to PLC*/
+ __SET_VAR(data__->, ACK, 1);
+ /* Mark as free */
+ __SET_VAR(data__->, STATE, PYTHON_FB_FREE);
+ /* mark as not trigged */
+ if(!poll)
+ __SET_VAR(data__->, TRIGGED, 0);
+ /*printf("__PythonEvalFB pop %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/
+ }else if(poll){
+ /* when in polling, no answer == ack down */
+ __SET_VAR(data__->, ACK, 0);
+ }
+ /* got the order to act ?*/
+ if(__GET_VAR(data__->TRIGGED) == 1 &&
+ /* and not already being processed */
+ __GET_VAR(data__->STATE) == PYTHON_FB_FREE)
+ {
+ /* Enter the block in the fifo
+ * Don't have to check if fifo cell is free
+ * as fifo size == FB count, and a FB cannot
+ * be requested twice */
+ EvalFBs[Current_PLC_EvalFB] = data__;
+ /* copy into BUFFER local*/
+ __SET_VAR(data__->, BUFFER, __GET_VAR(data__->PREBUFFER));
+ /* Set ACK pin to low so that we can set a rising edge on result */
+ if(!poll){
+ /* when not polling, a new answer imply reseting ack*/
+ __SET_VAR(data__->, ACK, 0);
+ }else{
+ /* when in polling, acting reset trigger */
+ __SET_VAR(data__->, TRIGGED, 0);
+ }
+ /* Mark FB busy */
+ __SET_VAR(data__->, STATE, PYTHON_FB_REQUESTED);
+ /* Have to wakeup python thread in case he was asleep */
+ PythonState |= PYTHON_MUSTWAKEUP;
+ /*printf("__PythonEvalFB push %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/
+ /* Get a new line */
+ Current_PLC_EvalFB = (Current_PLC_EvalFB + 1) %% %(python_eval_fb_count)d;
+ }
+ }
+}
+
+char* PythonIterator(char* result)
+{
+ char* next_command;
+ PYTHON_EVAL* data__;
+ //printf("PythonIterator result %%s\n", result);
+ /*emergency exit*/
+ if(PythonState & PYTHON_FINISHED) return NULL;
+ /* take python mutex to prevent changing PLC data while PLC running */
+ LockPython();
+ /* Get current FB */
+ data__ = EvalFBs[Current_Python_EvalFB];
+ if(data__ && /* may be null at first run */
+ __GET_VAR(data__->STATE) == PYTHON_FB_PROCESSING){ /* some answer awaited*/
+ /* If result not None */
+ if(result){
+ /* Get results len */
+ __SET_VAR(data__->, BUFFER, strlen(result), .len);
+ /* prevent results overrun */
+ if(__GET_VAR(data__->BUFFER, .len) > STR_MAX_LEN)
+ {
+ __SET_VAR(data__->, BUFFER, STR_MAX_LEN, .len );
+ /* TODO : signal error */
+ }
+ /* Copy results to buffer */
+ strncpy((char*)__GET_VAR(data__->BUFFER, .body), result, __GET_VAR(data__->BUFFER,.len));
+ }else{
+ __SET_VAR(data__->, BUFFER, 0, .len);
+ }
+ /* remove block from fifo*/
+ EvalFBs[Current_Python_EvalFB] = NULL;
+ /* Mark block as answered */
+ __SET_VAR(data__->, STATE, PYTHON_FB_ANSWERED);
+ /* Get a new line */
+ Current_Python_EvalFB = (Current_Python_EvalFB + 1) %% %(python_eval_fb_count)d;
+ //printf("PythonIterator ++ Current_Python_EvalFB %%d\n", Current_Python_EvalFB);
+ }
+ /* while next slot is empty */
+ while(((data__ = EvalFBs[Current_Python_EvalFB]) == NULL) ||
+ /* or doesn't contain command */
+ __GET_VAR(data__->STATE) != PYTHON_FB_REQUESTED)
+ {
+ UnLockPython();
+ /* wait next FB to eval */
+ //printf("PythonIterator wait\n");
+ if(WaitPythonCommands()) return NULL;
+ /*emergency exit*/
+ if(PythonState & PYTHON_FINISHED) return NULL;
+ LockPython();
+ }
+ /* Mark block as processing */
+ __SET_VAR(data__->, STATE, PYTHON_FB_PROCESSING);
+ //printf("PythonIterator\n");
+ /* make BUFFER a null terminated string */
+ __SET_VAR(data__->, BUFFER, 0, .body[__GET_VAR(data__->BUFFER, .len)]);
+ /* next command is BUFFER */
+ next_command = (char*)__GET_VAR(data__->BUFFER, .body);
+ /* free python mutex */
+ UnLockPython();
+ /* return the next command to eval */
+ return next_command;
+}
+
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/pous.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/pous.xml Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,457 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ N
+
+
+
+
+
+
+ TRIG
+
+
+
+
+
+
+ CODE
+
+
+
+
+
+
+
+
+
+
+ ACK
+
+
+
+
+
+
+
+
+
+
+ RESULT
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ COUNTER
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ USINT#1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ USINT#0
+
+
+
+
+
+
+
+
+
+
+ COUNTER
+
+
+
+
+
+
+
+
+
+
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/python.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/python.py Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,185 @@
+import wx
+import os
+import modules
+from ConfigTree import ConfigTreeNode, opjimg
+from PLCControler import UndoBuffer
+from PythonEditor import PythonEditor
+
+from xml.dom import minidom
+from xmlclass import *
+import cPickle
+
+PythonClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "python_xsd.xsd"))
+
+class PythonCodeTemplate:
+
+ EditorType = PythonEditor
+
+ def __init__(self):
+
+ self.ConfNodeMethods.insert(0,
+ {"bitmap" : opjimg("editPYTHONcode"),
+ "name" : _("Edit Python File"),
+ "tooltip" : _("Edit Python File"),
+ "method" : "_OpenView"},
+ )
+
+ filepath = self.PythonFileName()
+
+ self.PythonCode = PythonClasses["Python"]()
+ if os.path.isfile(filepath):
+ xmlfile = open(filepath, 'r')
+ tree = minidom.parse(xmlfile)
+ xmlfile.close()
+
+ for child in tree.childNodes:
+ if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "Python":
+ self.PythonCode.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"])
+ self.CreatePythonBuffer(True)
+ else:
+ self.CreatePythonBuffer(False)
+ self.OnPlugSave()
+
+ def ConfNodePath(self):
+ return os.path.join(self.PlugParent.ConfNodePath(), "modules", self.PlugType)
+
+ def PythonFileName(self):
+ return os.path.join(self.PlugPath(), "python.xml")
+
+ def GetFilename(self):
+ if self.PythonBuffer.IsCurrentSaved():
+ return "python"
+ else:
+ return "~python~"
+
+ def SetPythonCode(self, text):
+ self.PythonCode.settext(text)
+
+ def GetPythonCode(self):
+ return self.PythonCode.gettext()
+
+ def PlugTestModified(self):
+ return self.ChangesToSave or not self.PythonIsSaved()
+
+ def OnPlugSave(self):
+ filepath = self.PythonFileName()
+
+ text = "\n"
+ extras = {"xmlns":"http://www.w3.org/2001/XMLSchema",
+ "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
+ "xsi:schemaLocation" : "python_xsd.xsd"}
+ text += self.PythonCode.generateXMLText("Python", 0, extras)
+
+ xmlfile = open(filepath,"w")
+ xmlfile.write(text.encode("utf-8"))
+ xmlfile.close()
+
+ self.MarkPythonAsSaved()
+ return True
+
+#-------------------------------------------------------------------------------
+# Current Buffering Management Functions
+#-------------------------------------------------------------------------------
+
+ """
+ Return a copy of the project
+ """
+ def Copy(self, model):
+ return cPickle.loads(cPickle.dumps(model))
+
+ def CreatePythonBuffer(self, saved):
+ self.Buffering = False
+ self.PythonBuffer = UndoBuffer(cPickle.dumps(self.PythonCode), saved)
+
+ def BufferPython(self):
+ self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode))
+
+ def StartBuffering(self):
+ self.Buffering = True
+
+ def EndBuffering(self):
+ if self.Buffering:
+ self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode))
+ self.Buffering = False
+
+ def MarkPythonAsSaved(self):
+ self.EndBuffering()
+ self.PythonBuffer.CurrentSaved()
+
+ def PythonIsSaved(self):
+ return self.PythonBuffer.IsCurrentSaved() and not self.Buffering
+
+ def LoadPrevious(self):
+ self.EndBuffering()
+ self.PythonCode = cPickle.loads(self.PythonBuffer.Previous())
+
+ def LoadNext(self):
+ self.PythonCode = cPickle.loads(self.PythonBuffer.Next())
+
+ def GetBufferState(self):
+ first = self.PythonBuffer.IsFirst() and not self.Buffering
+ last = self.PythonBuffer.IsLast()
+ return not first, not last
+
+def _GetClassFunction(name):
+ def GetRootClass():
+ __import__("confnodes.python.modules." + name)
+ return getattr(modules, name).RootClass
+ return GetRootClass
+
+class RootClass(PythonCodeTemplate):
+
+ # For root object, available Childs Types are modules of the modules packages.
+ PlugChildsTypes = [(name, _GetClassFunction(name), help) for name, help in zip(modules.__all__,modules.helps)]
+
+ def ConfNodePath(self):
+ return os.path.join(self.PlugParent.ConfNodePath(), self.PlugType)
+
+ def PlugGenerate_C(self, buildpath, locations):
+ """
+ Generate C code
+ @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
+ @param locations: List of complete variables locations \
+ [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
+ "NAME" : name of the variable (generally "__IW0_1_2" style)
+ "DIR" : direction "Q","I" or "M"
+ "SIZE" : size "X", "B", "W", "D", "L"
+ "LOC" : tuple of interger for IEC location (0,1,2,...)
+ }, ...]
+ @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
+ """
+ current_location = self.GetCurrentLocation()
+ # define a unique name for the generated C file
+ location_str = "_".join(map(lambda x:str(x), current_location))
+
+ ctr = self.GetPlugRoot()
+ ctr.GetIECProgramsAndVariables()
+
+ plc_python_filepath = os.path.join(os.path.split(__file__)[0], "plc_python.c")
+ plc_python_file = open(plc_python_filepath, 'r')
+ plc_python_code = plc_python_file.read()
+ plc_python_file.close()
+ python_eval_fb_list = []
+ for v in ctr._VariablesList:
+ if v["vartype"] == "FB" and v["type"] in ["PYTHON_EVAL","PYTHON_POLL"]:
+ python_eval_fb_list.append(v)
+ python_eval_fb_count = max(1, len(python_eval_fb_list))
+
+ # prepare python code
+ plc_python_code = plc_python_code % {
+ "python_eval_fb_count": python_eval_fb_count,
+ "location": location_str}
+
+ Gen_Pythonfile_path = os.path.join(buildpath, "python_%s.c"%location_str)
+ pythonfile = open(Gen_Pythonfile_path,'w')
+ pythonfile.write(plc_python_code)
+ pythonfile.close()
+
+ runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
+ runtimefile = open(runtimefile_path, 'w')
+ runtimefile.write(self.GetPythonCode())
+ runtimefile.close()
+
+ matiec_flags = '"-I%s"'%os.path.abspath(self.GetPlugRoot().GetIECLibPath())
+
+ return [(Gen_Pythonfile_path, matiec_flags)], "", True, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb"))
diff -r 180e4a7d945c -r 1c23952dbde1 confnodes/python/python_xsd.xsd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/python_xsd.xsd Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+ Formatted text according to parts of XHTML 1.1
+
+
+
+
+
+
+
diff -r 180e4a7d945c -r 1c23952dbde1 connectors/LPC/LPCBootObject.py
--- a/connectors/LPC/LPCBootObject.py Thu May 03 19:02:34 2012 +0200
+++ b/connectors/LPC/LPCBootObject.py Mon May 07 18:47:29 2012 +0200
@@ -26,8 +26,8 @@
from LPCObject import *
class LPCBootObject(LPCObject):
- def __init__(self, pluginsroot, comportstr):
- LPCObject.__init__(self, pluginsroot, comportstr)
+ def __init__(self, confnodesroot, comportstr):
+ LPCObject.__init__(self, confnodesroot, comportstr)
self.successfully_transfered = False
def connect(self,comport):
diff -r 180e4a7d945c -r 1c23952dbde1 connectors/LPC/LPCObject.py
--- a/connectors/LPC/LPCObject.py Thu May 03 19:02:34 2012 +0200
+++ b/connectors/LPC/LPCObject.py Mon May 07 18:47:29 2012 +0200
@@ -27,16 +27,16 @@
class LPCObject():
- def __init__(self, pluginsroot, comportstr):
+ def __init__(self, confnodesroot, comportstr):
self.PLCStatus = "Disconnected"
- self.pluginsroot = pluginsroot
- self.PLCprint = pluginsroot.logger.writeyield
+ self.confnodesroot = confnodesroot
+ self.PLCprint = confnodesroot.logger.writeyield
self._Idxs = []
comport = int(comportstr[3:]) - 1
try:
self.connect(comportstr)
except Exception,e:
- self.pluginsroot.logger.write_error(str(e)+"\n")
+ self.confnodesroot.logger.write_error(str(e)+"\n")
self.SerialConnection = None
self.PLCStatus = "Disconnected"
@@ -46,14 +46,14 @@
self.PLCStatus, res = self.SerialConnection.HandleTransaction(transaction)
return res
except LPCProtoError,e:
- self.pluginsroot.logger.write(_("PLC disconnected\n"))
+ self.confnodesroot.logger.write(_("PLC disconnected\n"))
if self.SerialConnection is not None:
self.SerialConnection.close()
self.SerialConnection = None
self.PLCStatus = "Disconnected"
return None
except Exception,e:
- self.pluginsroot.logger.write_warning(str(e)+"\n")
+ self.confnodesroot.logger.write_warning(str(e)+"\n")
def StartPLC(self, debug=False):
raise LPCProtoError("Not implemented")
diff -r 180e4a7d945c -r 1c23952dbde1 connectors/LPC/__init__.py
--- a/connectors/LPC/__init__.py Thu May 03 19:02:34 2012 +0200
+++ b/connectors/LPC/__init__.py Mon May 07 18:47:29 2012 +0200
@@ -19,7 +19,7 @@
#License along with this library; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-def LPC_connector_factory(uri, pluginsroot):
+def LPC_connector_factory(uri, confnodesroot):
"""
This returns the connector to LPC style PLCobject
"""
@@ -27,9 +27,9 @@
mode,comportstr = location.split('/')
if mode=="APPLICATION":
from LPCAppObject import LPCAppObject
- return LPCAppObject(pluginsroot,comportstr)
+ return LPCAppObject(confnodesroot,comportstr)
elif mode=="BOOTLOADER":
from LPCBootObject import LPCBootObject
- return LPCBootObject(pluginsroot,comportstr)
+ return LPCBootObject(confnodesroot,comportstr)
diff -r 180e4a7d945c -r 1c23952dbde1 connectors/PYRO/__init__.py
--- a/connectors/PYRO/__init__.py Thu May 03 19:02:34 2012 +0200
+++ b/connectors/PYRO/__init__.py Mon May 07 18:47:29 2012 +0200
@@ -26,17 +26,17 @@
import copy
# this module attribute contains a list of DNS-SD (Zeroconf) service types
-# supported by this connector plugin.
+# supported by this connector confnode.
#
# for connectors that do not support DNS-SD, this attribute can be omitted
# or set to an empty list.
supported_dnssd_services = ["_PYRO._tcp.local."]
-def PYRO_connector_factory(uri, pluginsroot):
+def PYRO_connector_factory(uri, confnodesroot):
"""
This returns the connector to Pyro style PLCobject
"""
- pluginsroot.logger.write(_("Connecting to URI : %s\n")%uri)
+ confnodesroot.logger.write(_("Connecting to URI : %s\n")%uri)
servicetype, location = uri.split("://")
@@ -44,8 +44,8 @@
try :
RemotePLCObjectProxy = pyro.getAttrProxyForURI("PYROLOC://"+location+"/PLCObject")
except Exception, msg:
- pluginsroot.logger.write_error(_("Wrong URI, please check it !\n"))
- pluginsroot.logger.write_error(traceback.format_exc())
+ confnodesroot.logger.write_error(_("Wrong URI, please check it !\n"))
+ confnodesroot.logger.write_error(traceback.format_exc())
return None
def PyroCatcher(func, default=None):
@@ -59,21 +59,21 @@
except Pyro.errors.ProtocolError, e:
pass
except Pyro.errors.ConnectionClosedError, e:
- pluginsroot.logger.write_error("Connection lost!\n")
- pluginsroot._connector = None
+ confnodesroot.logger.write_error("Connection lost!\n")
+ confnodesroot._connector = None
except Exception,e:
- #pluginsroot.logger.write_error(traceback.format_exc())
+ #confnodesroot.logger.write_error(traceback.format_exc())
errmess = ''.join(Pyro.util.getPyroTraceback(e))
- pluginsroot.logger.write_error(errmess+"\n")
+ confnodesroot.logger.write_error(errmess+"\n")
print errmess
- pluginsroot._connector = None
+ confnodesroot._connector = None
return default
return catcher_func
# Check connection is effective.
# lambda is for getattr of GetPLCstatus to happen inside catcher
if PyroCatcher(lambda:RemotePLCObjectProxy.GetPLCstatus())() == None:
- pluginsroot.logger.write_error(_("Cannot get PLC status - connection failed.\n"))
+ confnodesroot.logger.write_error(_("Cannot get PLC status - connection failed.\n"))
return None
@@ -95,25 +95,25 @@
def _PyroStartPLC(self, *args, **kwargs):
"""
- pluginsroot._connector.GetPyroProxy() is used
+ confnodesroot._connector.GetPyroProxy() is used
rather than RemotePLCObjectProxy because
object is recreated meanwhile,
so we must not keep ref to it here
"""
- current_status = pluginsroot._connector.GetPyroProxy().GetPLCstatus()
+ current_status = confnodesroot._connector.GetPyroProxy().GetPLCstatus()
if current_status == "Dirty":
"""
Some bad libs with static symbols may polute PLC
ask runtime to suicide and come back again
"""
- pluginsroot.logger.write(_("Force runtime reload\n"))
- pluginsroot._connector.GetPyroProxy().ForceReload()
- pluginsroot._Disconnect()
+ confnodesroot.logger.write(_("Force runtime reload\n"))
+ confnodesroot._connector.GetPyroProxy().ForceReload()
+ confnodesroot._Disconnect()
# let remote PLC time to resurect.(freeze app)
sleep(0.5)
- pluginsroot._Connect()
- self.RemotePLCObjectProxyCopy = copy.copy(pluginsroot._connector.GetPyroProxy())
- return pluginsroot._connector.GetPyroProxy().StartPLC(*args, **kwargs)
+ confnodesroot._Connect()
+ self.RemotePLCObjectProxyCopy = copy.copy(confnodesroot._connector.GetPyroProxy())
+ return confnodesroot._connector.GetPyroProxy().StartPLC(*args, **kwargs)
StartPLC = PyroCatcher(_PyroStartPLC, False)
@@ -122,7 +122,7 @@
for safe use in from debug thread, must use the copy
"""
if self.RemotePLCObjectProxyCopy is None:
- self.RemotePLCObjectProxyCopy = copy.copy(pluginsroot._connector.GetPyroProxy())
+ self.RemotePLCObjectProxyCopy = copy.copy(confnodesroot._connector.GetPyroProxy())
return self.RemotePLCObjectProxyCopy.GetTraceVariables()
GetTraceVariables = PyroCatcher(_PyroGetTraceVariables,("Broken",None,None))
diff -r 180e4a7d945c -r 1c23952dbde1 connectors/__init__.py
--- a/connectors/__init__.py Thu May 03 19:02:34 2012 +0200
+++ b/connectors/__init__.py Mon May 07 18:47:29 2012 +0200
@@ -46,7 +46,7 @@
for st in new_module.supported_dnssd_services:
dnssd_connectors[st] = new_module
-def ConnectorFactory(uri, pluginsroot):
+def ConnectorFactory(uri, confnodesroot):
"""
Return a connector corresponding to the URI
or None if cannot connect to URI
@@ -56,12 +56,12 @@
# import module according to uri type
connectormodule = connector_modules[servicetype]
factoryname = servicetype + "_connector_factory"
- return getattr(connectormodule, factoryname)(uri, pluginsroot)
+ return getattr(connectormodule, factoryname)(uri, confnodesroot)
elif servicetype == "LOCAL":
- runtime_port = pluginsroot.AppFrame.StartLocalRuntime(taskbaricon=True)
+ runtime_port = confnodesroot.AppFrame.StartLocalRuntime(taskbaricon=True)
return PYRO.PYRO_connector_factory(
"PYRO://127.0.0.1:"+str(runtime_port),
- pluginsroot)
+ confnodesroot)
else :
return None
diff -r 180e4a7d945c -r 1c23952dbde1 plugger.py
--- a/plugger.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2063 +0,0 @@
-"""
-Base definitions for beremiz plugins
-"""
-
-import os,sys,traceback
-import time
-import plugins
-import types
-import shutil
-from xml.dom import minidom
-import wx
-
-#Quick hack to be able to find Beremiz IEC tools. Should be config params.
-base_folder = os.path.split(sys.path[0])[0]
-
-from xmlclass import GenerateClassesFromXSDstring
-from wxPopen import ProcessLogger
-
-from PLCControler import PLCControler, LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
-
-_BaseParamsClass = GenerateClassesFromXSDstring("""
-
-
-
-
-
-
-
-
- """)["BaseParams"]
-
-NameTypeSeparator = '@'
-
-class MiniTextControler:
-
- def __init__(self, filepath):
- self.FilePath = filepath
-
- def PlugFullName(self):
- return ""
-
- def SetEditedElementText(self, tagname, text):
- file = open(self.FilePath, "w")
- file.write(text)
- file.close()
-
- def GetEditedElementText(self, tagname, debug = False):
- if os.path.isfile(self.FilePath):
- file = open(self.FilePath, "r")
- text = file.read()
- file.close()
- return text
- return ""
-
- def GetEditedElementInterfaceVars(self, tagname, debug = False):
- return []
-
- def GetEditedElementType(self, tagname, debug = False):
- return "program"
-
- def GetBlockTypes(self, tagname = "", debug = False):
- return []
-
- def GetDataTypes(self, tagname = "", basetypes = True, only_locatables = False, debug = False):
- return []
-
- def GetEnumeratedDataValues(self, debug = False):
- return []
-
- def StartBuffering(self):
- pass
-
- def EndBuffering(self):
- pass
-
- def BufferProject(self):
- pass
-
-# helper func to get path to images
-def opjimg(imgname):
- return os.path.join(base_folder, "beremiz", "images",imgname)
-
-# helper func to check path write permission
-def CheckPathPerm(path):
- if path is None or not os.path.isdir(path):
- return False
- for root, dirs, files in os.walk(path):
- for name in files:
- if os.access(root, os.W_OK) is not True or os.access(os.path.join(root, name), os.W_OK) is not True:
- return False
- return True
-
-class PlugTemplate:
- """
- This class is the one that define plugins.
- """
-
- XSD = None
- PlugChildsTypes = []
- PlugMaxCount = None
- PluginMethods = []
- LibraryControler = None
- EditorType = None
-
- def _AddParamsMembers(self):
- self.PlugParams = None
- if self.XSD:
- self.Classes = GenerateClassesFromXSDstring(self.XSD)
- Classes = [(name, XSDclass) for name, XSDclass in self.Classes.items() if XSDclass.IsBaseClass]
- if len(Classes) == 1:
- name, XSDclass = Classes[0]
- obj = XSDclass()
- self.PlugParams = (name, obj)
- setattr(self, name, obj)
-
- def __init__(self):
- # Create BaseParam
- self.BaseParams = _BaseParamsClass()
- self.MandatoryParams = ("BaseParams", self.BaseParams)
- self._AddParamsMembers()
- self.PluggedChilds = {}
- self._View = None
- # copy PluginMethods so that it can be later customized
- self.PluginMethods = [dic.copy() for dic in self.PluginMethods]
- self.LoadSTLibrary()
-
- def PluginBaseXmlFilePath(self, PlugName=None):
- return os.path.join(self.PlugPath(PlugName), "baseplugin.xml")
-
- def PluginXmlFilePath(self, PlugName=None):
- return os.path.join(self.PlugPath(PlugName), "plugin.xml")
-
- def PluginLibraryFilePath(self):
- return os.path.join(self.PluginPath(), "pous.xml")
-
- def PluginPath(self):
- return os.path.join(self.PlugParent.PluginPath(), self.PlugType)
-
- def PlugPath(self,PlugName=None):
- if not PlugName:
- PlugName = self.PlugName()
- return os.path.join(self.PlugParent.PlugPath(),
- PlugName + NameTypeSeparator + self.PlugType)
-
- def PlugName(self):
- return self.BaseParams.getName()
-
- def PlugEnabled(self):
- return self.BaseParams.getEnabled()
-
- def PlugFullName(self):
- parent = self.PlugParent.PlugFullName()
- if parent != "":
- return parent + "." + self.PlugName()
- return self.BaseParams.getName()
-
- def GetIconPath(self, name):
- return opjimg(name)
-
- def PlugTestModified(self):
- return self.ChangesToSave
-
- def ProjectTestModified(self):
- """
- recursively check modified status
- """
- if self.PlugTestModified():
- return True
-
- for PlugChild in self.IterChilds():
- if PlugChild.ProjectTestModified():
- return True
-
- return False
-
- def RemoteExec(self, script, **kwargs):
- return self.PlugParent.RemoteExec(script, **kwargs)
-
- def OnPlugSave(self):
- #Default, do nothing and return success
- return True
-
- def GetParamsAttributes(self, path = None):
- if path:
- parts = path.split(".", 1)
- if self.MandatoryParams and parts[0] == self.MandatoryParams[0]:
- return self.MandatoryParams[1].getElementInfos(parts[0], parts[1])
- elif self.PlugParams and parts[0] == self.PlugParams[0]:
- return self.PlugParams[1].getElementInfos(parts[0], parts[1])
- else:
- params = []
- if wx.VERSION < (2, 8, 0) and self.MandatoryParams:
- params.append(self.MandatoryParams[1].getElementInfos(self.MandatoryParams[0]))
- if self.PlugParams:
- params.append(self.PlugParams[1].getElementInfos(self.PlugParams[0]))
- return params
-
- def SetParamsAttribute(self, path, value):
- self.ChangesToSave = True
- # Filter IEC_Channel and Name, that have specific behavior
- if path == "BaseParams.IEC_Channel":
- old_leading = ".".join(map(str, self.GetCurrentLocation()))
- new_value = self.FindNewIEC_Channel(value)
- new_leading = ".".join(map(str, self.PlugParent.GetCurrentLocation() + (new_value,)))
- self.GetPlugRoot().UpdateProjectVariableLocation(old_leading, new_leading)
- return new_value, True
- elif path == "BaseParams.Name":
- res = self.FindNewName(value)
- self.PlugRequestSave()
- return res, True
-
- parts = path.split(".", 1)
- if self.MandatoryParams and parts[0] == self.MandatoryParams[0]:
- self.MandatoryParams[1].setElementValue(parts[1], value)
- elif self.PlugParams and parts[0] == self.PlugParams[0]:
- self.PlugParams[1].setElementValue(parts[1], value)
- return value, False
-
- def PlugMakeDir(self):
- os.mkdir(self.PlugPath())
-
- def PlugRequestSave(self):
- if self.GetPlugRoot().CheckProjectPathPerm(False):
- # If plugin do not have corresponding directory
- plugpath = self.PlugPath()
- if not os.path.isdir(plugpath):
- # Create it
- os.mkdir(plugpath)
-
- # generate XML for base XML parameters controller of the plugin
- if self.MandatoryParams:
- BaseXMLFile = open(self.PluginBaseXmlFilePath(),'w')
- BaseXMLFile.write("\n")
- BaseXMLFile.write(self.MandatoryParams[1].generateXMLText(self.MandatoryParams[0], 0).encode("utf-8"))
- BaseXMLFile.close()
-
- # generate XML for XML parameters controller of the plugin
- if self.PlugParams:
- XMLFile = open(self.PluginXmlFilePath(),'w')
- XMLFile.write("\n")
- XMLFile.write(self.PlugParams[1].generateXMLText(self.PlugParams[0], 0).encode("utf-8"))
- XMLFile.close()
-
- # Call the plugin specific OnPlugSave method
- result = self.OnPlugSave()
- if not result:
- return _("Error while saving \"%s\"\n")%self.PlugPath()
-
- # mark plugin as saved
- self.ChangesToSave = False
- # go through all childs and do the same
- for PlugChild in self.IterChilds():
- result = PlugChild.PlugRequestSave()
- if result:
- return result
- return None
-
- def PlugImport(self, src_PlugPath):
- shutil.copytree(src_PlugPath, self.PlugPath)
- return True
-
- def PlugGenerate_C(self, buildpath, locations):
- """
- Generate C code
- @param locations: List of complete variables locations \
- [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
- "NAME" : name of the variable (generally "__IW0_1_2" style)
- "DIR" : direction "Q","I" or "M"
- "SIZE" : size "X", "B", "W", "D", "L"
- "LOC" : tuple of interger for IEC location (0,1,2,...)
- }, ...]
- @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
- """
- self.GetPlugRoot().logger.write_warning(".".join(map(lambda x:str(x), self.GetCurrentLocation())) + " -> Nothing to do\n")
- return [],"",False
-
- def _Generate_C(self, buildpath, locations):
- # Generate plugins [(Cfiles, CFLAGS)], LDFLAGS, DoCalls, extra_files
- # extra_files = [(fname,fobject), ...]
- gen_result = self.PlugGenerate_C(buildpath, locations)
- PlugCFilesAndCFLAGS, PlugLDFLAGS, DoCalls = gen_result[:3]
- extra_files = gen_result[3:]
- # if some files have been generated put them in the list with their location
- if PlugCFilesAndCFLAGS:
- LocationCFilesAndCFLAGS = [(self.GetCurrentLocation(), PlugCFilesAndCFLAGS, DoCalls)]
- else:
- LocationCFilesAndCFLAGS = []
-
- # plugin asks for some LDFLAGS
- if PlugLDFLAGS:
- # LDFLAGS can be either string
- if type(PlugLDFLAGS)==type(str()):
- LDFLAGS=[PlugLDFLAGS]
- #or list of strings
- elif type(PlugLDFLAGS)==type(list()):
- LDFLAGS=PlugLDFLAGS[:]
- else:
- LDFLAGS=[]
-
- # recurse through all childs, and stack their results
- for PlugChild in self.IECSortedChilds():
- new_location = PlugChild.GetCurrentLocation()
- # How deep are we in the tree ?
- depth=len(new_location)
- _LocationCFilesAndCFLAGS, _LDFLAGS, _extra_files = \
- PlugChild._Generate_C(
- #keep the same path
- buildpath,
- # filter locations that start with current IEC location
- [loc for loc in locations if loc["LOC"][0:depth] == new_location ])
- # stack the result
- LocationCFilesAndCFLAGS += _LocationCFilesAndCFLAGS
- LDFLAGS += _LDFLAGS
- extra_files += _extra_files
-
- return LocationCFilesAndCFLAGS, LDFLAGS, extra_files
-
- def PluginTypesFactory(self):
- if self.LibraryControler is not None:
- return [{"name" : self.PlugType, "types": self.LibraryControler.Project}]
- return []
-
- def ParentsTypesFactory(self):
- return self.PlugParent.ParentsTypesFactory() + self.PluginTypesFactory()
-
- def PluginsTypesFactory(self):
- list = self.PluginTypesFactory()
- for PlugChild in self.IterChilds():
- list += PlugChild.PluginsTypesFactory()
- return list
-
- def STLibraryFactory(self):
- if self.LibraryControler is not None:
- program, errors, warnings = self.LibraryControler.GenerateProgram()
- return program + "\n"
- return ""
-
- def PluginsSTLibraryFactory(self):
- program = self.STLibraryFactory()
- for PlugChild in self.IECSortedChilds():
- program += PlugChild.PluginsSTLibraryFactory()
- return program
-
- def IterChilds(self):
- for PlugType, PluggedChilds in self.PluggedChilds.items():
- for PlugInstance in PluggedChilds:
- yield PlugInstance
-
- def IECSortedChilds(self):
- # reorder childs by IEC_channels
- ordered = [(chld.BaseParams.getIEC_Channel(),chld) for chld in self.IterChilds()]
- if ordered:
- ordered.sort()
- return zip(*ordered)[1]
- else:
- return []
-
- def _GetChildBySomething(self, something, toks):
- for PlugInstance in self.IterChilds():
- # if match component of the name
- if getattr(PlugInstance.BaseParams, something) == toks[0]:
- # if Name have other components
- if len(toks) >= 2:
- # Recurse in order to find the latest object
- return PlugInstance._GetChildBySomething( something, toks[1:])
- # No sub name -> found
- return PlugInstance
- # Not found
- return None
-
- def GetChildByName(self, Name):
- if Name:
- toks = Name.split('.')
- return self._GetChildBySomething("Name", toks)
- else:
- return self
-
- def GetChildByIECLocation(self, Location):
- if Location:
- return self._GetChildBySomething("IEC_Channel", Location)
- else:
- return self
-
- def GetCurrentLocation(self):
- """
- @return: Tupple containing plugin IEC location of current plugin : %I0.0.4.5 => (0,0,4,5)
- """
- return self.PlugParent.GetCurrentLocation() + (self.BaseParams.getIEC_Channel(),)
-
- def GetCurrentName(self):
- """
- @return: String "ParentParentName.ParentName.Name"
- """
- return self.PlugParent._GetCurrentName() + self.BaseParams.getName()
-
- def _GetCurrentName(self):
- """
- @return: String "ParentParentName.ParentName.Name."
- """
- return self.PlugParent._GetCurrentName() + self.BaseParams.getName() + "."
-
- def GetPlugRoot(self):
- return self.PlugParent.GetPlugRoot()
-
- def GetFullIEC_Channel(self):
- return ".".join([str(i) for i in self.GetCurrentLocation()]) + ".x"
-
- def GetLocations(self):
- location = self.GetCurrentLocation()
- return [loc for loc in self.PlugParent.GetLocations() if loc["LOC"][0:len(location)] == location]
-
- def GetVariableLocationTree(self):
- '''
- This function is meant to be overridden by plugins.
-
- It should returns an list of dictionaries
-
- - IEC_type is an IEC type like BOOL/BYTE/SINT/...
- - location is a string of this variable's location, like "%IX0.0.0"
- '''
- children = []
- for child in self.IECSortedChilds():
- children.append(child.GetVariableLocationTree())
- return {"name": self.BaseParams.getName(),
- "type": LOCATION_PLUGIN,
- "location": self.GetFullIEC_Channel(),
- "children": children}
-
- def FindNewName(self, DesiredName):
- """
- Changes Name to DesiredName if available, Name-N if not.
- @param DesiredName: The desired Name (string)
- """
- # Get Current Name
- CurrentName = self.BaseParams.getName()
- # Do nothing if no change
- #if CurrentName == DesiredName: return CurrentName
- # Build a list of used Name out of parent's PluggedChilds
- AllNames=[]
- for PlugInstance in self.PlugParent.IterChilds():
- if PlugInstance != self:
- AllNames.append(PlugInstance.BaseParams.getName())
-
- # Find a free name, eventually appending digit
- res = DesiredName
- suffix = 1
- while res in AllNames:
- res = "%s-%d"%(DesiredName, suffix)
- suffix += 1
-
- # Get old path
- oldname = self.PlugPath()
- # Check previous plugin existance
- dontexist = self.BaseParams.getName() == "__unnamed__"
- # Set the new name
- self.BaseParams.setName(res)
- # Rename plugin dir if exist
- if not dontexist:
- shutil.move(oldname, self.PlugPath())
- # warn user he has two left hands
- if DesiredName != res:
- self.GetPlugRoot().logger.write_warning(_("A child names \"%s\" already exist -> \"%s\"\n")%(DesiredName,res))
- return res
-
- def GetAllChannels(self):
- AllChannels=[]
- for PlugInstance in self.PlugParent.IterChilds():
- if PlugInstance != self:
- AllChannels.append(PlugInstance.BaseParams.getIEC_Channel())
- AllChannels.sort()
- return AllChannels
-
- def FindNewIEC_Channel(self, DesiredChannel):
- """
- Changes IEC Channel number to DesiredChannel if available, nearest available if not.
- @param DesiredChannel: The desired IEC channel (int)
- """
- # Get Current IEC channel
- CurrentChannel = self.BaseParams.getIEC_Channel()
- # Do nothing if no change
- #if CurrentChannel == DesiredChannel: return CurrentChannel
- # Build a list of used Channels out of parent's PluggedChilds
- AllChannels = self.GetAllChannels()
-
- # Now, try to guess the nearest available channel
- res = DesiredChannel
- while res in AllChannels: # While channel not free
- if res < CurrentChannel: # Want to go down ?
- res -= 1 # Test for n-1
- if res < 0 :
- self.GetPlugRoot().logger.write_warning(_("Cannot find lower free IEC channel than %d\n")%CurrentChannel)
- return CurrentChannel # Can't go bellow 0, do nothing
- else : # Want to go up ?
- res += 1 # Test for n-1
- # Finally set IEC Channel
- self.BaseParams.setIEC_Channel(res)
- return res
-
- def _OpenView(self, name=None):
- if self.EditorType is not None and self._View is None:
- app_frame = self.GetPlugRoot().AppFrame
-
- self._View = self.EditorType(app_frame.TabsOpened, self, app_frame)
-
- app_frame.EditProjectElement(self._View, self.PlugName())
-
- return self._View
- return None
-
- def OnCloseEditor(self, view):
- if self._View == view:
- self._View = None
-
- def OnPlugClose(self):
- if self._View is not None:
- app_frame = self.GetPlugRoot().AppFrame
- if app_frame is not None:
- app_frame.DeletePage(self._View)
- return True
-
- def _doRemoveChild(self, PlugInstance):
- # Remove all childs of child
- for SubPlugInstance in PlugInstance.IterChilds():
- PlugInstance._doRemoveChild(SubPlugInstance)
- # Call the OnCloseMethod
- PlugInstance.OnPlugClose()
- # Delete plugin dir
- shutil.rmtree(PlugInstance.PlugPath())
- # Remove child of PluggedChilds
- self.PluggedChilds[PlugInstance.PlugType].remove(PlugInstance)
- # Forget it... (View have to refresh)
-
- def PlugRemove(self):
- # Fetch the plugin
- #PlugInstance = self.GetChildByName(PlugName)
- # Ask to his parent to remove it
- self.PlugParent._doRemoveChild(self)
-
- def PlugAddChild(self, PlugName, PlugType, IEC_Channel=0):
- """
- Create the plugins that may be added as child to this node self
- @param PlugType: string desining the plugin class name (get name from PlugChildsTypes)
- @param PlugName: string for the name of the plugin instance
- """
- # reorgabize self.PlugChildsTypes tuples from (name, PlugClass, Help)
- # to ( name, (PlugClass, Help)), an make a dict
- transpose = zip(*self.PlugChildsTypes)
- PlugChildsTypes = dict(zip(transpose[0],zip(transpose[1],transpose[2])))
- # Check that adding this plugin is allowed
- try:
- PlugClass, PlugHelp = PlugChildsTypes[PlugType]
- except KeyError:
- raise Exception, _("Cannot create child %s of type %s ")%(PlugName, PlugType)
-
- # if PlugClass is a class factory, call it. (prevent unneeded imports)
- if type(PlugClass) == types.FunctionType:
- PlugClass = PlugClass()
-
- # Eventualy Initialize child instance list for this class of plugin
- PluggedChildsWithSameClass = self.PluggedChilds.setdefault(PlugType, list())
- # Check count
- if getattr(PlugClass, "PlugMaxCount", None) and len(PluggedChildsWithSameClass) >= PlugClass.PlugMaxCount:
- raise Exception, _("Max count (%d) reached for this plugin of type %s ")%(PlugClass.PlugMaxCount, PlugType)
-
- # create the final class, derived of provided plugin and template
- class FinalPlugClass(PlugClass, PlugTemplate):
- """
- Plugin class is derivated into FinalPlugClass before being instanciated
- This way __init__ is overloaded to ensure PlugTemplate.__init__ is called
- before PlugClass.__init__, and to do the file related stuff.
- """
- def __init__(_self):
- # self is the parent
- _self.PlugParent = self
- # Keep track of the plugin type name
- _self.PlugType = PlugType
- # remind the help string, for more fancy display
- _self.PlugHelp = PlugHelp
- # Call the base plugin template init - change XSD into class members
- PlugTemplate.__init__(_self)
- # check name is unique
- NewPlugName = _self.FindNewName(PlugName)
- # If dir have already be made, and file exist
- if os.path.isdir(_self.PlugPath(NewPlugName)): #and os.path.isfile(_self.PluginXmlFilePath(PlugName)):
- #Load the plugin.xml file into parameters members
- _self.LoadXMLParams(NewPlugName)
- # Basic check. Better to fail immediately.
- if (_self.BaseParams.getName() != NewPlugName):
- raise Exception, _("Project tree layout do not match plugin.xml %s!=%s ")%(NewPlugName, _self.BaseParams.getName())
-
- # Now, self.PlugPath() should be OK
-
- # Check that IEC_Channel is not already in use.
- _self.FindNewIEC_Channel(_self.BaseParams.getIEC_Channel())
- # Call the plugin real __init__
- if getattr(PlugClass, "__init__", None):
- PlugClass.__init__(_self)
- #Load and init all the childs
- _self.LoadChilds()
- #just loaded, nothing to saved
- _self.ChangesToSave = False
- else:
- # If plugin do not have corresponding file/dirs - they will be created on Save
- _self.PlugMakeDir()
- # Find an IEC number
- _self.FindNewIEC_Channel(IEC_Channel)
- # Call the plugin real __init__
- if getattr(PlugClass, "__init__", None):
- PlugClass.__init__(_self)
- _self.PlugRequestSave()
- #just created, must be saved
- _self.ChangesToSave = True
-
- def _getBuildPath(_self):
- return self._getBuildPath()
-
- # Create the object out of the resulting class
- newPluginOpj = FinalPlugClass()
- # Store it in PluggedChils
- PluggedChildsWithSameClass.append(newPluginOpj)
-
- return newPluginOpj
-
- def ClearPluggedChilds(self):
- for child in self.IterChilds():
- child.ClearPluggedChilds()
- self.PluggedChilds = {}
-
- def LoadSTLibrary(self):
- # Get library blocks if plcopen library exist
- library_path = self.PluginLibraryFilePath()
- if os.path.isfile(library_path):
- self.LibraryControler = PLCControler()
- self.LibraryControler.OpenXMLFile(library_path)
- self.LibraryControler.ClearPluginTypes()
- self.LibraryControler.AddPluginTypesList(self.ParentsTypesFactory())
-
- def LoadXMLParams(self, PlugName = None):
- methode_name = os.path.join(self.PlugPath(PlugName), "methods.py")
- if os.path.isfile(methode_name):
- execfile(methode_name)
-
- # Get the base xml tree
- if self.MandatoryParams:
- try:
- basexmlfile = open(self.PluginBaseXmlFilePath(PlugName), 'r')
- basetree = minidom.parse(basexmlfile)
- self.MandatoryParams[1].loadXMLTree(basetree.childNodes[0])
- basexmlfile.close()
- except Exception, exc:
- self.GetPlugRoot().logger.write_error(_("Couldn't load plugin base parameters %s :\n %s") % (PlugName, str(exc)))
- self.GetPlugRoot().logger.write_error(traceback.format_exc())
-
- # Get the xml tree
- if self.PlugParams:
- try:
- xmlfile = open(self.PluginXmlFilePath(PlugName), 'r')
- tree = minidom.parse(xmlfile)
- self.PlugParams[1].loadXMLTree(tree.childNodes[0])
- xmlfile.close()
- except Exception, exc:
- self.GetPlugRoot().logger.write_error(_("Couldn't load plugin parameters %s :\n %s") % (PlugName, str(exc)))
- self.GetPlugRoot().logger.write_error(traceback.format_exc())
-
- def LoadChilds(self):
- # Iterate over all PlugName@PlugType in plugin directory, and try to open them
- for PlugDir in os.listdir(self.PlugPath()):
- if os.path.isdir(os.path.join(self.PlugPath(), PlugDir)) and \
- PlugDir.count(NameTypeSeparator) == 1:
- pname, ptype = PlugDir.split(NameTypeSeparator)
- try:
- self.PlugAddChild(pname, ptype)
- except Exception, exc:
- self.GetPlugRoot().logger.write_error(_("Could not add child \"%s\", type %s :\n%s\n")%(pname, ptype, str(exc)))
- self.GetPlugRoot().logger.write_error(traceback.format_exc())
-
- def EnableMethod(self, method, value):
- for d in self.PluginMethods:
- if d["method"]==method:
- d["enabled"]=value
- return True
- return False
-
- def ShowMethod(self, method, value):
- for d in self.PluginMethods:
- if d["method"]==method:
- d["shown"]=value
- return True
- return False
-
- def CallMethod(self, method):
- for d in self.PluginMethods:
- if d["method"]==method and d.get("enabled", True) and d.get("shown", True):
- getattr(self, method)()
-
-def _GetClassFunction(name):
- def GetRootClass():
- return getattr(__import__("plugins." + name), name).RootClass
- return GetRootClass
-
-
-####################################################################################
-####################################################################################
-####################################################################################
-################################### ROOT ######################################
-####################################################################################
-####################################################################################
-####################################################################################
-
-if wx.Platform == '__WXMSW__':
- exe_ext=".exe"
-else:
- exe_ext=""
-
-# import for project creation timestamping
-from threading import Timer, Lock, Thread, Semaphore
-from time import localtime
-from datetime import datetime
-# import necessary stuff from PLCOpenEditor
-from PLCOpenEditor import PLCOpenEditor, ProjectDialog
-from TextViewer import TextViewer
-from plcopen.structures import IEC_KEYWORDS, TypeHierarchy_list
-
-
-import re, tempfile
-import targets
-from targets.typemapping import DebugTypesSize
-
-import connectors
-from discovery import DiscoveryDialog
-from weakref import WeakKeyDictionary
-
-MATIEC_ERROR_MODEL = re.compile(".*\.st:(\d+)-(\d+)\.\.(\d+)-(\d+): error : (.*)$")
-
-DEBUG_RETRIES_WARN = 3
-DEBUG_RETRIES_REREGISTER = 4
-
-class PluginsRoot(PlugTemplate, PLCControler):
- """
- This class define Root object of the plugin tree.
- It is responsible of :
- - Managing project directory
- - Building project
- - Handling PLCOpenEditor controler and view
- - Loading user plugins and instanciante them as childs
- - ...
-
- """
-
- # For root object, available Childs Types are modules of the plugin packages.
- PlugChildsTypes = [(name, _GetClassFunction(name), help) for name, help in zip(plugins.__all__,plugins.helps)]
-
- XSD = """
-
-
-
-
-
-
-
- """+targets.targetchoices+"""
-
-
-
-
-
-
-
-
-
- """
-
- def __init__(self, frame, logger):
- PLCControler.__init__(self)
-
- self.MandatoryParams = None
- self.SetAppFrame(frame, logger)
- self._builder = None
- self._connector = None
-
- self.iec2c_path = os.path.join(base_folder, "matiec", "iec2c"+exe_ext)
- self.ieclib_path = os.path.join(base_folder, "matiec", "lib")
-
- # Setup debug information
- self.IECdebug_datas = {}
- self.IECdebug_lock = Lock()
-
- self.DebugTimer=None
- self.ResetIECProgramsAndVariables()
-
- #This method are not called here... but in NewProject and OpenProject
- #self._AddParamsMembers()
- #self.PluggedChilds = {}
-
- # In both new or load scenario, no need to save
- self.ChangesToSave = False
- # root have no parent
- self.PlugParent = None
- # Keep track of the plugin type name
- self.PlugType = "Beremiz"
- self.PluggedChilds = {}
- # After __init__ root plugin is not valid
- self.ProjectPath = None
- self._setBuildPath(None)
- self.DebugThread = None
- self.debug_break = False
- self.previous_plcstate = None
- # copy PluginMethods so that it can be later customized
- self.PluginMethods = [dic.copy() for dic in self.PluginMethods]
- self.LoadSTLibrary()
-
- def __del__(self):
- if self.DebugTimer:
- self.DebugTimer.cancel()
- self.KillDebugThread()
-
- def SetAppFrame(self, frame, logger):
- self.AppFrame = frame
- self.logger = logger
- self.StatusTimer = None
-
- if frame is not None:
- # Timer to pull PLC status
- ID_STATUSTIMER = wx.NewId()
- self.StatusTimer = wx.Timer(self.AppFrame, ID_STATUSTIMER)
- self.AppFrame.Bind(wx.EVT_TIMER, self.PullPLCStatusProc, self.StatusTimer)
-
- self.RefreshPluginsBlockLists()
-
- def ResetAppFrame(self, logger):
- if self.AppFrame is not None:
- self.AppFrame.Unbind(wx.EVT_TIMER, self.StatusTimer)
- self.StatusTimer = None
- self.AppFrame = None
-
- self.logger = logger
-
- def PluginLibraryFilePath(self):
- return os.path.join(os.path.split(__file__)[0], "pous.xml")
-
- def PlugTestModified(self):
- return self.ChangesToSave or not self.ProjectIsSaved()
-
- def PlugFullName(self):
- return ""
-
- def GetPlugRoot(self):
- return self
-
- def GetIECLibPath(self):
- return self.ieclib_path
-
- def GetIEC2cPath(self):
- return self.iec2c_path
-
- def GetCurrentLocation(self):
- return ()
-
- def GetCurrentName(self):
- return ""
-
- def _GetCurrentName(self):
- return ""
-
- def GetProjectPath(self):
- return self.ProjectPath
-
- def GetProjectName(self):
- return os.path.split(self.ProjectPath)[1]
-
- def GetDefaultTargetName(self):
- if wx.Platform == '__WXMSW__':
- return "Win32"
- else:
- return "Linux"
-
- def GetTarget(self):
- target = self.BeremizRoot.getTargetType()
- if target.getcontent() is None:
- target = self.Classes["BeremizRoot_TargetType"]()
- target_name = self.GetDefaultTargetName()
- target.setcontent({"name": target_name, "value": self.Classes["TargetType_%s"%target_name]()})
- return target
-
- def GetParamsAttributes(self, path = None):
- params = PlugTemplate.GetParamsAttributes(self, path)
- if params[0]["name"] == "BeremizRoot":
- for child in params[0]["children"]:
- if child["name"] == "TargetType" and child["value"] == '':
- child.update(self.GetTarget().getElementInfos("TargetType"))
- return params
-
- def SetParamsAttribute(self, path, value):
- if path.startswith("BeremizRoot.TargetType.") and self.BeremizRoot.getTargetType().getcontent() is None:
- self.BeremizRoot.setTargetType(self.GetTarget())
- return PlugTemplate.SetParamsAttribute(self, path, value)
-
- # helper func to check project path write permission
- def CheckProjectPathPerm(self, dosave=True):
- if CheckPathPerm(self.ProjectPath):
- return True
- dialog = wx.MessageDialog(self.AppFrame,
- _('You must have permission to work on the project\nWork on a project copy ?'),
- _('Error'),
- wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
- answer = dialog.ShowModal()
- dialog.Destroy()
- if answer == wx.ID_YES:
- if self.SaveProjectAs():
- self.AppFrame.RefreshAll()
- self.AppFrame.RefreshTitle()
- self.AppFrame.RefreshFileMenu()
- return True
- return False
-
- def NewProject(self, ProjectPath, BuildPath=None):
- """
- Create a new project in an empty folder
- @param ProjectPath: path of the folder where project have to be created
- @param PLCParams: properties of the PLCOpen program created
- """
- # Verify that chosen folder is empty
- if not os.path.isdir(ProjectPath) or len(os.listdir(ProjectPath)) > 0:
- return _("Chosen folder isn't empty. You can't use it for a new project!")
-
- dialog = ProjectDialog(self.AppFrame)
- if dialog.ShowModal() == wx.ID_OK:
- values = dialog.GetValues()
- values["creationDateTime"] = datetime(*localtime()[:6])
- dialog.Destroy()
- else:
- dialog.Destroy()
- return _("Project not created")
-
- # Create PLCOpen program
- self.CreateNewProject(values)
- # Change XSD into class members
- self._AddParamsMembers()
- self.PluggedChilds = {}
- # Keep track of the root plugin (i.e. project path)
- self.ProjectPath = ProjectPath
- self._setBuildPath(BuildPath)
- # get plugins bloclist (is that usefull at project creation?)
- self.RefreshPluginsBlockLists()
- # this will create files base XML files
- self.SaveProject()
- return None
-
- def LoadProject(self, ProjectPath, BuildPath=None):
- """
- Load a project contained in a folder
- @param ProjectPath: path of the project folder
- """
- if os.path.basename(ProjectPath) == "":
- ProjectPath = os.path.dirname(ProjectPath)
- # Verify that project contains a PLCOpen program
- plc_file = os.path.join(ProjectPath, "plc.xml")
- if not os.path.isfile(plc_file):
- return _("Chosen folder doesn't contain a program. It's not a valid project!")
- # Load PLCOpen file
- result = self.OpenXMLFile(plc_file)
- if result:
- return result
- # Change XSD into class members
- self._AddParamsMembers()
- self.PluggedChilds = {}
- # Keep track of the root plugin (i.e. project path)
- self.ProjectPath = ProjectPath
- self._setBuildPath(BuildPath)
- # If dir have already be made, and file exist
- if os.path.isdir(self.PlugPath()) and os.path.isfile(self.PluginXmlFilePath()):
- #Load the plugin.xml file into parameters members
- result = self.LoadXMLParams()
- if result:
- return result
- #Load and init all the childs
- self.LoadChilds()
- self.RefreshPluginsBlockLists()
-
- if os.path.exists(self._getBuildPath()):
- self.EnableMethod("_Clean", True)
-
- if os.path.isfile(self._getIECrawcodepath()):
- self.ShowMethod("_showIECcode", True)
-
- return None
-
- def CloseProject(self):
- self.ClearPluggedChilds()
- self.ResetAppFrame(None)
-
- def SaveProject(self):
- if self.CheckProjectPathPerm(False):
- self.SaveXMLFile(os.path.join(self.ProjectPath, 'plc.xml'))
- result = self.PlugRequestSave()
- if result:
- self.logger.write_error(result)
-
- def SaveProjectAs(self, dosave=True):
- # Ask user to choose a path with write permissions
- if wx.Platform == '__WXMSW__':
- path = os.getenv("USERPROFILE")
- else:
- path = os.getenv("HOME")
- dirdialog = wx.DirDialog(self.AppFrame , _("Choose a directory to save project"), path, wx.DD_NEW_DIR_BUTTON)
- answer = dirdialog.ShowModal()
- dirdialog.Destroy()
- if answer == wx.ID_OK:
- newprojectpath = dirdialog.GetPath()
- if os.path.isdir(newprojectpath):
- self.ProjectPath = newprojectpath
- if dosave:
- self.SaveProject()
- self._setBuildPath(self.BuildPath)
- return True
- return False
-
- # Update PLCOpenEditor Plugin Block types from loaded plugins
- def RefreshPluginsBlockLists(self):
- if getattr(self, "PluggedChilds", None) is not None:
- self.ClearPluginTypes()
- self.AddPluginTypesList(self.PluginsTypesFactory())
- if self.AppFrame is not None:
- self.AppFrame.RefreshLibraryPanel()
- self.AppFrame.RefreshEditor()
-
- # Update a PLCOpenEditor Pou variable location
- def UpdateProjectVariableLocation(self, old_leading, new_leading):
- self.Project.updateElementAddress(old_leading, new_leading)
- self.BufferProject()
- if self.AppFrame is not None:
- self.AppFrame.RefreshTitle()
- self.AppFrame.RefreshInstancesTree()
- self.AppFrame.RefreshFileMenu()
- self.AppFrame.RefreshEditMenu()
- self.AppFrame.RefreshEditor()
-
- def GetVariableLocationTree(self):
- '''
- This function is meant to be overridden by plugins.
-
- It should returns an list of dictionaries
-
- - IEC_type is an IEC type like BOOL/BYTE/SINT/...
- - location is a string of this variable's location, like "%IX0.0.0"
- '''
- children = []
- for child in self.IECSortedChilds():
- children.append(child.GetVariableLocationTree())
- return children
-
- def PluginPath(self):
- return os.path.join(os.path.split(__file__)[0], "plugins")
-
- def PlugPath(self, PlugName=None):
- return self.ProjectPath
-
- def PluginXmlFilePath(self, PlugName=None):
- return os.path.join(self.PlugPath(PlugName), "beremiz.xml")
-
- def ParentsTypesFactory(self):
- return self.PluginTypesFactory()
-
- def _setBuildPath(self, buildpath):
- if CheckPathPerm(buildpath):
- self.BuildPath = buildpath
- else:
- self.BuildPath = None
- self.BuildPath = buildpath
- self.DefaultBuildPath = None
- if self._builder is not None:
- self._builder.SetBuildPath(self._getBuildPath())
-
- def _getBuildPath(self):
- # BuildPath is defined by user
- if self.BuildPath is not None:
- return self.BuildPath
- # BuildPath isn't defined by user but already created by default
- if self.DefaultBuildPath is not None:
- return self.DefaultBuildPath
- # Create a build path in project folder if user has permissions
- if CheckPathPerm(self.ProjectPath):
- self.DefaultBuildPath = os.path.join(self.ProjectPath, "build")
- # Create a build path in temp folder
- else:
- self.DefaultBuildPath = os.path.join(tempfile.mkdtemp(), os.path.basename(self.ProjectPath), "build")
-
- if not os.path.exists(self.DefaultBuildPath):
- os.makedirs(self.DefaultBuildPath)
- return self.DefaultBuildPath
-
- def _getExtraFilesPath(self):
- return os.path.join(self._getBuildPath(), "extra_files")
-
- def _getIECcodepath(self):
- # define name for IEC code file
- return os.path.join(self._getBuildPath(), "plc.st")
-
- def _getIECgeneratedcodepath(self):
- # define name for IEC generated code file
- return os.path.join(self._getBuildPath(), "generated_plc.st")
-
- def _getIECrawcodepath(self):
- # define name for IEC raw code file
- return os.path.join(self.PlugPath(), "raw_plc.st")
-
- def GetLocations(self):
- locations = []
- filepath = os.path.join(self._getBuildPath(),"LOCATED_VARIABLES.h")
- if os.path.isfile(filepath):
- # IEC2C compiler generate a list of located variables : LOCATED_VARIABLES.h
- location_file = open(os.path.join(self._getBuildPath(),"LOCATED_VARIABLES.h"))
- # each line of LOCATED_VARIABLES.h declares a located variable
- lines = [line.strip() for line in location_file.readlines()]
- # This regular expression parses the lines genereated by IEC2C
- LOCATED_MODEL = re.compile("__LOCATED_VAR\((?P[A-Z]*),(?P[_A-Za-z0-9]*),(?P[QMI])(?:,(?P[XBWDL]))?,(?P[,0-9]*)\)")
- for line in lines:
- # If line match RE,
- result = LOCATED_MODEL.match(line)
- if result:
- # Get the resulting dict
- resdict = result.groupdict()
- # rewrite string for variadic location as a tuple of integers
- resdict['LOC'] = tuple(map(int,resdict['LOC'].split(',')))
- # set located size to 'X' if not given
- if not resdict['SIZE']:
- resdict['SIZE'] = 'X'
- # finally store into located variable list
- locations.append(resdict)
- return locations
-
- def _Generate_SoftPLC(self):
- """
- Generate SoftPLC ST/IL/SFC code out of PLCOpenEditor controller, and compile it with IEC2C
- @param buildpath: path where files should be created
- """
-
- # Update PLCOpenEditor Plugin Block types before generate ST code
- self.RefreshPluginsBlockLists()
-
- self.logger.write(_("Generating SoftPLC IEC-61131 ST/IL/SFC code...\n"))
- buildpath = self._getBuildPath()
- # ask PLCOpenEditor controller to write ST/IL/SFC code file
- program, errors, warnings = self.GenerateProgram(self._getIECgeneratedcodepath())
- if len(warnings) > 0:
- self.logger.write_warning(_("Warnings in ST/IL/SFC code generator :\n"))
- for warning in warnings:
- self.logger.write_warning("%s\n"%warning)
- if len(errors) > 0:
- # Failed !
- self.logger.write_error(_("Error in ST/IL/SFC code generator :\n%s\n")%errors[0])
- return False
- plc_file = open(self._getIECcodepath(), "w")
- # Add ST Library from plugins
- plc_file.write(self.PluginsSTLibraryFactory())
- if os.path.isfile(self._getIECrawcodepath()):
- plc_file.write(open(self._getIECrawcodepath(), "r").read())
- plc_file.write("\n")
- plc_file.close()
- plc_file = open(self._getIECcodepath(), "r")
- self.ProgramOffset = 0
- for line in plc_file.xreadlines():
- self.ProgramOffset += 1
- plc_file.close()
- plc_file = open(self._getIECcodepath(), "a")
- plc_file.write(open(self._getIECgeneratedcodepath(), "r").read())
- plc_file.close()
-
- self.logger.write(_("Compiling IEC Program into C code...\n"))
-
- # Now compile IEC code into many C files
- # files are listed to stdout, and errors to stderr.
- status, result, err_result = ProcessLogger(
- self.logger,
- "\"%s\" -f -I \"%s\" -T \"%s\" \"%s\""%(
- self.iec2c_path,
- self.ieclib_path,
- buildpath,
- self._getIECcodepath()),
- no_stdout=True, no_stderr=True).spin()
- if status:
- # Failed !
-
- # parse iec2c's error message. if it contains a line number,
- # then print those lines from the generated IEC file.
- for err_line in err_result.split('\n'):
- self.logger.write_warning(err_line + "\n")
-
- m_result = MATIEC_ERROR_MODEL.match(err_line)
- if m_result is not None:
- first_line, first_column, last_line, last_column, error = m_result.groups()
- first_line, last_line = int(first_line), int(last_line)
-
- last_section = None
- f = open(self._getIECcodepath())
-
- for i, line in enumerate(f.readlines()):
- i = i + 1
- if line[0] not in '\t \r\n':
- last_section = line
-
- if first_line <= i <= last_line:
- if last_section is not None:
- self.logger.write_warning("In section: " + last_section)
- last_section = None # only write section once
- self.logger.write_warning("%04d: %s" % (i, line))
-
- f.close()
-
- self.logger.write_error(_("Error : IEC to C compiler returned %d\n")%status)
- return False
-
- # Now extract C files of stdout
- C_files = [ fname for fname in result.splitlines() if fname[-2:]==".c" or fname[-2:]==".C" ]
- # remove those that are not to be compiled because included by others
- C_files.remove("POUS.c")
- if not C_files:
- self.logger.write_error(_("Error : At least one configuration and one resource must be declared in PLC !\n"))
- return False
- # transform those base names to full names with path
- C_files = map(lambda filename:os.path.join(buildpath, filename), C_files)
- self.logger.write(_("Extracting Located Variables...\n"))
- # Keep track of generated located variables for later use by self._Generate_C
- self.PLCGeneratedLocatedVars = self.GetLocations()
- # Keep track of generated C files for later use by self.PlugGenerate_C
- self.PLCGeneratedCFiles = C_files
- # compute CFLAGS for plc
- self.plcCFLAGS = "\"-I"+self.ieclib_path+"\""
- return True
-
- def GetBuilder(self):
- """
- Return a Builder (compile C code into machine code)
- """
- # Get target, module and class name
- targetname = self.GetTarget().getcontent()["name"]
- modulename = "targets." + targetname
- classname = targetname + "_target"
-
- # Get module reference
- try :
- targetmodule = getattr(__import__(modulename), targetname)
-
- except Exception, msg:
- self.logger.write_error(_("Can't find module for target %s!\n")%targetname)
- self.logger.write_error(str(msg))
- return None
-
- # Get target class
- targetclass = getattr(targetmodule, classname)
-
- # if target already
- if self._builder is None or not isinstance(self._builder,targetclass):
- # Get classname instance
- self._builder = targetclass(self)
- return self._builder
-
- def ResetBuildMD5(self):
- builder=self.GetBuilder()
- if builder is not None:
- builder.ResetBinaryCodeMD5()
- self.EnableMethod("_Transfer", False)
-
- def GetLastBuildMD5(self):
- builder=self.GetBuilder()
- if builder is not None:
- return builder.GetBinaryCodeMD5()
- else:
- return None
-
- #######################################################################
- #
- # C CODE GENERATION METHODS
- #
- #######################################################################
-
- def PlugGenerate_C(self, buildpath, locations):
- """
- Return C code generated by iec2c compiler
- when _generate_softPLC have been called
- @param locations: ignored
- @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
- """
-
- return ([(C_file_name, self.plcCFLAGS)
- for C_file_name in self.PLCGeneratedCFiles ],
- "", # no ldflags
- False) # do not expose retreive/publish calls
-
- def ResetIECProgramsAndVariables(self):
- """
- Reset variable and program list that are parsed from
- CSV file generated by IEC2C compiler.
- """
- self._ProgramList = None
- self._VariablesList = None
- self._IECPathToIdx = {}
- self._Ticktime = 0
- self.TracedIECPath = []
-
- def GetIECProgramsAndVariables(self):
- """
- Parse CSV-like file VARIABLES.csv resulting from IEC2C compiler.
- Each section is marked with a line staring with '//'
- list of all variables used in various POUs
- """
- if self._ProgramList is None or self._VariablesList is None:
- try:
- csvfile = os.path.join(self._getBuildPath(),"VARIABLES.csv")
- # describes CSV columns
- ProgramsListAttributeName = ["num", "C_path", "type"]
- VariablesListAttributeName = ["num", "vartype", "IEC_path", "C_path", "type"]
- self._ProgramList = []
- self._VariablesList = []
- self._IECPathToIdx = {}
-
- # Separate sections
- ListGroup = []
- for line in open(csvfile,'r').xreadlines():
- strippedline = line.strip()
- if strippedline.startswith("//"):
- # Start new section
- ListGroup.append([])
- elif len(strippedline) > 0 and len(ListGroup) > 0:
- # append to this section
- ListGroup[-1].append(strippedline)
-
- # first section contains programs
- for line in ListGroup[0]:
- # Split and Maps each field to dictionnary entries
- attrs = dict(zip(ProgramsListAttributeName,line.strip().split(';')))
- # Truncate "C_path" to remove conf an ressources names
- attrs["C_path"] = '__'.join(attrs["C_path"].split(".",2)[1:])
- # Push this dictionnary into result.
- self._ProgramList.append(attrs)
-
- # second section contains all variables
- for line in ListGroup[1]:
- # Split and Maps each field to dictionnary entries
- attrs = dict(zip(VariablesListAttributeName,line.strip().split(';')))
- # Truncate "C_path" to remove conf an ressources names
- parts = attrs["C_path"].split(".",2)
- if len(parts) > 2:
- attrs["C_path"] = '__'.join(parts[1:])
- else:
- attrs["C_path"] = '__'.join(parts)
- # Push this dictionnary into result.
- self._VariablesList.append(attrs)
- # Fill in IEC<->C translation dicts
- IEC_path=attrs["IEC_path"]
- Idx=int(attrs["num"])
- self._IECPathToIdx[IEC_path]=(Idx, attrs["type"])
-
- # third section contains ticktime
- if len(ListGroup) > 2:
- self._Ticktime = int(ListGroup[2][0])
-
- except Exception,e:
- self.logger.write_error(_("Cannot open/parse VARIABLES.csv!\n"))
- self.logger.write_error(traceback.format_exc())
- self.ResetIECProgramsAndVariables()
- return False
-
- return True
-
- def Generate_plc_debugger(self):
- """
- Generate trace/debug code out of PLC variable list
- """
- self.GetIECProgramsAndVariables()
-
- # prepare debug code
- debug_code = targets.code("plc_debug") % {
- "buffer_size": reduce(lambda x, y: x + y, [DebugTypesSize.get(v["type"], 0) for v in self._VariablesList], 0),
- "programs_declarations":
- "\n".join(["extern %(type)s %(C_path)s;"%p for p in self._ProgramList]),
- "extern_variables_declarations":"\n".join([
- {"EXT":"extern __IEC_%(type)s_p %(C_path)s;",
- "IN":"extern __IEC_%(type)s_p %(C_path)s;",
- "MEM":"extern __IEC_%(type)s_p %(C_path)s;",
- "OUT":"extern __IEC_%(type)s_p %(C_path)s;",
- "VAR":"extern __IEC_%(type)s_t %(C_path)s;"}[v["vartype"]]%v
- for v in self._VariablesList if v["vartype"] != "FB" and v["C_path"].find('.')<0]),
- "for_each_variable_do_code":"\n".join([
- {"EXT":" (*fp)((void*)&%(C_path)s,%(type)s_P_ENUM);\n",
- "IN":" (*fp)((void*)&%(C_path)s,%(type)s_P_ENUM);\n",
- "MEM":" (*fp)((void*)&%(C_path)s,%(type)s_O_ENUM);\n",
- "OUT":" (*fp)((void*)&%(C_path)s,%(type)s_O_ENUM);\n",
- "VAR":" (*fp)((void*)&%(C_path)s,%(type)s_ENUM);\n"}[v["vartype"]]%v
- for v in self._VariablesList if v["vartype"] != "FB" and v["type"] in DebugTypesSize ]),
- "find_variable_case_code":"\n".join([
- " case %(num)s:\n"%v+
- " *varp = (void*)&%(C_path)s;\n"%v+
- {"EXT":" return %(type)s_P_ENUM;\n",
- "IN":" return %(type)s_P_ENUM;\n",
- "MEM":" return %(type)s_O_ENUM;\n",
- "OUT":" return %(type)s_O_ENUM;\n",
- "VAR":" return %(type)s_ENUM;\n"}[v["vartype"]]%v
- for v in self._VariablesList if v["vartype"] != "FB" and v["type"] in DebugTypesSize ])}
-
- return debug_code
-
- def Generate_plc_common_main(self):
- """
- Use plugins layout given in LocationCFilesAndCFLAGS to
- generate glue code that dispatch calls to all plugins
- """
- # filter location that are related to code that will be called
- # in retreive, publish, init, cleanup
- locstrs = map(lambda x:"_".join(map(str,x)),
- [loc for loc,Cfiles,DoCalls in self.LocationCFilesAndCFLAGS if loc and DoCalls])
-
- # Generate main, based on template
- if self.BeremizRoot.getEnable_Plugins():
- plc_main_code = targets.code("plc_common_main") % {
- "calls_prototypes":"\n".join([(
- "int __init_%(s)s(int argc,char **argv);\n"+
- "void __cleanup_%(s)s(void);\n"+
- "void __retrieve_%(s)s(void);\n"+
- "void __publish_%(s)s(void);")%{'s':locstr} for locstr in locstrs]),
- "retrieve_calls":"\n ".join([
- "__retrieve_%s();"%locstrs[i-1] for i in xrange(len(locstrs), 0, -1)]),
- "publish_calls":"\n ".join([ #Call publish in reverse order
- "__publish_%s();"%locstr for locstr in locstrs]),
- "init_calls":"\n ".join([
- "init_level=%d; "%(i+1)+
- "if((res = __init_%s(argc,argv))){"%locstr +
- #"printf(\"%s\"); "%locstr + #for debug
- "return res;}" for i,locstr in enumerate(locstrs)]),
- "cleanup_calls":"\n ".join([
- "if(init_level >= %d) "%i+
- "__cleanup_%s();"%locstrs[i-1] for i in xrange(len(locstrs), 0, -1)])
- }
- else:
- plc_main_code = targets.code("plc_common_main") % {
- "calls_prototypes":"\n",
- "retrieve_calls":"\n",
- "publish_calls":"\n",
- "init_calls":"\n",
- "cleanup_calls":"\n"
- }
- plc_main_code += targets.targetcode(self.GetTarget().getcontent()["name"])
- return plc_main_code
-
-
- def _Build(self):
- """
- Method called by user to (re)build SoftPLC and plugin tree
- """
- if self.AppFrame is not None:
- self.AppFrame.ClearErrors()
-
- buildpath = self._getBuildPath()
-
- # Eventually create build dir
- if not os.path.exists(buildpath):
- os.mkdir(buildpath)
- # There is something to clean
- self.EnableMethod("_Clean", True)
-
- self.logger.flush()
- self.logger.write(_("Start build in %s\n") % buildpath)
-
- # Generate SoftPLC IEC code
- IECGenRes = self._Generate_SoftPLC()
- self.ShowMethod("_showIECcode", True)
-
- # If IEC code gen fail, bail out.
- if not IECGenRes:
- self.logger.write_error(_("IEC-61131-3 code generation failed !\n"))
- self.ResetBuildMD5()
- return False
-
- # Reset variable and program list that are parsed from
- # CSV file generated by IEC2C compiler.
- self.ResetIECProgramsAndVariables()
-
- # Generate C code and compilation params from plugin hierarchy
- self.logger.write(_("Generating plugins C code\n"))
- try:
- self.LocationCFilesAndCFLAGS, self.LDFLAGS, ExtraFiles = self._Generate_C(
- buildpath,
- self.PLCGeneratedLocatedVars)
- except Exception, exc:
- self.logger.write_error(_("Plugins code generation failed !\n"))
- self.logger.write_error(traceback.format_exc())
- self.ResetBuildMD5()
- return False
-
- # Get temporary directory path
- extrafilespath = self._getExtraFilesPath()
- # Remove old directory
- if os.path.exists(extrafilespath):
- shutil.rmtree(extrafilespath)
- # Recreate directory
- os.mkdir(extrafilespath)
- # Then write the files
- for fname,fobject in ExtraFiles:
- fpath = os.path.join(extrafilespath,fname)
- open(fpath, "wb").write(fobject.read())
- # Now we can forget ExtraFiles (will close files object)
- del ExtraFiles
-
- # Template based part of C code generation
- # files are stacked at the beginning, as files of plugin tree root
- for generator, filename, name in [
- # debugger code
- (self.Generate_plc_debugger, "plc_debugger.c", "Debugger"),
- # init/cleanup/retrieve/publish, run and align code
- (self.Generate_plc_common_main,"plc_common_main.c","Common runtime")]:
- try:
- # Do generate
- code = generator()
- if code is None:
- raise
- code_path = os.path.join(buildpath,filename)
- open(code_path, "w").write(code)
- # Insert this file as first file to be compiled at root plugin
- self.LocationCFilesAndCFLAGS[0][1].insert(0,(code_path, self.plcCFLAGS))
- except Exception, exc:
- self.logger.write_error(name+_(" generation failed !\n"))
- self.logger.write_error(traceback.format_exc())
- self.ResetBuildMD5()
- return False
-
- self.logger.write(_("C code generated successfully.\n"))
-
- # Get current or fresh builder
- builder = self.GetBuilder()
- if builder is None:
- self.logger.write_error(_("Fatal : cannot get builder.\n"))
- self.ResetBuildMD5()
- return False
-
- # Build
- try:
- if not builder.build() :
- self.logger.write_error(_("C Build failed.\n"))
- return False
- except Exception, exc:
- self.logger.write_error(_("C Build crashed !\n"))
- self.logger.write_error(traceback.format_exc())
- self.ResetBuildMD5()
- return False
-
- self.logger.write(_("Successfully built.\n"))
- # Update GUI status about need for transfer
- self.CompareLocalAndRemotePLC()
- return True
-
- def ShowError(self, logger, from_location, to_location):
- chunk_infos = self.GetChunkInfos(from_location, to_location)
- for infos, (start_row, start_col) in chunk_infos:
- start = (from_location[0] - start_row, from_location[1] - start_col)
- end = (to_location[0] - start_row, to_location[1] - start_col)
- #print from_location, to_location, start_row, start_col, start, end
- if self.AppFrame is not None:
- self.AppFrame.ShowError(infos, start, end)
-
- def _showIECcode(self):
- self._OpenView("IEC code")
-
- def _editIECrawcode(self):
- self._OpenView("IEC raw code")
-
- def _OpenView(self, name=None):
- if name == "IEC code":
- plc_file = self._getIECcodepath()
-
- IEC_code_viewer = TextViewer(self.AppFrame.TabsOpened, "", None, None, instancepath=name)
- #IEC_code_viewer.Enable(False)
- IEC_code_viewer.SetTextSyntax("ALL")
- IEC_code_viewer.SetKeywords(IEC_KEYWORDS)
- try:
- text = file(plc_file).read()
- except:
- text = '(* No IEC code have been generated at that time ! *)'
- IEC_code_viewer.SetText(text = text)
- IEC_code_viewer.SetIcon(self.AppFrame.GenerateBitmap("ST"))
-
- self.AppFrame.EditProjectElement(IEC_code_viewer, name)
-
- return IEC_code_viewer
-
- elif name == "IEC raw code":
- controler = MiniTextControler(self._getIECrawcodepath())
- IEC_raw_code_viewer = TextViewer(self.AppFrame.TabsOpened, "", None, controler, instancepath=name)
- #IEC_raw_code_viewer.Enable(False)
- IEC_raw_code_viewer.SetTextSyntax("ALL")
- IEC_raw_code_viewer.SetKeywords(IEC_KEYWORDS)
- IEC_raw_code_viewer.RefreshView()
- IEC_raw_code_viewer.SetIcon(self.AppFrame.GenerateBitmap("ST"))
-
- self.AppFrame.EditProjectElement(IEC_raw_code_viewer, name)
-
- return IEC_raw_code_viewer
-
- return None
-
- def _Clean(self):
- if os.path.isdir(os.path.join(self._getBuildPath())):
- self.logger.write(_("Cleaning the build directory\n"))
- shutil.rmtree(os.path.join(self._getBuildPath()))
- else:
- self.logger.write_error(_("Build directory already clean\n"))
- self.ShowMethod("_showIECcode", False)
- self.EnableMethod("_Clean", False)
- # kill the builder
- self._builder = None
- self.CompareLocalAndRemotePLC()
-
- ############# Real PLC object access #############
- def UpdateMethodsFromPLCStatus(self):
- # Get PLC state : Running or Stopped
- # TODO : use explicit status instead of boolean
- status = None
- if self._connector is not None:
- status = self._connector.GetPLCstatus()
- if status is None:
- self._connector = None
- status = "Disconnected"
- if(self.previous_plcstate != status):
- for args in {
- "Started" : [("_Run", False),
- ("_Stop", True)],
- "Stopped" : [("_Run", True),
- ("_Stop", False)],
- "Empty" : [("_Run", False),
- ("_Stop", False)],
- "Broken" : [],
- "Disconnected" :[("_Run", False),
- ("_Stop", False),
- ("_Transfer", False),
- ("_Connect", True),
- ("_Disconnect", False)],
- }.get(status,[]):
- self.ShowMethod(*args)
- self.previous_plcstate = status
- return True
- return False
-
- def PullPLCStatusProc(self, event):
- if self._connector is None:
- self.StatusTimer.Stop()
- if self.UpdateMethodsFromPLCStatus():
-
- status = _(self.previous_plcstate)
- {"Broken": self.logger.write_error,
- None: lambda x: None}.get(
- self.previous_plcstate, self.logger.write)(_("PLC is %s\n")%status)
- self.AppFrame.RefreshAll()
-
- def RegisterDebugVarToConnector(self):
- self.DebugTimer=None
- Idxs = []
- self.TracedIECPath = []
- if self._connector is not None:
- self.IECdebug_lock.acquire()
- IECPathsToPop = []
- for IECPath,data_tuple in self.IECdebug_datas.iteritems():
- WeakCallableDict, data_log, status, fvalue = data_tuple
- if len(WeakCallableDict) == 0:
- # Callable Dict is empty.
- # This variable is not needed anymore!
- #print "Unused : " + IECPath
- IECPathsToPop.append(IECPath)
- elif IECPath != "__tick__":
- # Convert
- Idx, IEC_Type = self._IECPathToIdx.get(IECPath,(None,None))
- if Idx is not None:
- if IEC_Type in DebugTypesSize:
- Idxs.append((Idx, IEC_Type, fvalue, IECPath))
- else:
- self.logger.write_warning(_("Debug : Unsuppoted type to debug %s\n")%IEC_Type)
- else:
- self.logger.write_warning(_("Debug : Unknown variable %s\n")%IECPath)
- for IECPathToPop in IECPathsToPop:
- self.IECdebug_datas.pop(IECPathToPop)
-
- if Idxs:
- Idxs.sort()
- self.TracedIECPath = zip(*Idxs)[3]
- self._connector.SetTraceVariablesList(zip(*zip(*Idxs)[0:3]))
- else:
- self.TracedIECPath = []
- self._connector.SetTraceVariablesList([])
- self.IECdebug_lock.release()
-
- #for IEC_path, IECdebug_data in self.IECdebug_datas.iteritems():
- # print IEC_path, IECdebug_data[0].keys()
-
- def ReArmDebugRegisterTimer(self):
- if self.DebugTimer is not None:
- self.DebugTimer.cancel()
-
- # Timer to prevent rapid-fire when registering many variables
- # use wx.CallAfter use keep using same thread. TODO : use wx.Timer instead
- self.DebugTimer=Timer(0.5,wx.CallAfter,args = [self.RegisterDebugVarToConnector])
- # Rearm anti-rapid-fire timer
- self.DebugTimer.start()
-
- def GetDebugIECVariableType(self, IECPath):
- Idx, IEC_Type = self._IECPathToIdx.get(IECPath,(None,None))
- return IEC_Type
-
- def SubscribeDebugIECVariable(self, IECPath, callableobj, *args, **kwargs):
- """
- Dispatching use a dictionnary linking IEC variable paths
- to a WeakKeyDictionary linking
- weakly referenced callables to optionnal args
- """
- if IECPath != "__tick__" and not self._IECPathToIdx.has_key(IECPath):
- return None
-
- self.IECdebug_lock.acquire()
- # If no entry exist, create a new one with a fresh WeakKeyDictionary
- IECdebug_data = self.IECdebug_datas.get(IECPath, None)
- if IECdebug_data is None:
- IECdebug_data = [
- WeakKeyDictionary(), # Callables
- [], # Data storage [(tick, data),...]
- "Registered", # Variable status
- None] # Forced value
- self.IECdebug_datas[IECPath] = IECdebug_data
-
- IECdebug_data[0][callableobj]=(args, kwargs)
-
- self.IECdebug_lock.release()
-
- self.ReArmDebugRegisterTimer()
-
- return IECdebug_data[1]
-
- def UnsubscribeDebugIECVariable(self, IECPath, callableobj):
- #print "Unsubscribe", IECPath, callableobj
- self.IECdebug_lock.acquire()
- IECdebug_data = self.IECdebug_datas.get(IECPath, None)
- if IECdebug_data is not None:
- IECdebug_data[0].pop(callableobj,None)
- self.IECdebug_lock.release()
-
- self.ReArmDebugRegisterTimer()
-
- def UnsubscribeAllDebugIECVariable(self):
- self.IECdebug_lock.acquire()
- IECdebug_data = {}
- self.IECdebug_lock.release()
-
- self.ReArmDebugRegisterTimer()
-
- def ForceDebugIECVariable(self, IECPath, fvalue):
- if not self.IECdebug_datas.has_key(IECPath):
- return
-
- self.IECdebug_lock.acquire()
-
- # If no entry exist, create a new one with a fresh WeakKeyDictionary
- IECdebug_data = self.IECdebug_datas.get(IECPath, None)
- IECdebug_data[2] = "Forced"
- IECdebug_data[3] = fvalue
-
- self.IECdebug_lock.release()
-
- self.ReArmDebugRegisterTimer()
-
- def ReleaseDebugIECVariable(self, IECPath):
- if not self.IECdebug_datas.has_key(IECPath):
- return
-
- self.IECdebug_lock.acquire()
-
- # If no entry exist, create a new one with a fresh WeakKeyDictionary
- IECdebug_data = self.IECdebug_datas.get(IECPath, None)
- IECdebug_data[2] = "Registered"
- IECdebug_data[3] = None
-
- self.IECdebug_lock.release()
-
- self.ReArmDebugRegisterTimer()
-
- def CallWeakcallables(self, IECPath, function_name, *cargs):
- data_tuple = self.IECdebug_datas.get(IECPath, None)
- if data_tuple is not None:
- WeakCallableDict, data_log, status, fvalue = data_tuple
- #data_log.append((debug_tick, value))
- for weakcallable,(args,kwargs) in WeakCallableDict.iteritems():
- #print weakcallable, value, args, kwargs
- function = getattr(weakcallable, function_name, None)
- if function is not None:
- if status == "Forced" and cargs[1] == fvalue:
- function(*(cargs + (True,) + args), **kwargs)
- else:
- function(*(cargs + args), **kwargs)
- # This will block thread if more than one call is waiting
-
- def GetTicktime(self):
- return self._Ticktime
-
- def RemoteExec(self, script, **kwargs):
- if self._connector is None:
- return -1, "No runtime connected!"
- return self._connector.RemoteExec(script, **kwargs)
-
- def DebugThreadProc(self):
- """
- This thread waid PLC debug data, and dispatch them to subscribers
- """
- self.debug_break = False
- debug_getvar_retry = 0
- while (not self.debug_break) and (self._connector is not None):
- Trace = self._connector.GetTraceVariables()
- if(Trace):
- plc_status, debug_tick, debug_vars = Trace
- else:
- plc_status = None
- debug_getvar_retry += 1
- #print debug_tick, debug_vars
- if plc_status == "Started":
- self.IECdebug_lock.acquire()
- if len(debug_vars) == len(self.TracedIECPath):
- if debug_getvar_retry > DEBUG_RETRIES_WARN:
- self.logger.write(_("... debugger recovered\n"))
- debug_getvar_retry = 0
- for IECPath,value in zip(self.TracedIECPath, debug_vars):
- if value is not None:
- self.CallWeakcallables(IECPath, "NewValue", debug_tick, value)
- self.CallWeakcallables("__tick__", "NewDataAvailable")
- self.IECdebug_lock.release()
- if debug_getvar_retry == DEBUG_RETRIES_WARN:
- self.logger.write(_("Waiting debugger to recover...\n"))
- if debug_getvar_retry == DEBUG_RETRIES_REREGISTER:
- # re-register debug registry to PLC
- wx.CallAfter(self.RegisterDebugVarToConnector)
- if debug_getvar_retry != 0:
- # Be patient, tollerate PLC to come up before debugging
- time.sleep(0.1)
- else:
- self.debug_break = True
- self.logger.write(_("Debugger disabled\n"))
- self.DebugThread = None
-
- def KillDebugThread(self):
- tmp_debugthread = self.DebugThread
- self.debug_break = True
- if tmp_debugthread is not None:
- self.logger.writeyield(_("Stopping debugger...\n"))
- tmp_debugthread.join(timeout=5)
- if tmp_debugthread.isAlive() and self.logger:
- self.logger.write_warning(_("Couldn't stop debugger.\n"))
- else:
- self.logger.write(_("Debugger stopped.\n"))
- self.DebugThread = None
-
- def _connect_debug(self):
- if self.AppFrame:
- self.AppFrame.ResetGraphicViewers()
- self.RegisterDebugVarToConnector()
- if self.DebugThread is None:
- self.DebugThread = Thread(target=self.DebugThreadProc)
- self.DebugThread.start()
-
- def _Run(self):
- """
- Start PLC
- """
- if self.GetIECProgramsAndVariables():
- self._connector.StartPLC()
- self.logger.write(_("Starting PLC\n"))
- self._connect_debug()
- else:
- self.logger.write_error(_("Couldn't start PLC !\n"))
- wx.CallAfter(self.UpdateMethodsFromPLCStatus)
-
- def _Stop(self):
- """
- Stop PLC
- """
- if self._connector is not None and not self._connector.StopPLC():
- self.logger.write_error(_("Couldn't stop PLC !\n"))
-
- # debugthread should die on his own
- #self.KillDebugThread()
-
- wx.CallAfter(self.UpdateMethodsFromPLCStatus)
-
- def _Connect(self):
- # don't accept re-connetion is already connected
- if self._connector is not None:
- self.logger.write_error(_("Already connected. Please disconnect\n"))
- return
-
- # Get connector uri
- uri = self.\
- BeremizRoot.\
- getURI_location().\
- strip()
-
- # if uri is empty launch discovery dialog
- if uri == "":
- # Launch Service Discovery dialog
- dialog = DiscoveryDialog(self.AppFrame)
- answer = dialog.ShowModal()
- uri = dialog.GetURI()
- dialog.Destroy()
-
- # Nothing choosed or cancel button
- if uri is None or answer == wx.ID_CANCEL:
- self.logger.write_error(_("Connection canceled!\n"))
- return
- else:
- self.\
- BeremizRoot.\
- setURI_location(uri)
-
- # Get connector from uri
- try:
- self._connector = connectors.ConnectorFactory(uri, self)
- except Exception, msg:
- self.logger.write_error(_("Exception while connecting %s!\n")%uri)
- self.logger.write_error(traceback.format_exc())
-
- # Did connection success ?
- if self._connector is None:
- # Oups.
- self.logger.write_error(_("Connection failed to %s!\n")%uri)
- else:
- self.ShowMethod("_Connect", False)
- self.ShowMethod("_Disconnect", True)
- self.ShowMethod("_Transfer", True)
-
- self.CompareLocalAndRemotePLC()
-
- # Init with actual PLC status and print it
- self.UpdateMethodsFromPLCStatus()
- if self.previous_plcstate is not None:
- status = _(self.previous_plcstate)
- else:
- status = ""
- self.logger.write(_("PLC is %s\n")%status)
-
- # Start the status Timer
- self.StatusTimer.Start(milliseconds=500, oneShot=False)
-
- if self.previous_plcstate=="Started":
- if self.DebugAvailable() and self.GetIECProgramsAndVariables():
- self.logger.write(_("Debug connect matching running PLC\n"))
- self._connect_debug()
- else:
- self.logger.write_warning(_("Debug do not match PLC - stop/transfert/start to re-enable\n"))
-
- def CompareLocalAndRemotePLC(self):
- if self._connector is None:
- return
- # We are now connected. Update button status
- MD5 = self.GetLastBuildMD5()
- # Check remote target PLC correspondance to that md5
- if MD5 is not None:
- if not self._connector.MatchMD5(MD5):
-# self.logger.write_warning(
-# _("Latest build does not match with target, please transfer.\n"))
- self.EnableMethod("_Transfer", True)
- else:
-# self.logger.write(
-# _("Latest build matches target, no transfer needed.\n"))
- self.EnableMethod("_Transfer", True)
- # warns controller that program match
- self.ProgramTransferred()
- #self.EnableMethod("_Transfer", False)
- else:
-# self.logger.write_warning(
-# _("Cannot compare latest build to target. Please build.\n"))
- self.EnableMethod("_Transfer", False)
-
-
- def _Disconnect(self):
- self._connector = None
- self.StatusTimer.Stop()
- wx.CallAfter(self.UpdateMethodsFromPLCStatus)
-
- def _Transfer(self):
- # Get the last build PLC's
- MD5 = self.GetLastBuildMD5()
-
- # Check if md5 file is empty : ask user to build PLC
- if MD5 is None :
- self.logger.write_error(_("Failed : Must build before transfer.\n"))
- return False
-
- # Compare PLC project with PLC on target
- if self._connector.MatchMD5(MD5):
- self.logger.write(
- _("Latest build already matches current target. Transfering anyway...\n"))
-
- # Get temprary directory path
- extrafilespath = self._getExtraFilesPath()
- extrafiles = [(name, open(os.path.join(extrafilespath, name),
- 'rb').read()) \
- for name in os.listdir(extrafilespath) \
- if not name=="CVS"]
-
- # Send PLC on target
- builder = self.GetBuilder()
- if builder is not None:
- data = builder.GetBinaryCode()
- if data is not None :
- if self._connector.NewPLC(MD5, data, extrafiles) and self.GetIECProgramsAndVariables():
- self.UnsubscribeAllDebugIECVariable()
- self.ProgramTransferred()
- if self.AppFrame is not None:
- self.AppFrame.RefreshInstancesTree()
- self.AppFrame.CloseObsoleteDebugTabs()
- self.logger.write(_("Transfer completed successfully.\n"))
- else:
- self.logger.write_error(_("Transfer failed\n"))
- else:
- self.logger.write_error(_("No PLC to transfer (did build succeed ?)\n"))
-
- wx.CallAfter(self.UpdateMethodsFromPLCStatus)
-
- PluginMethods = [
- {"bitmap" : opjimg("Build"),
- "name" : _("Build"),
- "tooltip" : _("Build project into build folder"),
- "method" : "_Build"},
- {"bitmap" : opjimg("Clean"),
- "name" : _("Clean"),
- "enabled" : False,
- "tooltip" : _("Clean project build folder"),
- "method" : "_Clean"},
- {"bitmap" : opjimg("Run"),
- "name" : _("Run"),
- "shown" : False,
- "tooltip" : _("Start PLC"),
- "method" : "_Run"},
- {"bitmap" : opjimg("Stop"),
- "name" : _("Stop"),
- "shown" : False,
- "tooltip" : _("Stop Running PLC"),
- "method" : "_Stop"},
- {"bitmap" : opjimg("Connect"),
- "name" : _("Connect"),
- "tooltip" : _("Connect to the target PLC"),
- "method" : "_Connect"},
- {"bitmap" : opjimg("Transfer"),
- "name" : _("Transfer"),
- "shown" : False,
- "tooltip" : _("Transfer PLC"),
- "method" : "_Transfer"},
- {"bitmap" : opjimg("Disconnect"),
- "name" : _("Disconnect"),
- "shown" : False,
- "tooltip" : _("Disconnect from PLC"),
- "method" : "_Disconnect"},
- {"bitmap" : opjimg("ShowIECcode"),
- "name" : _("Show code"),
- "shown" : False,
- "tooltip" : _("Show IEC code generated by PLCGenerator"),
- "method" : "_showIECcode"},
- {"bitmap" : opjimg("editIECrawcode"),
- "name" : _("Raw IEC code"),
- "tooltip" : _("Edit raw IEC code added to code generated by PLCGenerator"),
- "method" : "_editIECrawcode"},
- ]
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/.cvsignore
--- a/plugins/.cvsignore Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-*.pyc
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/__init__.py
--- a/plugins/__init__.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-from os import listdir, path
-
-_base_path = path.split(__file__)[0]
-
-__all__ = [name for name in listdir(_base_path) if path.isdir(path.join(_base_path, name)) and name.upper() != "CVS" or name.endswith(".py") and not name.startswith("__")]
-
-helps = []
-for name in __all__:
- helpfilename = path.join(_base_path, name, "README")
- if path.isfile(helpfilename):
- helps.append(open(helpfilename).readline().strip())
- else:
- helps.append(name)
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/c_ext/.cvsignore
--- a/plugins/c_ext/.cvsignore Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-*.pyc
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/c_ext/CFileEditor.py
--- a/plugins/c_ext/CFileEditor.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,967 +0,0 @@
-import keyword
-
-import wx
-import wx.grid
-import wx.stc as stc
-import wx.lib.buttons
-
-from controls import CustomGrid, CustomTable, EditorPanel
-
-if wx.Platform == '__WXMSW__':
- faces = { 'times': 'Times New Roman',
- 'mono' : 'Courier New',
- 'helv' : 'Arial',
- 'other': 'Comic Sans MS',
- 'size' : 10,
- 'size2': 8,
- }
-else:
- faces = { 'times': 'Times',
- 'mono' : 'Courier',
- 'helv' : 'Helvetica',
- 'other': 'new century schoolbook',
- 'size' : 12,
- 'size2': 10,
- }
-
-
-def AppendMenu(parent, help, id, kind, text):
- if wx.VERSION >= (2, 6, 0):
- parent.Append(help=help, id=id, kind=kind, text=text)
- else:
- parent.Append(helpString=help, id=id, kind=kind, item=text)
-
-
-[ID_CPPEDITOR,
-] = [wx.NewId() for _init_ctrls in range(1)]
-
-CPP_KEYWORDS = ["asm", "auto", "bool", "break", "case", "catch", "char", "class",
- "const", "const_cast", "continue", "default", "delete", "do", "double",
- "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false",
- "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable",
- "namespace", "new", "operator", "private", "protected", "public", "register",
- "reinterpret_cast", "return", "short", "signed", "sizeof", "static",
- "static_cast", "struct", "switch", "template", "this", "throw", "true", "try",
- "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual",
- "void", "volatile", "wchar_t", "while"]
-
-def GetCursorPos(old, new):
- old_length = len(old)
- new_length = len(new)
- common_length = min(old_length, new_length)
- i = 0
- for i in xrange(common_length):
- if old[i] != new[i]:
- break
- if old_length < new_length:
- if common_length > 0 and old[i] != new[i]:
- return i + new_length - old_length
- else:
- return i + new_length - old_length + 1
- elif old_length > new_length or i < min(old_length, new_length) - 1:
- if common_length > 0 and old[i] != new[i]:
- return i
- else:
- return i + 1
- else:
- return None
-
-class CppEditor(stc.StyledTextCtrl):
-
- fold_symbols = 3
-
- def __init__(self, parent, name, window, controler):
- stc.StyledTextCtrl.__init__(self, parent, ID_CPPEDITOR, wx.DefaultPosition,
- wx.Size(0, 0), 0)
-
- self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
- self.SetMarginWidth(1, 25)
-
- self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
- self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
-
- self.SetLexer(stc.STC_LEX_CPP)
- self.SetKeyWords(0, " ".join(CPP_KEYWORDS))
-
- self.SetProperty("fold", "1")
- self.SetProperty("tab.timmy.whinge.level", "1")
- self.SetMargins(0,0)
-
- self.SetViewWhiteSpace(False)
- #self.SetBufferedDraw(False)
- #self.SetViewEOL(True)
- #self.SetEOLMode(stc.STC_EOL_CRLF)
- #self.SetUseAntiAliasing(True)
-
- self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
- self.SetEdgeColumn(78)
-
- # Setup a margin to hold fold markers
- #self.SetFoldFlags(16) ### WHAT IS THIS VALUE? WHAT ARE THE OTHER FLAGS? DOES IT MATTER?
- self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
- self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
- self.SetMarginSensitive(2, True)
- self.SetMarginWidth(2, 12)
-
- if self.fold_symbols == 0:
- # Arrow pointing right for contracted folders, arrow pointing down for expanded
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_ARROWDOWN, "black", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_ARROW, "black", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "black", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "black", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
-
- elif self.fold_symbols == 1:
- # Plus for contracted folders, minus for expanded
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_MINUS, "white", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_PLUS, "white", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "white", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "white", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
-
- elif self.fold_symbols == 2:
- # Like a flattened tree control using circular headers and curved joins
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_CIRCLEMINUS, "white", "#404040")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_CIRCLEPLUS, "white", "#404040")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#404040")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNERCURVE, "white", "#404040")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_CIRCLEPLUSCONNECTED, "white", "#404040")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE, "white", "#404040")
-
- elif self.fold_symbols == 3:
- # Like a flattened tree control using square headers
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "#808080")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "#808080")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#808080")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "#808080")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "#808080")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
- self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "#808080")
-
-
- self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
- self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
- self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
-
- # Make some styles, The lexer defines what each style is used for, we
- # just have to define what each style looks like. This set is adapted from
- # Scintilla sample property files.
-
- # Global default styles for all languages
- self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces)
- self.StyleClearAll() # Reset all to be like the default
-
- # Global default styles for all languages
- self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces)
- self.StyleSetSpec(stc.STC_STYLE_LINENUMBER, "back:#C0C0C0,face:%(helv)s,size:%(size2)d" % faces)
- self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(other)s" % faces)
- self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, "fore:#FFFFFF,back:#0000FF,bold")
- self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, "fore:#000000,back:#FF0000,bold")
-
- self.StyleSetSpec(stc.STC_C_COMMENT, 'fore:#408060')
- self.StyleSetSpec(stc.STC_C_COMMENTLINE, 'fore:#408060')
- self.StyleSetSpec(stc.STC_C_COMMENTDOC, 'fore:#408060')
- self.StyleSetSpec(stc.STC_C_NUMBER, 'fore:#0076AE')
- self.StyleSetSpec(stc.STC_C_WORD, 'bold,fore:#800056')
- self.StyleSetSpec(stc.STC_C_STRING, 'fore:#2a00ff')
- self.StyleSetSpec(stc.STC_C_PREPROCESSOR, 'bold,fore:#800056')
- self.StyleSetSpec(stc.STC_C_OPERATOR, 'bold')
- self.StyleSetSpec(stc.STC_C_STRINGEOL, 'back:#FFD5FF')
-
- # register some images for use in the AutoComplete box.
- #self.RegisterImage(1, images.getSmilesBitmap())
- self.RegisterImage(1,
- wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16)))
- self.RegisterImage(2,
- wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16)))
- self.RegisterImage(3,
- wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
-
- # Indentation size
- self.SetTabWidth(2)
- self.SetUseTabs(0)
-
- self.Controler = controler
- self.ParentWindow = window
-
- self.DisableEvents = True
- self.Name = name
- self.CurrentAction = None
-
- self.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE)
-
- self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_CPPEDITOR)
- self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
- self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_CPPEDITOR)
-
- def OnModification(self, event):
- if not self.DisableEvents:
- mod_type = event.GetModificationType()
- if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO):
- if mod_type&wx.stc.STC_MOD_BEFOREINSERT:
- if self.CurrentAction == None:
- self.StartBuffering()
- elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
- self.Controler.EndBuffering()
- self.StartBuffering()
- self.CurrentAction = ("Add", event.GetPosition())
- wx.CallAfter(self.RefreshModel)
- elif mod_type&wx.stc.STC_MOD_BEFOREDELETE:
- if self.CurrentAction == None:
- self.StartBuffering()
- elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
- self.Controler.EndBuffering()
- self.StartBuffering()
- self.CurrentAction = ("Delete", event.GetPosition())
- wx.CallAfter(self.RefreshModel)
- event.Skip()
-
- def OnDoDrop(self, event):
- self.ResetBuffer()
- wx.CallAfter(self.RefreshModel)
- event.Skip()
-
- # Buffer the last model state
- def RefreshBuffer(self):
- self.Controler.BufferCFile()
- if self.ParentWindow is not None:
- self.ParentWindow.RefreshTitle()
- self.ParentWindow.RefreshFileMenu()
- self.ParentWindow.RefreshEditMenu()
- self.ParentWindow.RefreshPageTitles()
-
- def StartBuffering(self):
- self.Controler.StartBuffering()
- if self.ParentWindow is not None:
- self.ParentWindow.RefreshTitle()
- self.ParentWindow.RefreshFileMenu()
- self.ParentWindow.RefreshEditMenu()
- self.ParentWindow.RefreshPageTitles()
-
- def ResetBuffer(self):
- if self.CurrentAction != None:
- self.Controler.EndBuffering()
- self.CurrentAction = None
-
- def RefreshView(self):
- self.ResetBuffer()
- self.DisableEvents = True
- old_cursor_pos = self.GetCurrentPos()
- old_text = self.GetText()
- new_text = self.Controler.GetPartText(self.Name)
- self.SetText(new_text)
- new_cursor_pos = GetCursorPos(old_text, new_text)
- if new_cursor_pos != None:
- self.GotoPos(new_cursor_pos)
- else:
- self.GotoPos(old_cursor_pos)
- self.ScrollToColumn(0)
- self.EmptyUndoBuffer()
- self.DisableEvents = False
-
- self.Colourise(0, -1)
-
- def DoGetBestSize(self):
- return self.ParentWindow.GetPanelBestSize()
-
- def RefreshModel(self):
- self.Controler.SetPartText(self.Name, self.GetText())
-
- def OnKeyPressed(self, event):
- if self.CallTipActive():
- self.CallTipCancel()
- key = event.GetKeyCode()
-
- if key == 32 and event.ControlDown():
- pos = self.GetCurrentPos()
-
- # Tips
- if event.ShiftDown():
- pass
-## self.CallTipSetBackground("yellow")
-## self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n'
-## 'show some suff, maybe parameters..\n\n'
-## 'fubar(param1, param2)')
- # Code completion
- else:
- self.AutoCompSetIgnoreCase(False) # so this needs to match
-
- # Images are specified with a appended "?type"
- self.AutoCompShow(0, " ".join([word + "?1" for word in CPP_KEYWORDS]))
- else:
- event.Skip()
-
- def OnKillFocus(self, event):
- self.AutoCompCancel()
- event.Skip()
-
- def OnUpdateUI(self, evt):
- # check for matching braces
- braceAtCaret = -1
- braceOpposite = -1
- charBefore = None
- caretPos = self.GetCurrentPos()
-
- if caretPos > 0:
- charBefore = self.GetCharAt(caretPos - 1)
- styleBefore = self.GetStyleAt(caretPos - 1)
-
- # check before
- if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
- braceAtCaret = caretPos - 1
-
- # check after
- if braceAtCaret < 0:
- charAfter = self.GetCharAt(caretPos)
- styleAfter = self.GetStyleAt(caretPos)
-
- if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
- braceAtCaret = caretPos
-
- if braceAtCaret >= 0:
- braceOpposite = self.BraceMatch(braceAtCaret)
-
- if braceAtCaret != -1 and braceOpposite == -1:
- self.BraceBadLight(braceAtCaret)
- else:
- self.BraceHighlight(braceAtCaret, braceOpposite)
- #pt = self.PointFromPosition(braceOpposite)
- #self.Refresh(True, wxRect(pt.x, pt.y, 5,5))
- #print pt
- #self.Refresh(False)
-
-
- def OnMarginClick(self, evt):
- # fold and unfold as needed
- if evt.GetMargin() == 2:
- if evt.GetShift() and evt.GetControl():
- self.FoldAll()
- else:
- lineClicked = self.LineFromPosition(evt.GetPosition())
-
- if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
- if evt.GetShift():
- self.SetFoldExpanded(lineClicked, True)
- self.Expand(lineClicked, True, True, 1)
- elif evt.GetControl():
- if self.GetFoldExpanded(lineClicked):
- self.SetFoldExpanded(lineClicked, False)
- self.Expand(lineClicked, False, True, 0)
- else:
- self.SetFoldExpanded(lineClicked, True)
- self.Expand(lineClicked, True, True, 100)
- else:
- self.ToggleFold(lineClicked)
-
-
- def FoldAll(self):
- lineCount = self.GetLineCount()
- expanding = True
-
- # find out if we are folding or unfolding
- for lineNum in range(lineCount):
- if self.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
- expanding = not self.GetFoldExpanded(lineNum)
- break
-
- lineNum = 0
-
- while lineNum < lineCount:
- level = self.GetFoldLevel(lineNum)
- if level & stc.STC_FOLDLEVELHEADERFLAG and \
- (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
-
- if expanding:
- self.SetFoldExpanded(lineNum, True)
- lineNum = self.Expand(lineNum, True)
- lineNum = lineNum - 1
- else:
- lastChild = self.GetLastChild(lineNum, -1)
- self.SetFoldExpanded(lineNum, False)
-
- if lastChild > lineNum:
- self.HideLines(lineNum+1, lastChild)
-
- lineNum = lineNum + 1
-
-
-
- def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
- lastChild = self.GetLastChild(line, level)
- line = line + 1
-
- while line <= lastChild:
- if force:
- if visLevels > 0:
- self.ShowLines(line, line)
- else:
- self.HideLines(line, line)
- else:
- if doExpand:
- self.ShowLines(line, line)
-
- if level == -1:
- level = self.GetFoldLevel(line)
-
- if level & stc.STC_FOLDLEVELHEADERFLAG:
- if force:
- if visLevels > 1:
- self.SetFoldExpanded(line, True)
- else:
- self.SetFoldExpanded(line, False)
-
- line = self.Expand(line, doExpand, force, visLevels-1)
-
- else:
- if doExpand and self.GetFoldExpanded(line):
- line = self.Expand(line, True, force, visLevels-1)
- else:
- line = self.Expand(line, False, force, visLevels-1)
- else:
- line = line + 1
-
- return line
-
- def Cut(self):
- self.ResetBuffer()
- self.DisableEvents = True
- self.CmdKeyExecute(wx.stc.STC_CMD_CUT)
- self.DisableEvents = False
- self.RefreshModel()
- self.RefreshBuffer()
-
- def Copy(self):
- self.CmdKeyExecute(wx.stc.STC_CMD_COPY)
-
- def Paste(self):
- self.ResetBuffer()
- self.DisableEvents = True
- self.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
- self.DisableEvents = False
- self.RefreshModel()
- self.RefreshBuffer()
-
-
-#-------------------------------------------------------------------------------
-# Helper for VariablesGrid values
-#-------------------------------------------------------------------------------
-
-class VariablesTable(CustomTable):
-
- def GetValue(self, row, col):
- if row < self.GetNumberRows():
- if col == 0:
- return row + 1
- else:
- return str(self.data[row].get(self.GetColLabelValue(col, False), ""))
-
- def _updateColAttrs(self, grid):
- """
- wxGrid -> update the column attributes to add the
- appropriate renderer given the column name.
-
- Otherwise default to the default renderer.
- """
-
- typelist = None
- accesslist = None
- for row in range(self.GetNumberRows()):
- for col in range(self.GetNumberCols()):
- editor = None
- renderer = None
- colname = self.GetColLabelValue(col, False)
-
- if colname == "Name":
- editor = wx.grid.GridCellTextEditor()
- elif colname == "Class":
- editor = wx.grid.GridCellChoiceEditor()
- editor.SetParameters("input,memory,output")
- elif colname == "Type":
- pass
- else:
- grid.SetReadOnly(row, col, True)
-
- grid.SetCellEditor(row, col, editor)
- grid.SetCellRenderer(row, col, renderer)
-
- grid.SetCellBackgroundColour(row, col, wx.WHITE)
- self.ResizeRow(grid, row)
-
-
-[ID_VARIABLESEDITOR, ID_VARIABLESEDITORVARIABLESGRID,
- ID_VARIABLESEDITORADDVARIABLEBUTTON, ID_VARIABLESEDITORDELETEVARIABLEBUTTON,
- ID_VARIABLESEDITORUPVARIABLEBUTTON, ID_VARIABLESEDITORDOWNVARIABLEBUTTON
-] = [wx.NewId() for _init_ctrls in range(6)]
-
-class VariablesEditor(wx.Panel):
-
- if wx.VERSION < (2, 6, 0):
- def Bind(self, event, function, id = None):
- if id is not None:
- event(self, id, function)
- else:
- event(self, function)
-
- def _init_coll_MainSizer_Growables(self, parent):
- parent.AddGrowableCol(0)
- parent.AddGrowableRow(0)
-
- def _init_coll_MainSizer_Items(self, parent):
- parent.AddWindow(self.VariablesGrid, 0, border=0, flag=wx.GROW)
- parent.AddSizer(self.ButtonsSizer, 0, border=0, flag=wx.GROW)
-
- def _init_coll_ButtonsSizer_Growables(self, parent):
- parent.AddGrowableCol(0)
- parent.AddGrowableRow(0)
-
- def _init_coll_ButtonsSizer_Items(self, parent):
- parent.AddWindow(self.AddVariableButton, 0, border=0, flag=wx.ALIGN_RIGHT)
- parent.AddWindow(self.DeleteVariableButton, 0, border=0, flag=0)
- parent.AddWindow(self.UpVariableButton, 0, border=0, flag=0)
- parent.AddWindow(self.DownVariableButton, 0, border=0, flag=0)
-
- def _init_sizers(self):
- self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=4)
- self.ButtonsSizer = wx.FlexGridSizer(cols=5, hgap=5, rows=1, vgap=0)
-
- self._init_coll_MainSizer_Growables(self.MainSizer)
- self._init_coll_MainSizer_Items(self.MainSizer)
- self._init_coll_ButtonsSizer_Growables(self.ButtonsSizer)
- self._init_coll_ButtonsSizer_Items(self.ButtonsSizer)
-
- self.SetSizer(self.MainSizer)
-
- def _init_ctrls(self, prnt):
- wx.Panel.__init__(self, id=ID_VARIABLESEDITOR, name='', parent=prnt,
- size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
-
- self.VariablesGrid = CustomGrid(id=ID_VARIABLESEDITORVARIABLESGRID,
- name='VariablesGrid', parent=self, pos=wx.Point(0, 0),
- size=wx.Size(-1, -1), style=wx.VSCROLL)
- if wx.VERSION >= (2, 5, 0):
- self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnVariablesGridCellChange)
- self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnVariablesGridCellLeftClick)
- self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, self.OnVariablesGridEditorShown)
- else:
- wx.grid.EVT_GRID_CELL_CHANGE(self.VariablesGrid, self.OnVariablesGridCellChange)
- wx.grid.EVT_GRID_CELL_LEFT_CLICK(self.VariablesGrid, self.OnVariablesGridCellLeftClick)
- wx.grid.EVT_GRID_EDITOR_SHOWN(self.VariablesGrid, self.OnVariablesGridEditorShown)
-
- self.AddVariableButton = wx.Button(id=ID_VARIABLESEDITORADDVARIABLEBUTTON, label='Add Variable',
- name='AddVariableButton', parent=self, pos=wx.Point(0, 0),
- size=wx.Size(122, 32), style=0)
-
- self.DeleteVariableButton = wx.Button(id=ID_VARIABLESEDITORDELETEVARIABLEBUTTON, label='Delete Variable',
- name='DeleteVariableButton', parent=self, pos=wx.Point(0, 0),
- size=wx.Size(122, 32), style=0)
-
- self.UpVariableButton = wx.Button(id=ID_VARIABLESEDITORUPVARIABLEBUTTON, label='^',
- name='UpVariableButton', parent=self, pos=wx.Point(0, 0),
- size=wx.Size(32, 32), style=0)
-
- self.DownVariableButton = wx.Button(id=ID_VARIABLESEDITORDOWNVARIABLEBUTTON, label='v',
- name='DownVariableButton', parent=self, pos=wx.Point(0, 0),
- size=wx.Size(32, 32), style=0)
-
- self._init_sizers()
-
- def __init__(self, parent, window, controler):
- self._init_ctrls(parent)
-
- self.ParentWindow = window
- self.Controler = controler
-
- self.VariablesDefaultValue = {"Name" : "", "Class" : "input", "Type" : ""}
- self.Table = VariablesTable(self, [], ["#", "Name", "Class", "Type"])
- self.ColAlignements = [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
- self.ColSizes = [40, 200, 150, 150]
- self.VariablesGrid.SetTable(self.Table)
- self.VariablesGrid.SetButtons({"Add": self.AddVariableButton,
- "Delete": self.DeleteVariableButton,
- "Up": self.UpVariableButton,
- "Down": self.DownVariableButton})
-
- def _AddVariable(new_row):
- self.Table.InsertRow(new_row, self.VariablesDefaultValue.copy())
- self.RefreshModel()
- self.RefreshView()
- return new_row
- setattr(self.VariablesGrid, "_AddRow", _AddVariable)
-
- def _DeleteVariable(row):
- self.Table.RemoveRow(row)
- self.RefreshModel()
- self.RefreshView()
- setattr(self.VariablesGrid, "_DeleteRow", _DeleteVariable)
-
- def _MoveVariable(row, move):
- new_row = self.Table.MoveRow(row, move)
- if new_row != row:
- self.RefreshModel()
- self.RefreshView()
- return new_row
- setattr(self.VariablesGrid, "_MoveRow", _MoveVariable)
-
- self.VariablesGrid.SetRowLabelSize(0)
- for col in range(self.Table.GetNumberCols()):
- attr = wx.grid.GridCellAttr()
- attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE)
- self.VariablesGrid.SetColAttr(col, attr)
- self.VariablesGrid.SetColSize(col, self.ColSizes[col])
- self.Table.ResetView(self.VariablesGrid)
-
- def RefreshModel(self):
- self.Controler.SetVariables(self.Table.GetData())
- self.RefreshBuffer()
-
- # Buffer the last model state
- def RefreshBuffer(self):
- self.Controler.BufferCFile()
- self.ParentWindow.RefreshTitle()
- self.ParentWindow.RefreshFileMenu()
- self.ParentWindow.RefreshEditMenu()
- self.ParentWindow.RefreshPageTitles()
-
- def RefreshView(self):
- self.Table.SetData(self.Controler.GetVariables())
- self.Table.ResetView(self.VariablesGrid)
- self.VariablesGrid.RefreshButtons()
-
- def DoGetBestSize(self):
- return self.ParentWindow.GetPanelBestSize()
-
- def OnVariablesGridCellChange(self, event):
- self.RefreshModel()
- wx.CallAfter(self.RefreshView)
- event.Skip()
-
- def OnVariablesGridEditorShown(self, event):
- row, col = event.GetRow(), event.GetCol()
- if self.Table.GetColLabelValue(col) == "Type":
- type_menu = wx.Menu(title='')
- base_menu = wx.Menu(title='')
- for base_type in self.Controler.GetBaseTypes():
- new_id = wx.NewId()
- AppendMenu(base_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=base_type)
- self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(base_type), id=new_id)
- type_menu.AppendMenu(wx.NewId(), "Base Types", base_menu)
- datatype_menu = wx.Menu(title='')
- for datatype in self.Controler.GetDataTypes(basetypes=False, only_locatables=True):
- new_id = wx.NewId()
- AppendMenu(datatype_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
- self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
- type_menu.AppendMenu(wx.NewId(), "User Data Types", datatype_menu)
- rect = self.VariablesGrid.BlockToDeviceRect((row, col), (row, col))
-
- self.VariablesGrid.PopupMenuXY(type_menu, rect.x + rect.width, rect.y + self.VariablesGrid.GetColLabelSize())
- type_menu.Destroy()
- event.Veto()
- else:
- event.Skip()
-
- def GetVariableTypeFunction(self, base_type):
- def VariableTypeFunction(event):
- row = self.VariablesGrid.GetGridCursorRow()
- self.Table.SetValueByName(row, "Type", base_type)
- self.Table.ResetView(self.VariablesGrid)
- self.RefreshModel()
- self.RefreshView()
- event.Skip()
- return VariableTypeFunction
-
- def OnVariablesGridCellLeftClick(self, event):
- if event.GetCol() == 0:
- row = event.GetRow()
- num = 0
- if self.Table.GetValueByName(row, "Class") == "input":
- dir = "%I"
- for i in xrange(row):
- if self.Table.GetValueByName(i, "Class") == "input":
- num += 1
- elif self.Table.GetValueByName(row, "Class") == "memory":
- dir = "%M"
- for i in xrange(row):
- if self.Table.GetValueByName(i, "Class") == "memory":
- num += 1
- else:
- dir = "%Q"
- for i in xrange(row):
- if self.Table.GetValueByName(i, "Class") == "output":
- num += 1
- data_type = self.Table.GetValueByName(row, "Type")
- var_name = self.Table.GetValueByName(row, "Name")
- base_location = ".".join(map(lambda x:str(x), self.Controler.GetCurrentLocation()))
- location = "%s%s%s.%d"%(dir, self.Controler.GetSizeOfType(data_type), base_location, num)
- data = wx.TextDataObject(str((location, "location", data_type, var_name, "")))
- dragSource = wx.DropSource(self.VariablesGrid)
- dragSource.SetData(data)
- dragSource.DoDragDrop()
- event.Skip()
-
-
-#-------------------------------------------------------------------------------
-# SVGUIEditor Main Frame Class
-#-------------------------------------------------------------------------------
-
-CFILE_PARTS = [
- ("Includes", CppEditor),
- ("Variables", VariablesEditor),
- ("Globals", CppEditor),
- ("Init", CppEditor),
- ("CleanUp", CppEditor),
- ("Retrieve", CppEditor),
- ("Publish", CppEditor),
-]
-
-#----------------------------------------------------------------------
-# different icons for the collapsed/expanded states.
-# Taken from standard Windows XP collapsed/expanded states.
-#----------------------------------------------------------------------
-
-def GetCollapsedIconData():
- return \
-'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
-\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
-\x00\x01\x8eIDAT8\x8d\xa5\x93-n\xe4@\x10\x85?g\x03\n6lh)\xc4\xd2\x12\xc3\x81\
-\xd6\xa2I\x90\x154\xb9\x81\x8f1G\xc8\x11\x16\x86\xcd\xa0\x99F\xb3A\x91\xa1\
-\xc9J&\x96L"5lX\xcc\x0bl\xf7v\xb2\x7fZ\xa5\x98\xebU\xbdz\xf5\\\x9deW\x9f\xf8\
-H\\\xbfO|{y\x9dT\x15P\x04\x01\x01UPUD\x84\xdb/7YZ\x9f\xa5\n\xce\x97aRU\x8a\
-\xdc`\xacA\x00\x04P\xf0!0\xf6\x81\xa0\xf0p\xff9\xfb\x85\xe0|\x19&T)K\x8b\x18\
-\xf9\xa3\xe4\xbe\xf3\x8c^#\xc9\xd5\n\xa8*\xc5?\x9a\x01\x8a\xd2b\r\x1cN\xc3\
-\x14\t\xce\x97a\xb2F0Ks\xd58\xaa\xc6\xc5\xa6\xf7\xdfya\xe7\xbdR\x13M2\xf9\
-\xf9qKQ\x1fi\xf6-\x00~T\xfac\x1dq#\x82,\xe5q\x05\x91D\xba@\xefj\xba1\xf0\xdc\
-zzW\xcff&\xb8,\x89\xa8@Q\xd6\xaaf\xdfRm,\xee\xb1BDxr#\xae\xf5|\xddo\xd6\xe2H\
-\x18\x15\x84\xa0q@]\xe54\x8d\xa3\xedf\x05M\xe3\xd8Uy\xc4\x15\x8d\xf5\xd7\x8b\
-~\x82\x0fh\x0e"\xb0\xad,\xee\xb8c\xbb\x18\xe7\x8e;6\xa5\x89\x04\xde\xff\x1c\
-\x16\xef\xe0p\xfa>\x19\x11\xca\x8d\x8d\xe0\x93\x1b\x01\xd8m\xf3(;x\xa5\xef=\
-\xb7w\xf3\x1d$\x7f\xc1\xe0\xbd\xa7\xeb\xa0(,"Kc\x12\xc1+\xfd\xe8\tI\xee\xed)\
-\xbf\xbcN\xc1{D\x04k\x05#\x12\xfd\xf2a\xde[\x81\x87\xbb\xdf\x9cr\x1a\x87\xd3\
-0)\xba>\x83\xd5\xb97o\xe0\xaf\x04\xff\x13?\x00\xd2\xfb\xa9`z\xac\x80w\x00\
-\x00\x00\x00IEND\xaeB`\x82'
-
-def GetCollapsedIconBitmap():
- return wx.BitmapFromImage(GetCollapsedIconImage())
-
-def GetCollapsedIconImage():
- import cStringIO
- stream = cStringIO.StringIO(GetCollapsedIconData())
- return wx.ImageFromStream(stream)
-
-#----------------------------------------------------------------------
-def GetExpandedIconData():
- return \
-'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
-\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
-\x00\x01\x9fIDAT8\x8d\x95\x93\xa1\x8e\xdc0\x14EO\xb2\xc4\xd0\xd2\x12\xb7(mI\
-\xa4%V\xd1lQT4[4-\x9a\xfe\xc1\xc2|\xc6\xc2~BY\x83:A3E\xd3\xa0*\xa4\xd2\x90H!\
-\x95\x0c\r\r\x1fK\x81g\xb2\x99\x84\xb4\x0fY\xd6\xbb\xc7\xf7>=\'Iz\xc3\xbcv\
-\xfbn\xb8\x9c\x15 \xe7\xf3\xc7\x0fw\xc9\xbc7\x99\x03\x0e\xfbn0\x99F+\x85R\
-\x80RH\x10\x82\x08\xde\x05\x1ef\x90+\xc0\xe1\xd8\ryn\xd0Z-\\A\xb4\xd2\xf7\
-\x9e\xfbwoF\xc8\x088\x1c\xbbae\xb3\xe8y&\x9a\xdf\xf5\xbd\xe7\xfem\x84\xa4\
-\x97\xccYf\x16\x8d\xdb\xb2a]\xfeX\x18\xc9s\xc3\xe1\x18\xe7\x94\x12cb\xcc\xb5\
-\xfa\xb1l8\xf5\x01\xe7\x84\xc7\xb2Y@\xb2\xcc0\x02\xb4\x9a\x88%\xbe\xdc\xb4\
-\x9e\xb6Zs\xaa74\xadg[6\x88<\xb7]\xc6\x14\x1dL\x86\xe6\x83\xa0\x81\xba\xda\
-\x10\x02x/\xd4\xd5\x06\r\x840!\x9c\x1fM\x92\xf4\x86\x9f\xbf\xfe\x0c\xd6\x9ae\
-\xd6u\x8d \xf4\xf5\x165\x9b\x8f\x04\xe1\xc5\xcb\xdb$\x05\x90\xa97@\x04lQas\
-\xcd*7\x14\xdb\x9aY\xcb\xb8\\\xe9E\x10|\xbc\xf2^\xb0E\x85\xc95_\x9f\n\xaa/\
-\x05\x10\x81\xce\xc9\xa8\xf6>\x13\xc0n\xff{PJ\xc5\xfdP\x11""<\xbc\
-\xff\x87\xdf\xf8\xbf\xf5\x17FF\xaf\x8f\x8b\xd3\xe6K\x00\x00\x00\x00IEND\xaeB\
-`\x82'
-
-def GetExpandedIconBitmap():
- return wx.BitmapFromImage(GetExpandedIconImage())
-
-def GetExpandedIconImage():
- import cStringIO
- stream = cStringIO.StringIO(GetExpandedIconData())
- return wx.ImageFromStream(stream)
-
-class FoldPanelCaption(wx.lib.buttons.GenBitmapTextToggleButton):
-
- def GetBackgroundBrush(self, dc):
- colBg = self.GetBackgroundColour()
- brush = wx.Brush(colBg, wx.SOLID)
- if self.style & wx.BORDER_NONE:
- myAttr = self.GetDefaultAttributes()
- parAttr = self.GetParent().GetDefaultAttributes()
- myDef = colBg == myAttr.colBg
- parDef = self.GetParent().GetBackgroundColour() == parAttr.colBg
- if myDef and parDef:
- if wx.Platform == "__WXMAC__":
- brush.MacSetTheme(1) # 1 == kThemeBrushDialogBackgroundActive
- elif wx.Platform == "__WXMSW__":
- if self.DoEraseBackground(dc):
- brush = None
- elif myDef and not parDef:
- colBg = self.GetParent().GetBackgroundColour()
- brush = wx.Brush(colBg, wx.SOLID)
- return brush
-
- def DrawLabel(self, dc, width, height, dx=0, dy=0):
- bmp = self.bmpLabel
- if bmp is not None: # if the bitmap is used
- if self.bmpDisabled and not self.IsEnabled():
- bmp = self.bmpDisabled
- if self.bmpFocus and self.hasFocus:
- bmp = self.bmpFocus
- if self.bmpSelected and not self.up:
- bmp = self.bmpSelected
- bw,bh = bmp.GetWidth(), bmp.GetHeight()
- hasMask = bmp.GetMask() is not None
- else:
- bw = bh = 0 # no bitmap -> size is zero
-
- dc.SetFont(self.GetFont())
- if self.IsEnabled():
- dc.SetTextForeground(self.GetForegroundColour())
- else:
- dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
-
- label = self.GetLabel()
- tw, th = dc.GetTextExtent(label) # size of text
-
- if bmp is not None:
- dc.DrawBitmap(bmp, width - bw - 2, (height-bh)/2, hasMask) # draw bitmap if available
-
- dc.DrawText(label, 2, (height-th)/2) # draw the text
-
- dc.SetPen(wx.Pen(self.GetForegroundColour()))
- dc.SetBrush(wx.TRANSPARENT_BRUSH)
- dc.DrawRectangle(0, 0, width, height)
-
-[ID_CFILEEDITOR, ID_CFILEEDITORMAINSPLITTER,
- ID_CFILEEDITORCFILETREE, ID_CFILEEDITORPARTSOPENED,
-] = [wx.NewId() for _init_ctrls in range(4)]
-
-class CFileEditor(EditorPanel):
-
- def _init_Editor(self, prnt):
- self.Editor = wx.Panel(id=ID_CFILEEDITOR, parent=prnt, pos=wx.Point(0, 0),
- size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
-
- self.Panels = {}
- self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2 * len(CFILE_PARTS) + 1, vgap=0)
- self.MainSizer.AddGrowableCol(0)
-
- for idx, (name, panel_class) in enumerate(CFILE_PARTS):
- button_id = wx.NewId()
- button = FoldPanelCaption(id=button_id, name='FoldPanelCaption_%s' % name,
- label=name, bitmap=GetCollapsedIconBitmap(), parent=self.Editor, pos=wx.Point(0, 0),
- size=wx.Size(0, 20), style=wx.NO_BORDER|wx.ALIGN_LEFT)
- button.SetBitmapSelected(GetExpandedIconBitmap())
- button.Bind(wx.EVT_BUTTON, self.GenPanelButtonCallback(name), id=button_id)
- self.MainSizer.AddWindow(button, 0, border=0, flag=wx.TOP|wx.GROW)
-
- if panel_class == VariablesEditor:
- panel = VariablesEditor(self.Editor, self.ParentWindow, self.Controler)
- else:
- panel = panel_class(self.Editor, name, self.ParentWindow, self.Controler)
- self.MainSizer.AddWindow(panel, 0, border=0, flag=wx.BOTTOM|wx.GROW)
- panel.Hide()
-
- self.Panels[name] = {"button": button, "panel": panel, "expanded": False, "row": 2 * idx + 1}
-
- self.Spacer = wx.Panel(self.Editor, -1)
- self.SpacerExpanded = True
- self.MainSizer.AddWindow(self.Spacer, 0, border=0, flag=wx.GROW)
-
- self.MainSizer.AddGrowableRow(2 * len(CFILE_PARTS))
-
- self.Editor.SetSizer(self.MainSizer)
-
- def __init__(self, parent, controler, window):
- EditorPanel.__init__(self, parent, "", window, controler)
-
- img = wx.Bitmap(self.Controler.GetIconPath("Cfile.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
- self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
-
- def __del__(self):
- self.Controler.OnCloseEditor(self)
-
- def GetTitle(self):
- fullname = self.Controler.PlugFullName()
- if not self.Controler.CFileIsSaved():
- return "~%s~" % fullname
- return fullname
-
- def GetBufferState(self):
- return self.Controler.GetBufferState()
-
- def Undo(self):
- self.Controler.LoadPrevious()
- self.RefreshView()
-
- def Redo(self):
- self.Controler.LoadNext()
- self.RefreshView()
-
- def HasNoModel(self):
- return False
-
- def RefreshView(self):
- for infos in self.Panels.itervalues():
- infos["panel"].RefreshView()
-
- def GenPanelButtonCallback(self, name):
- def PanelButtonCallback(event):
- self.TogglePanel(name)
- return PanelButtonCallback
-
- def ExpandPanel(self, name):
- infos = self.Panels.get(name, None)
- if infos is not None and not infos["expanded"]:
- infos["expanded"] = True
- infos["button"].SetToggle(True)
- infos["panel"].Show()
- self.MainSizer.AddGrowableRow(infos["row"])
-
- self.RefreshSizerLayout()
-
- def CollapsePanel(self, name):
- infos = self.Panels.get(name, None)
- if infos is not None and infos["expanded"]:
- infos["expanded"] = False
- infos["button"].SetToggle(False)
- infos["panel"].Hide()
- self.MainSizer.RemoveGrowableRow(infos["row"])
-
- self.RefreshSizerLayout()
-
- def TogglePanel(self, name):
- infos = self.Panels.get(name, None)
- if infos is not None:
- infos["expanded"] = not infos["expanded"]
- infos["button"].SetToggle(infos["expanded"])
- if infos["expanded"]:
- infos["panel"].Show()
- self.MainSizer.AddGrowableRow(infos["row"])
- else:
- infos["panel"].Hide()
- self.MainSizer.RemoveGrowableRow(infos["row"])
-
- self.RefreshSizerLayout()
-
- def RefreshSizerLayout(self):
- expand_spacer = True
- for infos in self.Panels.itervalues():
- expand_spacer = expand_spacer and not infos["expanded"]
-
- if self.SpacerExpanded != expand_spacer:
- self.SpacerExpanded = expand_spacer
- if expand_spacer:
- self.Spacer.Show()
- self.MainSizer.AddGrowableRow(2 * len(CFILE_PARTS))
- else:
- self.Spacer.Hide()
- self.MainSizer.RemoveGrowableRow(2 * len(CFILE_PARTS))
-
- self.MainSizer.Layout()
-
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/c_ext/README
--- a/plugins/c_ext/README Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-C extension
\ No newline at end of file
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/c_ext/__init__.py
--- a/plugins/c_ext/__init__.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-from c_ext import *
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/c_ext/c_ext.py
--- a/plugins/c_ext/c_ext.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,315 +0,0 @@
-import wx
-import os
-from xml.dom import minidom
-import cPickle
-
-from xmlclass import *
-
-from plugger import PlugTemplate, opjimg
-from CFileEditor import CFileEditor
-from PLCControler import PLCControler, UndoBuffer, LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
-
-CFileClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "cext_xsd.xsd"))
-
-TYPECONVERSION = {"BOOL" : "X", "SINT" : "B", "INT" : "W", "DINT" : "D", "LINT" : "L",
- "USINT" : "B", "UINT" : "W", "UDINT" : "D", "ULINT" : "L", "REAL" : "D", "LREAL" : "L",
- "STRING" : "B", "BYTE" : "B", "WORD" : "W", "DWORD" : "D", "LWORD" : "L", "WSTRING" : "W"}
-
-class _Cfile:
- XSD = """
-
-
-
-
-
-
-
-
- """
- EditorType = CFileEditor
-
- def __init__(self):
- filepath = self.CFileName()
-
- self.CFile = CFileClasses["CFile"]()
- if os.path.isfile(filepath):
- xmlfile = open(filepath, 'r')
- tree = minidom.parse(xmlfile)
- xmlfile.close()
-
- for child in tree.childNodes:
- if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "CFile":
- self.CFile.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"])
- self.CreateCFileBuffer(True)
- else:
- self.CreateCFileBuffer(False)
- self.OnPlugSave()
-
- def CFileName(self):
- return os.path.join(self.PlugPath(), "cfile.xml")
-
- def GetBaseTypes(self):
- return self.GetPlugRoot().GetBaseTypes()
-
- def GetDataTypes(self, basetypes = False, only_locatables = False):
- return self.GetPlugRoot().GetDataTypes(basetypes=basetypes, only_locatables=only_locatables)
-
- def GetSizeOfType(self, type):
- return TYPECONVERSION.get(self.GetPlugRoot().GetBaseType(type), None)
-
- def SetVariables(self, variables):
- self.CFile.variables.setvariable([])
- for var in variables:
- variable = CFileClasses["variables_variable"]()
- variable.setname(var["Name"])
- variable.settype(var["Type"])
- variable.setclass(var["Class"])
- self.CFile.variables.appendvariable(variable)
-
- def GetVariables(self):
- datas = []
- for var in self.CFile.variables.getvariable():
- datas.append({"Name" : var.getname(), "Type" : var.gettype(), "Class" : var.getclass()})
- return datas
-
- def GetVariableLocationTree(self):
- '''See PlugTemplate.GetVariableLocationTree() for a description.'''
-
- current_location = ".".join(map(str, self.GetCurrentLocation()))
-
- vars = []
- input = memory = output = 0
- for var in self.CFile.variables.getvariable():
- var_size = self.GetSizeOfType(var.gettype())
- var_location = ""
- if var.getclass() == "input":
- var_class = LOCATION_VAR_INPUT
- if var_size is not None:
- var_location = "%%I%s%s.%d"%(var_size, current_location, input)
- input += 1
- elif var.getclass() == "memory":
- var_class = LOCATION_VAR_INPUT
- if var_size is not None:
- var_location = "%%M%s%s.%d"%(var_size, current_location, memory)
- memory += 1
- else:
- var_class = LOCATION_VAR_OUTPUT
- if var_size is not None:
- var_location = "%%Q%s%s.%d"%(var_size, current_location, output)
- output += 1
- vars.append({"name": var.getname(),
- "type": var_class,
- "size": var_size,
- "IEC_type": var.gettype(),
- "var_name": var.getname(),
- "location": var_location,
- "description": "",
- "children": []})
-
- return {"name": self.BaseParams.getName(),
- "type": LOCATION_PLUGIN,
- "location": self.GetFullIEC_Channel(),
- "children": vars}
-
- def SetPartText(self, name, text):
- if name == "Includes":
- self.CFile.includes.settext(text)
- elif name == "Globals":
- self.CFile.globals.settext(text)
- elif name == "Init":
- self.CFile.initFunction.settext(text)
- elif name == "CleanUp":
- self.CFile.cleanUpFunction.settext(text)
- elif name == "Retrieve":
- self.CFile.retrieveFunction.settext(text)
- elif name == "Publish":
- self.CFile.publishFunction.settext(text)
-
- def GetPartText(self, name):
- if name == "Includes":
- return self.CFile.includes.gettext()
- elif name == "Globals":
- return self.CFile.globals.gettext()
- elif name == "Init":
- return self.CFile.initFunction.gettext()
- elif name == "CleanUp":
- return self.CFile.cleanUpFunction.gettext()
- elif name == "Retrieve":
- return self.CFile.retrieveFunction.gettext()
- elif name == "Publish":
- return self.CFile.publishFunction.gettext()
- return ""
-
- PluginMethods = [
- {"bitmap" : os.path.join("images", "EditCfile"),
- "name" : _("Edit C File"),
- "tooltip" : _("Edit C File"),
- "method" : "_OpenView"},
- ]
-
- def PlugTestModified(self):
- return self.ChangesToSave or not self.CFileIsSaved()
-
- def OnPlugSave(self):
- filepath = self.CFileName()
-
- text = "\n"
- extras = {"xmlns":"http://www.w3.org/2001/XMLSchema",
- "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
- "xsi:schemaLocation" : "cext_xsd.xsd"}
- text += self.CFile.generateXMLText("CFile", 0, extras)
-
- xmlfile = open(filepath,"w")
- xmlfile.write(text.encode("utf-8"))
- xmlfile.close()
-
- self.MarkCFileAsSaved()
- return True
-
- def PlugGenerate_C(self, buildpath, locations):
- """
- Generate C code
- @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
- @param locations: List of complete variables locations \
- [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
- "NAME" : name of the variable (generally "__IW0_1_2" style)
- "DIR" : direction "Q","I" or "M"
- "SIZE" : size "X", "B", "W", "D", "L"
- "LOC" : tuple of interger for IEC location (0,1,2,...)
- }, ...]
- @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
- """
- current_location = self.GetCurrentLocation()
- # define a unique name for the generated C file
- location_str = "_".join(map(str, current_location))
-
- text = "/* Code generated by Beremiz c_ext plugin */\n\n"
-
- # Adding includes
- text += "/* User includes */\n"
- text += self.CFile.includes.gettext()
- text += "\n"
-
- text += """/* Beremiz c_ext plugin includes */
-#ifdef _WINDOWS_H
- #include "iec_types.h"
-#else
- #include "iec_std_lib.h"
-#endif
-
-"""
-
- # Adding variables
- vars = []
- inputs = memories = outputs = 0
- for variable in self.CFile.variables.variable:
- var = {"Name" : variable.getname(), "Type" : variable.gettype()}
- if variable.getclass() == "input":
- var["location"] = "__I%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, inputs)
- inputs += 1
- elif variable.getclass() == "memory":
- var["location"] = "__M%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, memories)
- memories += 1
- else:
- var["location"] = "__Q%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, outputs)
- outputs += 1
- vars.append(var)
- text += "/* Beremiz c_ext plugin user variables definition */\n"
- base_types = self.GetPlugRoot().GetBaseTypes()
- for var in vars:
- if var["Type"] in base_types:
- prefix = "IEC_"
- else:
- prefix = ""
- text += "%s%s beremiz%s;\n"%(prefix, var["Type"], var["location"])
- text += "%s%s *%s = &beremiz%s;\n"%(prefix, var["Type"], var["location"], var["location"])
- text += "/* User variables reference */\n"
- for var in vars:
- text += "#define %s beremiz%s\n"%(var["Name"], var["location"])
- text += "\n"
-
- # Adding user global variables and routines
- text += "/* User internal user variables and routines */\n"
- text += self.CFile.globals.gettext()
-
- # Adding Beremiz plugin functions
- text += "/* Beremiz plugin functions */\n"
- text += "int __init_%s(int argc,char **argv)\n{\n"%location_str
- text += self.CFile.initFunction.gettext()
- text += " return 0;\n"
- text += "\n}\n\n"
-
- text += "void __cleanup_%s(void)\n{\n"%location_str
- text += self.CFile.cleanUpFunction.gettext()
- text += "\n}\n\n"
-
- text += "void __retrieve_%s(void)\n{\n"%location_str
- text += self.CFile.retrieveFunction.gettext()
- text += "\n}\n\n"
-
- text += "void __publish_%s(void)\n{\n"%location_str
- text += self.CFile.publishFunction.gettext()
- text += "\n}\n\n"
-
- Gen_Cfile_path = os.path.join(buildpath, "CFile_%s.c"%location_str)
- cfile = open(Gen_Cfile_path,'w')
- cfile.write(text)
- cfile.close()
-
- matiec_flags = '"-I%s"'%os.path.abspath(self.GetPlugRoot().GetIECLibPath())
-
- return [(Gen_Cfile_path, str(self.CExtension.getCFLAGS() + matiec_flags))],str(self.CExtension.getLDFLAGS()),True
-
-
-#-------------------------------------------------------------------------------
-# Current Buffering Management Functions
-#-------------------------------------------------------------------------------
-
- """
- Return a copy of the cfile model
- """
- def Copy(self, model):
- return cPickle.loads(cPickle.dumps(model))
-
- def CreateCFileBuffer(self, saved):
- self.Buffering = False
- self.CFileBuffer = UndoBuffer(cPickle.dumps(self.CFile), saved)
-
- def BufferCFile(self):
- self.CFileBuffer.Buffering(cPickle.dumps(self.CFile))
-
- def StartBuffering(self):
- self.Buffering = True
-
- def EndBuffering(self):
- if self.Buffering:
- self.CFileBuffer.Buffering(cPickle.dumps(self.CFile))
- self.Buffering = False
-
- def MarkCFileAsSaved(self):
- self.EndBuffering()
- self.CFileBuffer.CurrentSaved()
-
- def CFileIsSaved(self):
- return self.CFileBuffer.IsCurrentSaved() and not self.Buffering
-
- def LoadPrevious(self):
- self.EndBuffering()
- self.CFile = cPickle.loads(self.CFileBuffer.Previous())
-
- def LoadNext(self):
- self.CFile = cPickle.loads(self.CFileBuffer.Next())
-
- def GetBufferState(self):
- first = self.CFileBuffer.IsFirst() and not self.Buffering
- last = self.CFileBuffer.IsLast()
- return not first, not last
-
-class RootClass:
-
- PlugChildsTypes = [("C_File",_Cfile, "C file")]
-
- def PlugGenerate_C(self, buildpath, locations):
- return [],"",False
-
-
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/c_ext/cext_xsd.xsd
--- a/plugins/c_ext/cext_xsd.xsd Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Formatted text according to parts of XHTML 1.1
-
-
-
-
-
-
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/canfestival/.cvsignore
--- a/plugins/canfestival/.cvsignore Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-*.pyc
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/canfestival/NetworkEditor.py
--- a/plugins/canfestival/NetworkEditor.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-import os, sys
-base_folder = os.path.split(sys.path[0])[0]
-CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
-
-import wx
-
-from subindextable import EditingPanel
-from networkedit import NetworkEditorTemplate
-from controls import EditorPanel
-
-[ID_NETWORKEDITOR,
-] = [wx.NewId() for _init_ctrls in range(1)]
-
-[ID_NETWORKEDITORPLUGINMENUADDSLAVE, ID_NETWORKEDITORPLUGINMENUREMOVESLAVE,
- ID_NETWORKEDITORPLUGINMENUMASTER,
-] = [wx.NewId() for _init_coll_PluginMenu_Items in range(3)]
-
-[ID_NETWORKEDITORMASTERMENUNODEINFOS, ID_NETWORKEDITORMASTERMENUDS301PROFILE,
- ID_NETWORKEDITORMASTERMENUDS302PROFILE, ID_NETWORKEDITORMASTERMENUDSOTHERPROFILE,
- ID_NETWORKEDITORMASTERMENUADD,
-] = [wx.NewId() for _init_coll_MasterMenu_Items in range(5)]
-
-[ID_NETWORKEDITORADDMENUSDOSERVER, ID_NETWORKEDITORADDMENUSDOCLIENT,
- ID_NETWORKEDITORADDMENUPDOTRANSMIT, ID_NETWORKEDITORADDMENUPDORECEIVE,
- ID_NETWORKEDITORADDMENUMAPVARIABLE, ID_NETWORKEDITORADDMENUUSERTYPE,
-] = [wx.NewId() for _init_coll_AddMenu_Items in range(6)]
-
-class NetworkEditor(EditorPanel, NetworkEditorTemplate):
-
- ID = ID_NETWORKEDITOR
-
- def _init_coll_MainSizer_Items(self, parent):
- parent.AddWindow(self.NetworkNodes, 0, border=5, flag=wx.GROW|wx.ALL)
-
- def _init_coll_MainSizer_Growables(self, parent):
- parent.AddGrowableCol(0)
- parent.AddGrowableRow(0)
-
- def _init_sizers(self):
- self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=1, vgap=0)
-
- self._init_coll_MainSizer_Items(self.MainSizer)
- self._init_coll_MainSizer_Growables(self.MainSizer)
-
- self.Editor.SetSizer(self.MainSizer)
-
- def _init_Editor(self, prnt):
- self.Editor = wx.Panel(id=-1, parent=prnt, pos=wx.Point(0, 0),
- size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
-
- NetworkEditorTemplate._init_ctrls(self, self.Editor)
-
- self._init_sizers()
-
- def __init__(self, parent, controler, window):
- EditorPanel.__init__(self, parent, "", window, controler)
- NetworkEditorTemplate.__init__(self, controler, window, False)
-
- img = wx.Bitmap(os.path.join(CanFestivalPath, "objdictgen", "networkedit.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
- self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
-
- self.RefreshNetworkNodes()
- self.RefreshBufferState()
-
- def __del__(self):
- self.Controler.OnCloseEditor(self)
-
- def GetPluginMenuItems(self):
- add_menu = [(wx.ITEM_NORMAL, (_('SDO Server'), ID_NETWORKEDITORADDMENUSDOSERVER, '', self.OnAddSDOServerMenu)),
- (wx.ITEM_NORMAL, (_('SDO Client'), ID_NETWORKEDITORADDMENUSDOCLIENT, '', self.OnAddSDOClientMenu)),
- (wx.ITEM_NORMAL, (_('PDO Transmit'), ID_NETWORKEDITORADDMENUPDOTRANSMIT, '', self.OnAddPDOTransmitMenu)),
- (wx.ITEM_NORMAL, (_('PDO Receive'), ID_NETWORKEDITORADDMENUPDORECEIVE, '', self.OnAddPDOReceiveMenu)),
- (wx.ITEM_NORMAL, (_('Map Variable'), ID_NETWORKEDITORADDMENUMAPVARIABLE, '', self.OnAddMapVariableMenu)),
- (wx.ITEM_NORMAL, (_('User Type'), ID_NETWORKEDITORADDMENUUSERTYPE, '', self.OnAddUserTypeMenu))]
-
- profile = self.Manager.GetCurrentProfileName()
- if profile not in ("None", "DS-301"):
- other_profile_text = _("%s Profile") % profile
- add_menu.append((wx.ITEM_SEPARATOR, None))
- for text, indexes in self.Manager.GetCurrentSpecificMenu():
- add_menu.append((wx.ITEM_NORMAL, (text, wx.NewId(), '', self.GetProfileCallBack(text))))
- else:
- other_profile_text = _('Other Profile')
-
- master_menu = [(wx.ITEM_NORMAL, (_('Node infos'), ID_NETWORKEDITORMASTERMENUNODEINFOS, '', self.OnNodeInfosMenu)),
- (wx.ITEM_NORMAL, (_('DS-301 Profile'), ID_NETWORKEDITORMASTERMENUDS301PROFILE, '', self.OnCommunicationMenu)),
- (wx.ITEM_NORMAL, (_('DS-302 Profile'), ID_NETWORKEDITORMASTERMENUDS302PROFILE, '', self.OnOtherCommunicationMenu)),
- (wx.ITEM_NORMAL, (other_profile_text, ID_NETWORKEDITORMASTERMENUDSOTHERPROFILE, '', self.OnEditProfileMenu)),
- (wx.ITEM_SEPARATOR, None),
- (add_menu, (_('Add'), ID_NETWORKEDITORMASTERMENUADD))]
-
- return [(wx.ITEM_NORMAL, (_('Add slave'), ID_NETWORKEDITORPLUGINMENUADDSLAVE, '', self.OnAddSlaveMenu)),
- (wx.ITEM_NORMAL, (_('Remove slave'), ID_NETWORKEDITORPLUGINMENUREMOVESLAVE, '', self.OnRemoveSlaveMenu)),
- (wx.ITEM_SEPARATOR, None),
- (master_menu, (_('Master'), ID_NETWORKEDITORPLUGINMENUMASTER))]
-
- def RefreshMainMenu(self):
- pass
-
- def RefreshPluginMenu(self, plugin_menu):
- plugin_menu.Enable(ID_NETWORKEDITORPLUGINMENUMASTER, self.NetworkNodes.GetSelection() == 0)
-
- def GetTitle(self):
- fullname = self.Controler.PlugFullName()
- if not self.Manager.CurrentIsSaved():
- return "~%s~" % fullname
- return fullname
-
- def RefreshView(self):
- self.RefreshCurrentIndexList()
-
- def RefreshBufferState(self):
- NetworkEditorTemplate.RefreshBufferState(self)
- self.ParentWindow.RefreshTitle()
- self.ParentWindow.RefreshFileMenu()
- self.ParentWindow.RefreshEditMenu()
- self.ParentWindow.RefreshPageTitles()
-
- def OnNodeSelectedChanged(self, event):
- NetworkEditorTemplate.OnNodeSelectedChanged(self, event)
- wx.CallAfter(self.ParentWindow.RefreshPluginMenu)
-
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/canfestival/README
--- a/plugins/canfestival/README Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-CANOpen
\ No newline at end of file
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/canfestival/SlaveEditor.py
--- a/plugins/canfestival/SlaveEditor.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-import os, sys
-base_folder = os.path.split(sys.path[0])[0]
-CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
-
-import wx
-
-from subindextable import EditingPanel
-from nodeeditor import NodeEditorTemplate
-from controls import EditorPanel
-
-[ID_SLAVEEDITORPLUGINMENUNODEINFOS, ID_SLAVEEDITORPLUGINMENUDS301PROFILE,
- ID_SLAVEEDITORPLUGINMENUDS302PROFILE, ID_SLAVEEDITORPLUGINMENUDSOTHERPROFILE,
- ID_SLAVEEDITORPLUGINMENUADD,
-] = [wx.NewId() for _init_coll_PluginMenu_Items in range(5)]
-
-[ID_SLAVEEDITORADDMENUSDOSERVER, ID_SLAVEEDITORADDMENUSDOCLIENT,
- ID_SLAVEEDITORADDMENUPDOTRANSMIT, ID_SLAVEEDITORADDMENUPDORECEIVE,
- ID_SLAVEEDITORADDMENUMAPVARIABLE, ID_SLAVEEDITORADDMENUUSERTYPE,
-] = [wx.NewId() for _init_coll_AddMenu_Items in range(6)]
-
-class SlaveEditor(EditorPanel, NodeEditorTemplate):
-
- def _init_Editor(self, prnt):
- self.Editor = EditingPanel(prnt, self, self.Controler, self.Editable)
-
- def __init__(self, parent, controler, window, editable=True):
- self.Editable = editable
- EditorPanel.__init__(self, parent, "", window, controler)
- NodeEditorTemplate.__init__(self, controler, window, False)
-
- img = wx.Bitmap(os.path.join(CanFestivalPath, "objdictgen", "networkedit.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
- self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
-
- def __del__(self):
- self.Controler.OnCloseEditor(self)
-
- def GetPluginMenuItems(self):
- if self.Editable:
- add_menu = [(wx.ITEM_NORMAL, (_('SDO Server'), ID_SLAVEEDITORADDMENUSDOSERVER, '', self.OnAddSDOServerMenu)),
- (wx.ITEM_NORMAL, (_('SDO Client'), ID_SLAVEEDITORADDMENUSDOCLIENT, '', self.OnAddSDOClientMenu)),
- (wx.ITEM_NORMAL, (_('PDO Transmit'), ID_SLAVEEDITORADDMENUPDOTRANSMIT, '', self.OnAddPDOTransmitMenu)),
- (wx.ITEM_NORMAL, (_('PDO Receive'), ID_SLAVEEDITORADDMENUPDORECEIVE, '', self.OnAddPDOReceiveMenu)),
- (wx.ITEM_NORMAL, (_('Map Variable'), ID_SLAVEEDITORADDMENUMAPVARIABLE, '', self.OnAddMapVariableMenu)),
- (wx.ITEM_NORMAL, (_('User Type'), ID_SLAVEEDITORADDMENUUSERTYPE, '', self.OnAddUserTypeMenu))]
-
- profile = self.Controler.GetCurrentProfileName()
- if profile not in ("None", "DS-301"):
- other_profile_text = _("%s Profile") % profile
- add_menu.append((wx.ITEM_SEPARATOR, None))
- for text, indexes in self.Manager.GetCurrentSpecificMenu():
- add_menu.append((wx.ITEM_NORMAL, (text, wx.NewId(), '', self.GetProfileCallBack(text))))
- else:
- other_profile_text = _('Other Profile')
-
- return [(wx.ITEM_NORMAL, (_('Node infos'), ID_SLAVEEDITORPLUGINMENUNODEINFOS, '', self.OnNodeInfosMenu)),
- (wx.ITEM_NORMAL, (_('DS-301 Profile'), ID_SLAVEEDITORPLUGINMENUDS301PROFILE, '', self.OnCommunicationMenu)),
- (wx.ITEM_NORMAL, (_('DS-302 Profile'), ID_SLAVEEDITORPLUGINMENUDS302PROFILE, '', self.OnOtherCommunicationMenu)),
- (wx.ITEM_NORMAL, (other_profile_text, ID_SLAVEEDITORPLUGINMENUDSOTHERPROFILE, '', self.OnEditProfileMenu)),
- (wx.ITEM_SEPARATOR, None),
- (add_menu, (_('Add'), ID_SLAVEEDITORPLUGINMENUADD))]
- return []
-
- def RefreshPluginMenu(self, plugin_menu):
- plugin_menu.Enable(ID_SLAVEEDITORPLUGINMENUDSOTHERPROFILE, False)
-
- def GetTitle(self):
- fullname = self.Controler.PlugFullName()
- if not self.Controler.CurrentIsSaved():
- return "~%s~" % fullname
- return fullname
-
- def RefreshView(self):
- self.Editor.RefreshIndexList()
-
- def RefreshCurrentIndexList(self):
- self.RefreshView()
-
- def RefreshBufferState(self):
- self.ParentWindow.RefreshTitle()
- self.ParentWindow.RefreshFileMenu()
- self.ParentWindow.RefreshEditMenu()
- self.ParentWindow.RefreshPageTitles()
-
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/canfestival/__init__.py
--- a/plugins/canfestival/__init__.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-from canfestival import *
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/canfestival/canfestival.py
--- a/plugins/canfestival/canfestival.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,484 +0,0 @@
-import os, sys
-base_folder = os.path.split(sys.path[0])[0]
-CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
-sys.path.append(os.path.join(CanFestivalPath, "objdictgen"))
-
-from nodelist import NodeList
-from nodemanager import NodeManager
-import config_utils, gen_cfile, eds_utils
-from networkedit import networkedit
-from objdictedit import objdictedit
-import canfestival_config as local_canfestival_config
-from plugger import PlugTemplate
-from commondialogs import CreateNodeDialog
-import wx
-
-from SlaveEditor import SlaveEditor
-from NetworkEditor import NetworkEditor
-
-from gnosis.xml.pickle import *
-from gnosis.xml.pickle.util import setParanoia
-setParanoia(0)
-
-if wx.Platform == '__WXMSW__':
- DEFAULT_SETTINGS = {
- "CAN_Driver": "can_tcp_win32",
- "CAN_Device": "127.0.0.1",
- "CAN_Baudrate": "125K",
- "Slave_NodeId": 2,
- "Master_NodeId": 1,
- }
-else:
- DEFAULT_SETTINGS = {
- "CAN_Driver": "../CanFestival-3/drivers/can_socket/libcanfestival_can_socket.so",
- "CAN_Device": "vcan0",
- "CAN_Baudrate": "125K",
- "Slave_NodeId": 2,
- "Master_NodeId": 1,
- }
-
-#--------------------------------------------------
-# SLAVE
-#--------------------------------------------------
-
-class _SlavePlug(NodeManager):
- XSD = """
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- """ % DEFAULT_SETTINGS
-
- EditorType = SlaveEditor
-
- def __init__(self):
- # TODO change netname when name change
- NodeManager.__init__(self)
- odfilepath = self.GetSlaveODPath()
- if(os.path.isfile(odfilepath)):
- self.OpenFileInCurrent(odfilepath)
- else:
- self.FilePath = ""
- dialog = CreateNodeDialog(None, wx.OK)
- dialog.Type.Enable(False)
- dialog.GenSYNC.Enable(False)
- if dialog.ShowModal() == wx.ID_OK:
- name, id, nodetype, description = dialog.GetValues()
- profile, filepath = dialog.GetProfile()
- NMT = dialog.GetNMTManagement()
- options = dialog.GetOptions()
- self.CreateNewNode(name, # Name - will be changed at build time
- id, # NodeID - will be changed at build time
- "slave", # Type
- description,# description
- profile, # profile
- filepath, # prfile filepath
- NMT, # NMT
- options) # options
- else:
- self.CreateNewNode("SlaveNode", # Name - will be changed at build time
- 0x00, # NodeID - will be changed at build time
- "slave", # Type
- "", # description
- "None", # profile
- "", # prfile filepath
- "heartbeat", # NMT
- []) # options
- dialog.Destroy()
- self.OnPlugSave()
-
- def GetSlaveODPath(self):
- return os.path.join(self.PlugPath(), 'slave.od')
-
- def GetCanDevice(self):
- return self.CanFestivalSlaveNode.getCan_Device()
-
- def _OpenView(self):
- PlugTemplate._OpenView(self)
- if self._View is not None:
- self._View.SetBusId(self.GetCurrentLocation())
-
- PluginMethods = [
- {"bitmap" : os.path.join("images", "NetworkEdit"),
- "name" : "Edit slave",
- "tooltip" : "Edit CanOpen slave with ObjdictEdit",
- "method" : "_OpenView"},
- ]
-
- def OnPlugClose(self):
- if self._View:
- self._View.Close()
-
- def PlugTestModified(self):
- return self.ChangesToSave or self.OneFileHasChanged()
-
- def OnPlugSave(self):
- return self.SaveCurrentInFile(self.GetSlaveODPath())
-
- def SetParamsAttribute(self, path, value):
- result = PlugTemplate.SetParamsAttribute(self, path, value)
-
- # Filter IEC_Channel and Name, that have specific behavior
- if path == "BaseParams.IEC_Channel" and self._View is not None:
- self._View.SetBusId(self.GetCurrentLocation())
-
- return result
-
- def PlugGenerate_C(self, buildpath, locations):
- """
- Generate C code
- @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
- @param locations: List of complete variables locations \
- [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
- "NAME" : name of the variable (generally "__IW0_1_2" style)
- "DIR" : direction "Q","I" or "M"
- "SIZE" : size "X", "B", "W", "D", "L"
- "LOC" : tuple of interger for IEC location (0,1,2,...)
- }, ...]
- @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
- """
- current_location = self.GetCurrentLocation()
- # define a unique name for the generated C file
- prefix = "_".join(map(str, current_location))
- Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix )
- # Create a new copy of the model
- slave = self.GetCurrentNodeCopy()
- slave.SetNodeName("OD_%s"%prefix)
- # allow access to local OD from Slave PLC
- pointers = config_utils.LocalODPointers(locations, current_location, slave)
- res = gen_cfile.GenerateFile(Gen_OD_path, slave, pointers)
- if res :
- raise Exception, res
- res = eds_utils.GenerateEDSFile(os.path.join(buildpath, "Slave_%s.eds"%prefix), slave)
- if res :
- raise Exception, res
- return [(Gen_OD_path,local_canfestival_config.getCFLAGS(CanFestivalPath))],"",False
-
- def LoadPrevious(self):
- self.LoadCurrentPrevious()
-
- def LoadNext(self):
- self.LoadCurrentNext()
-
- def GetBufferState(self):
- return self.GetCurrentBufferState()
-
-#--------------------------------------------------
-# MASTER
-#--------------------------------------------------
-
-class MiniNodeManager(NodeManager):
-
- def __init__(self, parent, filepath, fullname):
- NodeManager.__init__(self)
-
- self.OpenFileInCurrent(filepath)
-
- self.Parent = parent
- self.Fullname = fullname
-
- def OnCloseEditor(self, view):
- self.Parent.OnCloseEditor(view)
-
- def PlugFullName(self):
- return self.Fullname
-
- def GetBufferState(self):
- return self.GetCurrentBufferState()
-
-class _NodeListPlug(NodeList):
- XSD = """
-
-
-
-
-
-
-
-
-
-
- """ % DEFAULT_SETTINGS
-
- EditorType = NetworkEditor
-
- def __init__(self):
- manager = NodeManager()
- NodeList.__init__(self, manager)
- self.LoadProject(self.PlugPath())
- self.SetNetworkName(self.BaseParams.getName())
-
- def GetCanDevice(self):
- return self.CanFestivalNode.getCan_Device()
-
- def SetParamsAttribute(self, path, value):
- result = PlugTemplate.SetParamsAttribute(self, path, value)
-
- # Filter IEC_Channel and Name, that have specific behavior
- if path == "BaseParams.IEC_Channel" and self._View is not None:
- self._View.SetBusId(self.GetCurrentLocation())
- elif path == "BaseParams.Name":
- self.SetNetworkName(value)
-
- return result
-
- def _OpenView(self):
- PlugTemplate._OpenView(self)
- if self._View is not None:
- self._View.SetBusId(self.GetCurrentLocation())
-
- _GeneratedView = None
- def _ShowMasterGenerated(self):
- if self._GeneratedView is None:
- buildpath = self._getBuildPath()
- # Eventually create build dir
- if not os.path.exists(buildpath):
- self.GetPlugRoot().logger.write_error(_("Error: No PLC built\n"))
- return
-
- masterpath = os.path.join(buildpath, "MasterGenerated.od")
- if not os.path.exists(masterpath):
- self.GetPlugRoot().logger.write_error(_("Error: No Master generated\n"))
- return
-
- app_frame = self.GetPlugRoot().AppFrame
-
- manager = MiniNodeManager(self, masterpath, self.PlugFullName() + ".generated_master")
- self._GeneratedView = SlaveEditor(app_frame.TabsOpened, manager, app_frame, False)
-
- app_frame.EditProjectElement(self._GeneratedView, "MasterGenerated")
-
- def _CloseGenerateView(self):
- if self._GeneratedView is not None:
- app_frame = self.GetPlugRoot().AppFrame
- if app_frame is not None:
- app_frame.DeletePage(self._GeneratedView)
-
- PluginMethods = [
- {"bitmap" : os.path.join("images", "NetworkEdit"),
- "name" : _("Edit network"),
- "tooltip" : _("Edit CanOpen Network with NetworkEdit"),
- "method" : "_OpenView"},
- {"bitmap" : os.path.join("images", "ShowMaster"),
- "name" : _("Show Master"),
- "tooltip" : _("Show Master generated by config_utils"),
- "method" : "_ShowMasterGenerated"}
- ]
-
- def OnCloseEditor(self, view):
- PlugTemplate.OnCloseEditor(self, view)
- if self._GeneratedView == view:
- self._GeneratedView = None
-
- def OnPlugClose(self):
- PlugTemplate.OnPlugClose(self)
- self._CloseGenerateView()
- return True
-
- def PlugTestModified(self):
- return self.ChangesToSave or self.HasChanged()
-
- def OnPlugSave(self):
- self.SetRoot(self.PlugPath())
- return self.SaveProject() is None
-
- def PlugGenerate_C(self, buildpath, locations):
- """
- Generate C code
- @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
- @param locations: List of complete variables locations \
- [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
- "NAME" : name of the variable (generally "__IW0_1_2" style)
- "DIR" : direction "Q","I" or "M"
- "SIZE" : size "X", "B", "W", "D", "L"
- "LOC" : tuple of interger for IEC location (0,1,2,...)
- }, ...]
- @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
- """
- self._CloseGenerateView()
- current_location = self.GetCurrentLocation()
- # define a unique name for the generated C file
- prefix = "_".join(map(str, current_location))
- Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix )
- # Create a new copy of the model with DCF loaded with PDO mappings for desired location
- try:
- master, pointers = config_utils.GenerateConciseDCF(locations, current_location, self, self.CanFestivalNode.getSync_TPDOs(),"OD_%s"%prefix)
- except config_utils.PDOmappingException, e:
- raise Exception, e.message
- # Do generate C file.
- res = gen_cfile.GenerateFile(Gen_OD_path, master, pointers)
- if res :
- raise Exception, res
-
- file = open(os.path.join(buildpath, "MasterGenerated.od"), "w")
- dump(master, file)
- file.close()
-
- return [(Gen_OD_path,local_canfestival_config.getCFLAGS(CanFestivalPath))],"",False
-
- def LoadPrevious(self):
- self.Manager.LoadCurrentPrevious()
-
- def LoadNext(self):
- self.Manager.LoadCurrentNext()
-
- def GetBufferState(self):
- return self.Manager.GetCurrentBufferState()
-
-class RootClass:
- XSD = """
-
-
-
-
-
-
-
-
- """ % DEFAULT_SETTINGS
-
- PlugChildsTypes = [("CanOpenNode",_NodeListPlug, "CanOpen Master"),
- ("CanOpenSlave",_SlavePlug, "CanOpen Slave")]
- def GetParamsAttributes(self, path = None):
- infos = PlugTemplate.GetParamsAttributes(self, path = None)
- for element in infos:
- if element["name"] == "CanFestivalInstance":
- for child in element["children"]:
- if child["name"] == "CAN_Driver":
- DLL_LIST= getattr(local_canfestival_config,"DLL_LIST",None)
- if DLL_LIST is not None:
- child["type"] = DLL_LIST
- return infos
-
- def GetCanDriver(self):
- can_driver = self.CanFestivalInstance.getCAN_Driver()
- if sys.platform == 'win32':
- if self.CanFestivalInstance.getDebug_mode() and os.path.isfile(os.path.join("%s"%(can_driver + '_DEBUG.dll'))):
- can_driver += '_DEBUG.dll'
- else:
- can_driver += '.dll'
- return can_driver
-
- def PlugGenerate_C(self, buildpath, locations):
-
- format_dict = {"locstr" : "_".join(map(str,self.GetCurrentLocation())),
- "candriver" : self.GetCanDriver(),
- "nodes_includes" : "",
- "board_decls" : "",
- "nodes_init" : "",
- "nodes_open" : "",
- "nodes_stop" : "",
- "nodes_close" : "",
- "nodes_send_sync" : "",
- "nodes_proceed_sync" : "",
- "slavebootups" : "",
- "slavebootup_register" : "",
- "post_sync" : "",
- "post_sync_register" : "",
- }
- for child in self.IECSortedChilds():
- childlocstr = "_".join(map(str,child.GetCurrentLocation()))
- nodename = "OD_%s" % childlocstr
-
- # Try to get Slave Node
- child_data = getattr(child, "CanFestivalSlaveNode", None)
- if child_data is None:
- # Not a slave -> master
- child_data = getattr(child, "CanFestivalNode")
- # Apply sync setting
- format_dict["nodes_init"] += 'NODE_MASTER_INIT(%s, %s)\n '%(
- nodename,
- child_data.getNodeId())
- if child_data.getSync_TPDOs():
- format_dict["nodes_send_sync"] += 'NODE_SEND_SYNC(%s)\n '%(nodename)
- format_dict["nodes_proceed_sync"] += 'NODE_PROCEED_SYNC(%s)\n '%(nodename)
-
- # initialize and declare node boot status variables for post_SlaveBootup lookup
- SlaveIDs = child.GetSlaveIDs()
- if len(SlaveIDs) == 0:
- # define post_SlaveBootup lookup functions
- format_dict["slavebootups"] += (
- "static void %s_post_SlaveBootup(CO_Data* d, UNS8 nodeId){}\n"%(nodename))
- else:
- for id in SlaveIDs:
- format_dict["slavebootups"] += (
- "int %s_slave_%d_booted = 0;\n"%(nodename, id))
- # define post_SlaveBootup lookup functions
- format_dict["slavebootups"] += (
- "static void %s_post_SlaveBootup(CO_Data* d, UNS8 nodeId){\n"%(nodename)+
- " switch(nodeId){\n")
- # one case per declared node, mark node as booted
- for id in SlaveIDs:
- format_dict["slavebootups"] += (
- " case %d:\n"%(id)+
- " %s_slave_%d_booted = 1;\n"%(nodename, id)+
- " break;\n")
- format_dict["slavebootups"] += (
- " default:\n"+
- " break;\n"+
- " }\n"+
- " if( ")
- # expression to test if all declared nodes booted
- format_dict["slavebootups"] += " && ".join(["%s_slave_%d_booted"%(nodename, id) for id in SlaveIDs])
- format_dict["slavebootups"] += " )\n" + (
- " Master_post_SlaveBootup(d,nodeId);\n"+
- "}\n")
- # register previously declared func as post_SlaveBootup callback for that node
- format_dict["slavebootup_register"] += (
- "%s_Data.post_SlaveBootup = %s_post_SlaveBootup;\n"%(nodename,nodename))
- else:
- # Slave node
- align = child_data.getSync_Align()
- align_ratio=child_data.getSync_Align_Ratio()
- if align > 0:
- format_dict["post_sync"] += (
- "static int %s_CalCount = 0;\n"%(nodename)+
- "static void %s_post_sync(CO_Data* d){\n"%(nodename)+
- " if(%s_CalCount < %d){\n"%(nodename, align)+
- " %s_CalCount++;\n"%(nodename)+
- " align_tick(-1);\n"+
- " }else{\n"+
- " align_tick(%d);\n"%(align_ratio)+
- " }\n"+
- "}\n")
- format_dict["post_sync_register"] += (
- "%s_Data.post_sync = %s_post_sync;\n"%(nodename,nodename))
- format_dict["nodes_init"] += 'NODE_SLAVE_INIT(%s, %s)\n '%(
- nodename,
- child_data.getNodeId())
-
- # Include generated OD headers
- format_dict["nodes_includes"] += '#include "%s.h"\n'%(nodename)
- # Declare CAN channels according user filled config
- format_dict["board_decls"] += 'BOARD_DECL(%s, "%s", "%s")\n'%(
- nodename,
- child.GetCanDevice(),
- child_data.getCAN_Baudrate())
- format_dict["nodes_open"] += 'NODE_OPEN(%s)\n '%(nodename)
- format_dict["nodes_close"] += 'NODE_CLOSE(%s)\n '%(nodename)
- format_dict["nodes_stop"] += 'NODE_STOP(%s)\n '%(nodename)
-
- filename = os.path.join(os.path.split(__file__)[0],"cf_runtime.c")
- cf_main = open(filename).read() % format_dict
- cf_main_path = os.path.join(buildpath, "CF_%(locstr)s.c"%format_dict)
- f = open(cf_main_path,'w')
- f.write(cf_main)
- f.close()
-
- return [(cf_main_path, local_canfestival_config.getCFLAGS(CanFestivalPath))],local_canfestival_config.getLDFLAGS(CanFestivalPath), True
-
-
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/canfestival/cf_runtime.c
--- a/plugins/canfestival/cf_runtime.c Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-
-#include "canfestival.h"
-
-/* CanFestival nodes generated OD headers*/
-%(nodes_includes)s
-
-#define BOARD_DECL(nodename, busname, baudrate)\
- s_BOARD nodename##Board = {busname, baudrate};
-
-/* CAN channels declaration */
-%(board_decls)s
-
-/* Keep track of init level to cleanup correctly */
-static int init_level=0;
-/* Retrieve PLC cycle time */
-extern int common_ticktime__;
-
-/* Called once all NetworkEdit declares slaves have booted*/
-static void Master_post_SlaveBootup(CO_Data* d, UNS8 nodeId)
-{
- /* Put the master in operational mode */
- setState(d, Operational);
-
- /* Ask slave node to go in operational mode */
- masterSendNMTstateChange (d, 0, NMT_Start_Node);
-}
-
-/* Per master node slavebootup callbacks. Checks that
- * every node have booted before calling Master_post_SlaveBootup */
-%(slavebootups)s
-
-/* One slave node post_sync callback.
- * Used to align PLC tick-time on CANopen SYNC
- */
-%(post_sync)s
-
-#define NODE_FORCE_SYNC(nodename) \
- /* Artificially force sync state to 1 so that it is not started */\
- nodename##_Data.CurrentCommunicationState.csSYNC = -1;\
- /* Force sync period to common_ticktime__ so that other node can read it*/\
- *nodename##_Data.COB_ID_Sync = 0x40000080;\
- *nodename##_Data.Sync_Cycle_Period = common_ticktime__ * 1000;
-
-#define NODE_INIT(nodename, nodeid) \
- /* Defining the node Id */\
- setNodeId(&nodename##_Data, nodeid);\
- /* init */\
- setState(&nodename##_Data, Initialisation);
-
-#define NODE_MASTER_INIT(nodename, nodeid) \
- NODE_FORCE_SYNC(nodename) \
- NODE_INIT(nodename, nodeid)
-
-#define NODE_SLAVE_INIT(nodename, nodeid) \
- NODE_INIT(nodename, nodeid)
-
-void InitNodes(CO_Data* d, UNS32 id)
-{
- %(slavebootup_register)s
- %(post_sync_register)s
- %(nodes_init)s
-}
-
-#define NODE_STOP(nodename) \
- if(init_level-- > 0)\
- {\
- masterSendNMTstateChange(&nodename##_Data, 0, NMT_Reset_Node);\
- setState(&nodename##_Data, Stopped);\
- }
-
-void Exit(CO_Data* d, UNS32 id)
-{
- %(nodes_stop)s
-}
-
-#define NODE_CLOSE(nodename) \
- if(init_level_c-- > 0)\
- {\
- canClose(&nodename##_Data);\
- }
-
-void __cleanup_%(locstr)s(void)
-{
- // Stop timer thread
- if(init_level-- > 0){
- int init_level_c = init_level;
- StopTimerLoop(&Exit);
- %(nodes_close)s
- }
-
- TimerCleanup();
-}
-
-#ifndef stderr
-#define fprintf(...)
-#define fflush(...)
-#endif
-
-#define NODE_OPEN(nodename)\
- if(!canOpen(&nodename##Board,&nodename##_Data)){\
- fprintf(stderr,"Cannot open CAN intefrace %%s at speed %%s\n for CANopen node \"" #nodename "\"",nodename##Board.busname, nodename##Board.baudrate);\
- fflush(stderr);\
- return -1;\
- }\
- init_level++;
-
-/*************************** INIT *****************************************/
-int __init_%(locstr)s(int argc,char **argv)
-{
-#ifndef NOT_USE_DYNAMIC_LOADING
- if( !LoadCanDriver("%(candriver)s") ){
- fprintf(stderr, "Cannot load CAN interface library for CanFestival (%(candriver)s)\n");\
- fflush(stderr);\
- return -1;\
- }
-#endif
-
- TimerInit();
-
- %(nodes_open)s
-
- // Start timer thread
- StartTimerLoop(&InitNodes);
- init_level++;
- return 0;
-}
-
-#define NODE_SEND_SYNC(nodename)\
- sendSYNCMessage(&nodename##_Data);
-
-void __retrieve_%(locstr)s(void)
-{
- /* Locks the stack, so that no changes occurs while PLC access variables
- * TODO : implement buffers to avoid such a big lock
- * */
- EnterMutex();
- /* Send Sync */
- %(nodes_send_sync)s
-}
-
-#define NODE_PROCEED_SYNC(nodename)\
- proceedSYNC(&nodename##_Data);
-
-void __publish_%(locstr)s(void)
-{
- /* Process sync event */
- %(nodes_proceed_sync)s
- LeaveMutex();
-}
-
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/canfestival/config_utils.py
--- a/plugins/canfestival/config_utils.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,737 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-#This file is part of Beremiz, a Integrated Development Environment for
-#programming IEC 61131-3 automates supporting plcopen standard and CanFestival.
-#
-#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
-#
-#See COPYING file for copyrights details.
-#
-#This library is free software; you can redistribute it and/or
-#modify it under the terms of the GNU General Public
-#License as published by the Free Software Foundation; either
-#version 2.1 of the License, or (at your option) any later version.
-#
-#This library is distributed in the hope that it will be useful,
-#but WITHOUT ANY WARRANTY; without even the implied warranty of
-#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-#General Public License for more details.
-#
-#You should have received a copy of the GNU General Public
-#License along with this library; if not, write to the Free Software
-#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-from types import *
-
-# Translation between IEC types and Can Open types
-IECToCOType = {"BOOL":0x01, "SINT":0x02, "INT":0x03,"DINT":0x04,"LINT":0x10,
- "USINT":0x05,"UINT":0x06,"UDINT":0x07,"ULINT":0x1B,"REAL":0x08,
- "LREAL":0x11,"STRING":0x09,"BYTE":0x05,"WORD":0x06,"DWORD":0x07,
- "LWORD":0x1B,"WSTRING":0x0B}
-
-# Constants for PDO types
-RPDO = 1
-TPDO = 2
-
-SlavePDOType = {"I" : TPDO, "Q" : RPDO}
-InvertPDOType = {RPDO : TPDO, TPDO : RPDO}
-PDOTypeBaseIndex = {RPDO : 0x1400, TPDO : 0x1800}
-PDOTypeBaseCobId = {RPDO : 0x200, TPDO : 0x180}
-
-VariableIncrement = 0x100
-VariableStartIndex = {TPDO : 0x2000, RPDO : 0x4000}
-VariableDirText = {TPDO : "__I", RPDO : "__Q"}
-VariableTypeOffset = dict(zip(["","X","B","W","D","L"], range(6)))
-
-TrashVariables = [(1, 0x01), (8, 0x05), (16, 0x06), (32, 0x07), (64, 0x1B)]
-
-#-------------------------------------------------------------------------------
-# Specific exception for PDO mapping errors
-#-------------------------------------------------------------------------------
-
-class PDOmappingException(Exception):
- pass
-
-
-def LE_to_BE(value, size):
- """
- Convert Little Endian to Big Endian
- @param value: value expressed in integer
- @param size: number of bytes generated
- @return: a string containing the value converted
- """
-
- data = ("%" + str(size * 2) + "." + str(size * 2) + "X") % value
- list_car = [data[i:i+2] for i in xrange(0, len(data), 2)]
- list_car.reverse()
- return "".join([chr(int(car, 16)) for car in list_car])
-
-
-def GetNodePDOIndexes(node, type, parameters = False):
- """
- Find the PDO indexes of a node
- @param node: node
- @param type: type of PDO searched (RPDO or TPDO or both)
- @param parameters: indicate which indexes are expected (PDO paramaters : True or PDO mappings : False)
- @return: a list of indexes found
- """
-
- indexes = []
- if type & RPDO:
- indexes.extend([idx for idx in node.GetIndexes() if 0x1400 <= idx <= 0x15FF])
- if type & TPDO:
- indexes.extend([idx for idx in node.GetIndexes() if 0x1800 <= idx <= 0x19FF])
- if not parameters:
- return [idx + 0x200 for idx in indexes]
- else:
- return indexes
-
-
-def SearchNodePDOMapping(loc_infos, node):
- """
- Find the PDO indexes of a node
- @param node: node
- @param type: type of PDO searched (RPDO or TPDO or both)
- @param parameters: indicate which indexes are expected (PDO paramaters : True or PDO mappings : False)
- @return: a list of indexes found
- """
-
- model = (loc_infos["index"] << 16) + (loc_infos["subindex"] << 8)
-
- for PDOidx in GetNodePDOIndexes(node, loc_infos["pdotype"]):
- values = node.GetEntry(PDOidx)
- if values != None:
- for subindex, mapping in enumerate(values):
- if subindex != 0 and mapping & 0xFFFFFF00 == model:
- return PDOidx, subindex
- return None
-
-
-def GeneratePDOMappingDCF(idx, cobid, transmittype, pdomapping):
- """
- Build concise DCF value for configuring a PDO
- @param idx: index of PDO parameters
- @param cobid: PDO generated COB ID
- @param transmittype : PDO transmit type
- @param pdomapping: list of PDO mappings
- @return: a tuple of value and number of parameters to add to DCF
- """
-
- # Create entry for RPDO or TPDO parameters and Disable PDO
- dcfdata = LE_to_BE(idx, 2) + LE_to_BE(0x01, 1) + LE_to_BE(0x04, 4) + LE_to_BE(0x80000000 + cobid, 4)
- # Set Transmit type synchrone
- dcfdata += LE_to_BE(idx, 2) + LE_to_BE(0x02, 1) + LE_to_BE(0x01, 4) + LE_to_BE(transmittype, 1)
- # Re-Enable PDO
- # ---- INDEX ----- --- SUBINDEX ---- ----- SIZE ------ ------ DATA ------
- dcfdata += LE_to_BE(idx, 2) + LE_to_BE(0x01, 1) + LE_to_BE(0x04, 4) + LE_to_BE(cobid, 4)
- nbparams = 3
- if len(pdomapping) > 0:
- dcfdata += LE_to_BE(idx + 0x200, 2) + LE_to_BE(0x00, 1) + LE_to_BE(0x01, 4) + LE_to_BE(len(pdomapping), 1)
- nbparams += 1
- # Map Variables
- for subindex, (name, loc_infos) in enumerate(pdomapping):
- value = (loc_infos["index"] << 16) + (loc_infos["subindex"] << 8) + loc_infos["size"]
- dcfdata += LE_to_BE(idx + 0x200, 2) + LE_to_BE(subindex + 1, 1) + LE_to_BE(0x04, 4) + LE_to_BE(value, 4)
- nbparams += 1
- return dcfdata, nbparams
-
-class ConciseDCFGenerator:
-
- def __init__(self, nodelist, nodename):
- # Dictionary of location informations classed by name
- self.IECLocations = {}
- # Dictionary of location that have not been mapped yet
- self.LocationsNotMapped = {}
- # Dictionary of location informations classed by name
- self.MasterMapping = {}
- # List of COB IDs available
- self.ListCobIDAvailable = range(0x180, 0x580)
- # Dictionary of mapping value where unexpected variables are stored
- self.TrashVariables = {}
- # Dictionary of pointed variables
- self.PointedVariables = {}
-
- self.NodeList = nodelist
- self.Manager = self.NodeList.Manager
- self.MasterNode = self.Manager.GetCurrentNodeCopy()
- self.MasterNode.SetNodeName(nodename)
- self.PrepareMasterNode()
-
- def GetPointedVariables(self):
- return self.PointedVariables
-
- def RemoveUsedNodeCobId(self, node):
- """
- Remove all PDO COB ID used by the given node from the list of available COB ID
- @param node: node
- @return: a tuple of number of RPDO and TPDO for the node
- """
-
- # Get list of all node TPDO and RPDO indexes
- nodeRpdoIndexes = GetNodePDOIndexes(node, RPDO, True)
- nodeTpdoIndexes = GetNodePDOIndexes(node, TPDO, True)
-
- # Mark all the COB ID of the node already mapped PDO as not available
- for PdoIdx in nodeRpdoIndexes + nodeTpdoIndexes:
- pdo_cobid = node.GetEntry(PdoIdx, 0x01)
- # Extract COB ID, if PDO isn't active
- if pdo_cobid > 0x600 :
- pdo_cobid -= 0x80000000
- # Remove COB ID from the list of available COB ID
- if pdo_cobid in self.ListCobIDAvailable:
- self.ListCobIDAvailable.remove(pdo_cobid)
-
- return len(nodeRpdoIndexes), len(nodeTpdoIndexes)
-
-
- def PrepareMasterNode(self):
- """
- Add mandatory entries for DCF generation into MasterNode.
- """
-
- # Adding DCF entry into Master node
- if not self.MasterNode.IsEntry(0x1F22):
- self.MasterNode.AddEntry(0x1F22, 1, "")
- self.Manager.AddSubentriesToCurrent(0x1F22, 127, self.MasterNode)
-
- # Adding trash mappable variables for unused mapped datas
- idxTrashVariables = 0x2000 + self.MasterNode.GetNodeID()
- # Add an entry for storing unexpected all variable
- self.Manager.AddMapVariableToCurrent(idxTrashVariables, self.MasterNode.GetNodeName()+"_trashvariables", 3, len(TrashVariables), self.MasterNode)
- for subidx, (size, typeidx) in enumerate(TrashVariables):
- # Add a subentry for storing unexpected variable of this size
- self.Manager.SetCurrentEntry(idxTrashVariables, subidx + 1, "TRASH%d" % size, "name", None, self.MasterNode)
- self.Manager.SetCurrentEntry(idxTrashVariables, subidx + 1, typeidx, "type", None, self.MasterNode)
- # Store the mapping value for this entry
- self.TrashVariables[size] = (idxTrashVariables << 16) + ((subidx + 1) << 8) + size
-
- RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(self.MasterNode)
-
- # Store the indexes of the first RPDO and TPDO available for MasterNode
- self.CurrentPDOParamsIdx = {RPDO : 0x1400 + RPDOnumber, TPDO : 0x1800 + TPDOnumber}
-
- # Prepare MasterNode with all nodelist slaves
- for idx, (nodeid, nodeinfos) in enumerate(self.NodeList.SlaveNodes.items()):
- node = nodeinfos["Node"]
- node.SetNodeID(nodeid)
-
- RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(node)
-
- # Get Slave's default SDO server parameters
- RSDO_cobid = node.GetEntry(0x1200,0x01)
- if not RSDO_cobid:
- RSDO_cobid = 0x600 + nodeid
- TSDO_cobid = node.GetEntry(0x1200,0x02)
- if not TSDO_cobid:
- TSDO_cobid = 0x580 + nodeid
-
- # Configure Master's SDO parameters entries
- self.Manager.ManageEntriesOfCurrent([0x1280 + idx], [], self.MasterNode)
- self.MasterNode.SetEntry(0x1280 + idx, 0x01, RSDO_cobid)
- self.MasterNode.SetEntry(0x1280 + idx, 0x02, TSDO_cobid)
- self.MasterNode.SetEntry(0x1280 + idx, 0x03, nodeid)
-
-
- def GetMasterNode(self):
- """
- Return MasterNode.
- """
- return self.MasterNode
-
- def AddParamsToDCF(self, nodeid, data, nbparams):
- """
- Add entry to DCF, for the requested nodeID
- @param nodeid: id of the slave (int)
- @param data: data to add to slave DCF (string)
- @param nbparams: number of params added to slave DCF (int)
- """
- # Get current DCF for slave
- nodeDCF = self.MasterNode.GetEntry(0x1F22, nodeid)
-
- # Extract data and number of params in current DCF
- if nodeDCF != None and nodeDCF != '':
- tmpnbparams = [i for i in nodeDCF[:4]]
- tmpnbparams.reverse()
- nbparams += int(''.join(["%2.2x"%ord(i) for i in tmpnbparams]), 16)
- data = nodeDCF[4:] + data
-
- # Build new DCF
- dcf = LE_to_BE(nbparams, 0x04) + data
- # Set new DCF for slave
- self.MasterNode.SetEntry(0x1F22, nodeid, dcf)
-
- def GetEmptyPDO(self, nodeid, pdotype, start_index=None):
- """
- Search a not configured PDO for a slave
- @param node: the slave node object
- @param pdotype: type of PDO to generated (RPDO or TPDO)
- @param start_index: Index where search must start (default: None)
- @return tuple of PDO index, COB ID and number of subindex defined
- """
- # If no start_index defined, start with PDOtype base index
- if start_index is None:
- index = PDOTypeBaseIndex[pdotype]
- else:
- index = start_index
-
- # Search for all PDO possible index until find a configurable PDO
- # starting from start_index
- while index < PDOTypeBaseIndex[pdotype] + 0x200:
- values = self.NodeList.GetSlaveNodeEntry(nodeid, index + 0x200)
- if values != None and values[0] > 0:
- # Check that all subindex upper than 0 equal 0 => configurable PDO
- if reduce(lambda x, y: x and y, map(lambda x: x == 0, values[1:]), True):
- cobid = self.NodeList.GetSlaveNodeEntry(nodeid, index, 1)
- # If no COB ID defined in PDO, generate a new one (not used)
- if cobid == 0:
- if len(self.ListCobIDAvailable) == 0:
- return None
- # Calculate COB ID from standard values
- if index < PDOTypeBaseIndex[pdotype] + 4:
- cobid = PDOTypeBaseCobId[pdotype] + 0x100 * (index - PDOTypeBaseIndex[pdotype]) + nodeid
- if cobid not in self.ListCobIDAvailable:
- cobid = self.ListCobIDAvailable.pop(0)
- return index, cobid, values[0]
- index += 1
- return None
-
- def AddPDOMapping(self, nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs):
- """
- Record a new mapping request for a slave, and add related slave config to the DCF
- @param nodeid: id of the slave (int)
- @param pdotype: type of PDO to generated (RPDO or TPDO)
- @param pdomapping: list od variables to map with PDO
- """
- # Add an entry to MasterMapping
- self.MasterMapping[pdocobid] = {"type" : InvertPDOType[pdotype],
- "mapping" : [None] + [(loc_infos["type"], name) for name, loc_infos in pdomapping]}
-
- # Return the data to add to DCF
- if sync_TPDOs:
- return GeneratePDOMappingDCF(pdoindex, pdocobid, 0x01, pdomapping)
- else:
- return GeneratePDOMappingDCF(pdoindex, pdocobid, 0xFF, pdomapping)
- return 0, ""
-
- def GenerateDCF(self, locations, current_location, sync_TPDOs):
- """
- Generate Concise DCF of MasterNode for the locations list given
- @param locations: list of locations to be mapped
- @param current_location: tuple of the located prefixes not to be considered
- @param sync_TPDOs: indicate if TPDO must be synchronous
- """
-
- #-------------------------------------------------------------------------------
- # Verify that locations correspond to real slave variables
- #-------------------------------------------------------------------------------
-
- # Get list of locations check if exists and mappables -> put them in IECLocations
- for location in locations:
- COlocationtype = IECToCOType[location["IEC_TYPE"]]
- name = location["NAME"]
- if name in self.IECLocations:
- if self.IECLocations[name]["type"] != COlocationtype:
- raise PDOmappingException, _("Type conflict for location \"%s\"") % name
- else:
- # Get only the part of the location that concern this node
- loc = location["LOC"][len(current_location):]
- # loc correspond to (ID, INDEX, SUBINDEX [,BIT])
- if len(loc) not in (2, 3, 4):
- raise PDOmappingException, _("Bad location size : %s") % str(loc)
- elif len(loc) == 2:
- continue
-
- direction = location["DIR"]
-
- sizelocation = location["SIZE"]
-
- # Extract and check nodeid
- nodeid, index, subindex = loc[:3]
-
- # Check Id is in slave node list
- if nodeid not in self.NodeList.SlaveNodes.keys():
- raise PDOmappingException, _("Non existing node ID : %d (variable %s)") % (nodeid,name)
-
- # Get the model for this node (made from EDS)
- node = self.NodeList.SlaveNodes[nodeid]["Node"]
-
- # Extract and check index and subindex
- if not node.IsEntry(index, subindex):
- raise PDOmappingException, _("No such index/subindex (%x,%x) in ID : %d (variable %s)") % (index,subindex,nodeid,name)
-
- # Get the entry info
- subentry_infos = node.GetSubentryInfos(index, subindex)
-
- # If a PDO mappable
- if subentry_infos and subentry_infos["pdo"]:
- if sizelocation == "X" and len(loc) > 3:
- numbit = loc[3]
- elif sizelocation != "X" and len(loc) > 3:
- raise PDOmappingException, _("Cannot set bit offset for non bool '%s' variable (ID:%d,Idx:%x,sIdx:%x))") % (name,nodeid,index,subindex)
- else:
- numbit = None
-
- if location["IEC_TYPE"] != "BOOL" and subentry_infos["type"] != COlocationtype:
- raise PDOmappingException, _("Invalid type \"%s\"-> %d != %d for location\"%s\"") % (location["IEC_TYPE"], COlocationtype, subentry_infos["type"] , name)
-
- typeinfos = node.GetEntryInfos(COlocationtype)
- self.IECLocations[name] = {"type":COlocationtype, "pdotype":SlavePDOType[direction],
- "nodeid": nodeid, "index": index,"subindex": subindex,
- "bit": numbit, "size": typeinfos["size"], "sizelocation": sizelocation}
- else:
- raise PDOmappingException, _("Not PDO mappable variable : '%s' (ID:%d,Idx:%x,sIdx:%x))") % (name,nodeid,index,subindex)
-
- #-------------------------------------------------------------------------------
- # Search for locations already mapped
- #-------------------------------------------------------------------------------
-
- for name, locationinfos in self.IECLocations.items():
- node = self.NodeList.SlaveNodes[locationinfos["nodeid"]]["Node"]
-
- # Search if slave has a PDO mapping this locations
- result = SearchNodePDOMapping(locationinfos, node)
- if result != None:
- index, subindex = result
- # Get COB ID of the PDO
- cobid = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 1)
-
- # Add PDO to MasterMapping
- if cobid not in self.MasterMapping.keys():
- # Verify that PDO transmit type is conform to sync_TPDOs
- transmittype = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 2)
- if sync_TPDOs and transmittype != 0x01 or transmittype != 0xFF:
- if sync_TPDOs:
- # Change TransmitType to SYNCHRONE
- data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0x01, [])
- else:
- # Change TransmitType to ASYCHRONE
- data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0xFF, [])
-
- # Add entry to slave dcf to change transmit type of
- self.AddParamsToDCF(locationinfos["nodeid"], data, nbparams)
-
- mapping = [None]
- values = node.GetEntry(index)
- # Store the size of each entry mapped in PDO
- for value in values[1:]:
- if value != 0:
- mapping.append(value % 0x100)
- self.MasterMapping[cobid] = {"type" : InvertPDOType[locationinfos["pdotype"]], "mapping" : mapping}
-
- # Indicate that this PDO entry must be saved
- if locationinfos["bit"] is not None:
- if not isinstance(self.MasterMapping[cobid]["mapping"][subindex], ListType):
- self.MasterMapping[cobid]["mapping"][subindex] = [1] * self.MasterMapping[cobid]["mapping"][subindex]
- if locationinfos["bit"] < len(self.MasterMapping[cobid]["mapping"][subindex]):
- self.MasterMapping[cobid]["mapping"][subindex][locationinfos["bit"]] = (locationinfos["type"], name)
- else:
- self.MasterMapping[cobid]["mapping"][subindex] = (locationinfos["type"], name)
-
- else:
- # Add location to those that haven't been mapped yet
- if locationinfos["nodeid"] not in self.LocationsNotMapped.keys():
- self.LocationsNotMapped[locationinfos["nodeid"]] = {TPDO : [], RPDO : []}
- self.LocationsNotMapped[locationinfos["nodeid"]][locationinfos["pdotype"]].append((name, locationinfos))
-
- #-------------------------------------------------------------------------------
- # Build concise DCF for the others locations
- #-------------------------------------------------------------------------------
-
- for nodeid, locations in self.LocationsNotMapped.items():
- node = self.NodeList.SlaveNodes[nodeid]["Node"]
-
- # Initialize number of params and data to add to node DCF
- nbparams = 0
- dataparams = ""
-
- # Generate the best PDO mapping for each type of PDO
- for pdotype in (TPDO, RPDO):
- if len(locations[pdotype]) > 0:
- pdosize = 0
- pdomapping = []
- result = self.GetEmptyPDO(nodeid, pdotype)
- if result is None:
- raise PDOmappingException, _("Unable to define PDO mapping for node %02x") % nodeid
- pdoindex, pdocobid, pdonbparams = result
- for name, loc_infos in locations[pdotype]:
- pdosize += loc_infos["size"]
- # If pdo's size > 64 bits
- if pdosize > 64 or len(pdomapping) >= pdonbparams:
- # Generate a new PDO Mapping
- data, nbaddedparams = self.AddPDOMapping(nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs)
- dataparams += data
- nbparams += nbaddedparams
- pdosize = loc_infos["size"]
- pdomapping = [(name, loc_infos)]
- result = self.GetEmptyPDO(nodeid, pdotype, pdoindex + 1)
- if result is None:
- raise PDOmappingException, _("Unable to define PDO mapping for node %02x") % nodeid
- pdoindex, pdocobid, pdonbparams = result
- else:
- pdomapping.append((name, loc_infos))
- # If there isn't locations yet but there is still a PDO to generate
- if len(pdomapping) > 0:
- # Generate a new PDO Mapping
- data, nbaddedparams = self.AddPDOMapping(nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs)
- dataparams += data
- nbparams += nbaddedparams
-
- # Add number of params and data to node DCF
- self.AddParamsToDCF(nodeid, dataparams, nbparams)
-
- #-------------------------------------------------------------------------------
- # Master Node Configuration
- #-------------------------------------------------------------------------------
-
- # Generate Master's Configuration from informations stored in MasterMapping
- for cobid, pdo_infos in self.MasterMapping.items():
- # Get next PDO index in MasterNode for this PDO type
- current_idx = self.CurrentPDOParamsIdx[pdo_infos["type"]]
-
- # Search if there is already a PDO in MasterNode with this cob id
- for idx in GetNodePDOIndexes(self.MasterNode, pdo_infos["type"], True):
- if self.MasterNode.GetEntry(idx, 1) == cobid:
- current_idx = idx
-
- # Add a PDO to MasterNode if not PDO have been found
- if current_idx == self.CurrentPDOParamsIdx[pdo_infos["type"]]:
- addinglist = [current_idx, current_idx + 0x200]
- self.Manager.ManageEntriesOfCurrent(addinglist, [], self.MasterNode)
- self.MasterNode.SetEntry(current_idx, 0x01, cobid)
-
- # Increment the number of PDO for this PDO type
- self.CurrentPDOParamsIdx[pdo_infos["type"]] += 1
-
- # Change the transmit type of the PDO
- if sync_TPDOs:
- self.MasterNode.SetEntry(current_idx, 0x02, 0x01)
- else:
- self.MasterNode.SetEntry(current_idx, 0x02, 0xFF)
-
- mapping = []
- for item in pdo_infos["mapping"]:
- if isinstance(item, ListType):
- mapping.extend(item)
- else:
- mapping.append(item)
-
- # Add some subentries to PDO mapping if there is not enough
- if len(mapping) > 1:
- self.Manager.AddSubentriesToCurrent(current_idx + 0x200, len(mapping) - 1, self.MasterNode)
-
- # Generate MasterNode's PDO mapping
- for subindex, variable in enumerate(mapping):
- if subindex == 0:
- continue
- new_index = False
-
- if isinstance(variable, (IntType, LongType)):
- # If variable is an integer then variable is unexpected
- self.MasterNode.SetEntry(current_idx + 0x200, subindex, self.TrashVariables[variable])
- else:
- typeidx, varname = variable
- variable_infos = self.IECLocations[varname]
-
- # Calculate base index for storing variable
- mapvariableidx = VariableStartIndex[variable_infos["pdotype"]] + \
- VariableTypeOffset[variable_infos["sizelocation"]] * VariableIncrement + \
- variable_infos["nodeid"]
-
- # Generate entry name
- indexname = "%s%s%s_%d"%(VariableDirText[variable_infos["pdotype"]],
- variable_infos["sizelocation"],
- '_'.join(map(str,current_location)),
- variable_infos["nodeid"])
-
- # Search for an entry that has an empty subindex
- while mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000:
- # Entry doesn't exist
- if not self.MasterNode.IsEntry(mapvariableidx):
- # Add entry to MasterNode
- self.Manager.AddMapVariableToCurrent(mapvariableidx, "beremiz"+indexname, 3, 1, self.MasterNode)
- new_index = True
- nbsubentries = self.MasterNode.GetEntry(mapvariableidx, 0x00)
- else:
- # Get Number of subentries already defined
- nbsubentries = self.MasterNode.GetEntry(mapvariableidx, 0x00)
- # if entry is full, go to next entry possible or stop now
- if nbsubentries == 0xFF:
- mapvariableidx += 8 * VariableIncrement
- else:
- break
-
- # Verify that a not full entry has been found
- if mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000:
- # Generate subentry name
- if variable_infos["bit"] != None:
- subindexname = "%(index)d_%(subindex)d_%(bit)d"%variable_infos
- else:
- subindexname = "%(index)d_%(subindex)d"%variable_infos
- # If entry have just been created, no subentry have to be added
- if not new_index:
- self.Manager.AddSubentriesToCurrent(mapvariableidx, 1, self.MasterNode)
- nbsubentries += 1
- # Add informations to the new subentry created
- self.MasterNode.SetMappingEntry(mapvariableidx, nbsubentries, values = {"name" : subindexname})
- self.MasterNode.SetMappingEntry(mapvariableidx, nbsubentries, values = {"type" : typeidx})
-
- # Set value of the PDO mapping
- typeinfos = self.Manager.GetEntryInfos(typeidx)
- if typeinfos != None:
- value = (mapvariableidx << 16) + ((nbsubentries) << 8) + typeinfos["size"]
- self.MasterNode.SetEntry(current_idx + 0x200, subindex, value)
-
- # Add variable to pointed variables
- self.PointedVariables[(mapvariableidx, nbsubentries)] = "%s_%s"%(indexname, subindexname)
-
-def GenerateConciseDCF(locations, current_location, nodelist, sync_TPDOs, nodename):
- """
- Fills a CanFestival network editor model, with DCF with requested PDO mappings.
- @param locations: List of complete variables locations \
- [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
- "NAME" : name of the variable (generally "__IW0_1_2" style)
- "DIR" : direction "Q","I" or "M"
- "SIZE" : size "X", "B", "W", "D", "L"
- "LOC" : tuple of interger for IEC location (0,1,2,...)
- }, ...]
- @param nodelist: CanFestival network editor model
- @return: a modified copy of the given CanFestival network editor model
- """
-
- dcfgenerator = ConciseDCFGenerator(nodelist, nodename)
- dcfgenerator.GenerateDCF(locations, current_location, sync_TPDOs)
- masternode,pointers = dcfgenerator.GetMasterNode(), dcfgenerator.GetPointedVariables()
- # allow access to local OD from Master PLC
- pointers.update(LocalODPointers(locations, current_location, masternode))
- return masternode,pointers
-
-def LocalODPointers(locations, current_location, slave):
- IECLocations = {}
- pointers = {}
- for location in locations:
- COlocationtype = IECToCOType[location["IEC_TYPE"]]
- name = location["NAME"]
- if name in IECLocations:
- if IECLocations[name] != COlocationtype:
- raise PDOmappingException, _("Type conflict for location \"%s\"") % name
- else:
- # Get only the part of the location that concern this node
- loc = location["LOC"][len(current_location):]
- # loc correspond to (ID, INDEX, SUBINDEX [,BIT])
- if len(loc) not in (2, 3, 4):
- raise PDOmappingException, _("Bad location size : %s") % str(loc)
- elif len(loc) != 2:
- continue
-
- # Extract and check nodeid
- index, subindex = loc[:2]
-
- # Extract and check index and subindex
- if not slave.IsEntry(index, subindex):
- raise PDOmappingException, _("No such index/subindex (%x,%x) (variable %s)") % (index, subindex, name)
-
- # Get the entry info
- subentry_infos = slave.GetSubentryInfos(index, subindex)
- if subentry_infos["type"] != COlocationtype:
- raise PDOmappingException, _("Invalid type \"%s\"-> %d != %d for location\"%s\"") % (location["IEC_TYPE"], COlocationtype, subentry_infos["type"] , name)
-
- IECLocations[name] = COlocationtype
- pointers[(index, subindex)] = name
- return pointers
-
-if __name__ == "__main__":
- import os, sys, getopt
-
- def usage():
- print """
-Usage of config_utils.py test :
-
- %s [options]
-
-Options:
- --help (-h)
- Displays help informations for config_utils
-
- --reset (-r)
- Reset the reference result of config_utils test.
- Use with caution. Be sure that config_utils
- is currently working properly.
-"""%sys.argv[0]
-
- # Boolean that indicate if reference result must be redefined
- reset = False
-
- # Extract command options
- try:
- opts, args = getopt.getopt(sys.argv[1:], "hr", ["help","reset"])
- except getopt.GetoptError:
- # print help information and exit:
- usage()
- sys.exit(2)
-
- # Test each option
- for o, a in opts:
- if o in ("-h", "--help"):
- usage()
- sys.exit()
- elif o in ("-r", "--reset"):
- reset = True
-
- # Extract workspace base folder
- base_folder = sys.path[0]
- for i in xrange(3):
- base_folder = os.path.split(base_folder)[0]
- # Add CanFestival folder to search pathes
- sys.path.append(os.path.join(base_folder, "CanFestival-3", "objdictgen"))
-
- from nodemanager import *
- from nodelist import *
-
- # Open the test nodelist contained into test_config folder
- manager = NodeManager()
- nodelist = NodeList(manager)
- result = nodelist.LoadProject("test_config")
-
- # List of locations, we try to map for test
- locations = [{"IEC_TYPE":"BYTE","NAME":"__IB0_1_64_24576_1","DIR":"I","SIZE":"B","LOC":(0,1,64,24576,1)},
- {"IEC_TYPE":"INT","NAME":"__IW0_1_64_25601_2","DIR":"I","SIZE":"W","LOC":(0,1,64,25601,2)},
- {"IEC_TYPE":"INT","NAME":"__IW0_1_64_25601_3","DIR":"I","SIZE":"W","LOC":(0,1,64,25601,3)},
- {"IEC_TYPE":"INT","NAME":"__QW0_1_64_25617_2","DIR":"Q","SIZE":"W","LOC":(0,1,64,25617,1)},
- {"IEC_TYPE":"BYTE","NAME":"__IB0_1_64_24578_1","DIR":"I","SIZE":"B","LOC":(0,1,64,24578,1)},
- {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_1","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,1)},
- {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_2","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,2)},
- {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_3","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,3)},
- {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_4","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,4)},
- {"IEC_TYPE":"UDINT","NAME":"__ID0_1_4096_0","DIR":"I","SIZE":"D","LOC":(0,1,4096,0)}]
-
- # Generate MasterNode configuration
- try:
- masternode, pointedvariables = GenerateConciseDCF(locations, (0, 1), nodelist, True, "TestNode")
- except ValueError, message:
- print "%s\nTest Failed!"%message
- sys.exit()
-
- import pprint
- # Get Text corresponding to MasterNode
- result_node = masternode.PrintString()
- result_vars = pprint.pformat(pointedvariables)
- result = result_node + "\n********POINTERS*********\n" + result_vars + "\n"
-
- # If reset has been choosen
- if reset:
- # Write Text into reference result file
- testfile = open("test_config/result.txt", "w")
- testfile.write(result)
- testfile.close()
-
- print "Reset Successful!"
- else:
- import os
-
- testfile = open("test_config/result_tmp.txt", "w")
- testfile.write(result)
- testfile.close()
-
- os.system("diff test_config/result.txt test_config/result_tmp.txt")
- os.remove("test_config/result_tmp.txt")
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/canfestival/test_config/eds/PEAK MicroMod.eds
--- a/plugins/canfestival/test_config/eds/PEAK MicroMod.eds Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1289 +0,0 @@
-[FileInfo]
-CreatedBy=ESAcademy
-ModifiedBy=ESAcademy
-Description=PEAK MicroMod CANopenIA Generic
-CreationTime=09:41PM
-CreationDate=05-05-2003
-ModificationTime=05:05PM
-ModificationDate=03-23-2005
-FileName=C:\CANopenCT\Tests\PEAK MicroMod.eds
-FileVersion=1
-FileRevision=1
-EDSVersion=4
-
-[DeviceInfo]
-VendorName=PEAK System Technik
-VendorNumber=0x00000175
-ProductName=PEAK MicroMod CANopenIA Generic
-ProductNumber=0x00100000
-RevisionNumber=0x00010001
-OrderCode=na
-BaudRate_10=0
-BaudRate_20=0
-BaudRate_50=1
-BaudRate_125=1
-BaudRate_250=1
-BaudRate_500=1
-BaudRate_800=1
-BaudRate_1000=1
-SimpleBootUpMaster=0
-SimpleBootUpSlave=1
-Granularity=0
-DynamicChannelsSupported=0
-CompactPDO=0
-GroupMessaging=0
-NrOfRXPDO=4
-NrOfTXPDO=4
-LSS_Supported=0
-
-[DummyUsage]
-Dummy0001=0
-Dummy0002=0
-Dummy0003=0
-Dummy0004=0
-Dummy0005=1
-Dummy0006=1
-Dummy0007=1
-
-[Comments]
-Lines=0
-
-[MandatoryObjects]
-SupportedObjects=3
-1=0x1000
-2=0x1001
-3=0x1018
-
-[1000]
-ParameterName=Device Type
-ObjectType=0x7
-DataType=0x0007
-AccessType=ro
-DefaultValue=0x000F0191
-PDOMapping=0
-
-[1001]
-ParameterName=Error Register
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=0
-PDOMapping=0
-
-[1018]
-ParameterName=Identity Object
-ObjectType=0x9
-SubNumber=4
-
-[1018sub0]
-ParameterName=number of entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=3
-PDOMapping=0
-
-[1018sub1]
-ParameterName=Vendor ID
-ObjectType=0x7
-DataType=0x0007
-AccessType=ro
-DefaultValue=0x00000175
-PDOMapping=0
-
-[1018sub2]
-ParameterName=Product Code
-ObjectType=0x7
-DataType=0x0007
-AccessType=ro
-DefaultValue=0x00100000
-PDOMapping=0
-
-[1018sub3]
-ParameterName=Revision number
-ObjectType=0x7
-DataType=0x0007
-AccessType=ro
-DefaultValue=0x00010001
-PDOMapping=0
-
-[OptionalObjects]
-SupportedObjects=41
-1=0x1002
-2=0x1005
-3=0x1008
-4=0x1009
-5=0x100A
-6=0x100C
-7=0x100D
-8=0x1010
-9=0x1011
-10=0x1016
-11=0x1017
-12=0x1020
-13=0x1400
-14=0x1401
-15=0x1402
-16=0x1403
-17=0x1600
-18=0x1601
-19=0x1602
-20=0x1603
-21=0x1800
-22=0x1801
-23=0x1802
-24=0x1803
-25=0x1A00
-26=0x1A01
-27=0x1A02
-28=0x1A03
-29=0x1F50
-30=0x6000
-31=0x6002
-32=0x6200
-33=0x6202
-34=0x6206
-35=0x6207
-36=0x6401
-37=0x6411
-38=0x6423
-39=0x6426
-40=0x6443
-41=0x6444
-
-[1002]
-ParameterName=PEAK Status Register
-ObjectType=0x7
-DataType=0x0007
-AccessType=ro
-PDOMapping=0
-
-[1005]
-ParameterName=COB-ID SYNC
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x00000080
-PDOMapping=0
-
-[1008]
-ParameterName=Manufacturer Device Name
-ObjectType=0x7
-DataType=0x0009
-AccessType=const
-PDOMapping=0
-
-[1009]
-ParameterName=Manufacturer Hardware Version
-ObjectType=0x7
-DataType=0x0009
-AccessType=const
-PDOMapping=0
-
-[100a]
-ParameterName=Manufacturer Software Version
-ObjectType=0x7
-DataType=0x0009
-AccessType=const
-PDOMapping=0
-
-[100c]
-ParameterName=Guard Time
-ObjectType=0x7
-DataType=0x0006
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[100d]
-ParameterName=Life Time Factor
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0x00
-PDOMapping=0
-
-[1010]
-ParameterName=Store Parameter Field
-ObjectType=0x8
-SubNumber=2
-
-[1010sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=1
-PDOMapping=0
-
-[1010sub1]
-ParameterName=Save all Parameters
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-PDOMapping=0
-
-[1011]
-ParameterName=Restore Default Parameters
-ObjectType=0x8
-SubNumber=2
-
-[1011sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=1
-PDOMapping=0
-
-[1011sub1]
-ParameterName=Restore all Default Parameters
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-PDOMapping=0
-
-[1016]
-ParameterName=Consumer Heartbeat Time
-ObjectType=0x8
-SubNumber=4
-
-[1016sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=3
-PDOMapping=0
-LowLimit=0x1
-
-[1016sub1]
-ParameterName=Consumer Heartbeat Time
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1016sub2]
-ParameterName=Consumer Heartbeat Time
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1016sub3]
-ParameterName=Consumer Heartbeat Time
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1017]
-ParameterName=Producer Heartbeat Time
-ObjectType=0x7
-DataType=0x0006
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1020]
-ParameterName=Verify Configuration
-ObjectType=0x8
-SubNumber=3
-
-[1020sub0]
-ParameterName=Number of entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=2
-PDOMapping=0
-
-[1020sub1]
-ParameterName=Configuration date
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-PDOMapping=0
-
-[1020sub2]
-ParameterName=Configuration time
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-PDOMapping=0
-
-[1400]
-ParameterName=Receive PDO Communication Parameter
-ObjectType=0x9
-SubNumber=3
-
-[1400sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=2
-PDOMapping=0
-
-[1400sub1]
-ParameterName=COB-ID
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=$NODEID+0x200
-PDOMapping=0
-LowLimit=0x00000001
-HighLimit=0xFFFFFFFF
-
-[1400sub2]
-ParameterName=Transmission Type
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=255
-PDOMapping=0
-
-[1401]
-ParameterName=Receive PDO Communication Parameter
-ObjectType=0x9
-SubNumber=3
-
-[1401sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=2
-PDOMapping=0
-
-[1401sub1]
-ParameterName=COB-ID
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=$NODEID+0x300
-PDOMapping=0
-LowLimit=0x00000001
-HighLimit=0xFFFFFFFF
-
-[1401sub2]
-ParameterName=Transmission Type
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=255
-PDOMapping=0
-
-[1402]
-ParameterName=Receive PDO Communication Parameter
-ObjectType=0x9
-SubNumber=3
-
-[1402sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=2
-PDOMapping=0
-LowLimit=0x02
-HighLimit=0x05
-
-[1402sub1]
-ParameterName=COB-ID
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=$NODEID+0x80000400
-PDOMapping=0
-LowLimit=0x00000001
-HighLimit=0xFFFFFFFF
-
-[1402sub2]
-ParameterName=Transmission Type
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=255
-PDOMapping=0
-
-[1403]
-ParameterName=Receive PDO Communication Parameter
-ObjectType=0x9
-SubNumber=3
-
-[1403sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=2
-PDOMapping=0
-LowLimit=0x02
-HighLimit=0x05
-
-[1403sub1]
-ParameterName=COB-ID
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=$NODEID+0x80000500
-PDOMapping=0
-LowLimit=0x00000001
-HighLimit=0xFFFFFFFF
-
-[1403sub2]
-ParameterName=Transmission Type
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=255
-PDOMapping=0
-
-[1600]
-ParameterName=Receive PDO Mapping Parameter
-ObjectType=0x9
-SubNumber=2
-
-[1600sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=1
-PDOMapping=0
-
-[1600sub1]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x62000108
-PDOMapping=0
-
-[1601]
-ParameterName=Receive PDO Mapping Parameter
-ObjectType=0x9
-SubNumber=5
-
-[1601sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=4
-PDOMapping=0
-
-[1601sub1]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64110110
-PDOMapping=0
-
-[1601sub2]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64110210
-PDOMapping=0
-
-[1601sub3]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64110310
-PDOMapping=0
-
-[1601sub4]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64110410
-PDOMapping=0
-
-[1602]
-ParameterName=Receive PDO Mapping Parameter
-ObjectType=0x9
-SubNumber=1
-
-[1602sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1603]
-ParameterName=Receive PDO Mapping Parameter
-ObjectType=0x9
-SubNumber=1
-
-[1603sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1800]
-ParameterName=Transmit PDO Communication Parameter
-ObjectType=0x9
-SubNumber=5
-
-[1800sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=5
-PDOMapping=0
-LowLimit=0x02
-HighLimit=0x05
-
-[1800sub1]
-ParameterName=COB-ID
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=$NODEID+0x180
-PDOMapping=0
-LowLimit=0x00000001
-HighLimit=0xFFFFFFFF
-
-[1800sub2]
-ParameterName=Transmission Type
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=255
-PDOMapping=0
-
-[1800sub3]
-ParameterName=Inhibit Time
-ObjectType=0x7
-DataType=0x0006
-AccessType=rw
-DefaultValue=0x0000
-PDOMapping=0
-
-[1800sub5]
-ParameterName=Event Timer
-ObjectType=0x7
-DataType=0x0006
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1801]
-ParameterName=Transmit PDO Communication Parameter
-ObjectType=0x9
-SubNumber=5
-
-[1801sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=5
-PDOMapping=0
-LowLimit=0x02
-HighLimit=0x05
-
-[1801sub1]
-ParameterName=COB-ID
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=$NODEID+0x280
-PDOMapping=0
-LowLimit=0x00000001
-HighLimit=0xFFFFFFFF
-
-[1801sub2]
-ParameterName=Transmission Type
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=255
-PDOMapping=0
-
-[1801sub3]
-ParameterName=Inhibit Time
-ObjectType=0x7
-DataType=0x0006
-AccessType=rw
-DefaultValue=0x0000
-PDOMapping=0
-
-[1801sub5]
-ParameterName=Event Timer
-ObjectType=0x7
-DataType=0x0006
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1802]
-ParameterName=Transmit PDO Communication Parameter
-ObjectType=0x9
-SubNumber=5
-
-[1802sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=5
-PDOMapping=0
-LowLimit=0x02
-HighLimit=0x05
-
-[1802sub1]
-ParameterName=COB-ID
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=$NODEID+0x380
-PDOMapping=0
-LowLimit=0x00000001
-HighLimit=0xFFFFFFFF
-
-[1802sub2]
-ParameterName=Transmission Type
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=255
-PDOMapping=0
-
-[1802sub3]
-ParameterName=Inhibit Time
-ObjectType=0x7
-DataType=0x0006
-AccessType=rw
-DefaultValue=0x0000
-PDOMapping=0
-
-[1802sub5]
-ParameterName=Event Timer
-ObjectType=0x7
-DataType=0x0006
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1803]
-ParameterName=Transmit PDO Communication Parameter
-ObjectType=0x9
-SubNumber=5
-
-[1803sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=5
-PDOMapping=0
-LowLimit=0x02
-HighLimit=0x05
-
-[1803sub1]
-ParameterName=COB-ID
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=$NODEID+0x80000480
-PDOMapping=0
-LowLimit=0x00000001
-HighLimit=0xFFFFFFFF
-
-[1803sub2]
-ParameterName=Transmission Type
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=255
-PDOMapping=0
-
-[1803sub3]
-ParameterName=Inhibit Time
-ObjectType=0x7
-DataType=0x0006
-AccessType=rw
-DefaultValue=0x0000
-PDOMapping=0
-
-[1803sub5]
-ParameterName=Event Timer
-ObjectType=0x7
-DataType=0x0006
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1a00]
-ParameterName=Transmit PDO Mapping Parameter
-ObjectType=0x9
-SubNumber=2
-
-[1a00sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=1
-PDOMapping=0
-
-[1a00sub1]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x60000108
-PDOMapping=0
-
-[1a01]
-ParameterName=Transmit PDO Mapping Parameter
-ObjectType=0x9
-SubNumber=5
-
-[1a01sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=4
-PDOMapping=0
-
-[1a01sub1]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64010110
-PDOMapping=0
-
-[1a01sub2]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64010210
-PDOMapping=0
-
-[1a01sub3]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64010310
-PDOMapping=0
-
-[1a01sub4]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64010410
-PDOMapping=0
-
-[1a02]
-ParameterName=Transmit PDO Mapping Parameter
-ObjectType=0x9
-SubNumber=5
-
-[1a02sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=4
-PDOMapping=0
-
-[1a02sub1]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64010510
-PDOMapping=0
-
-[1a02sub2]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64010610
-PDOMapping=0
-
-[1a02sub3]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64010710
-PDOMapping=0
-
-[1a02sub4]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64010810
-PDOMapping=0
-
-[1a03]
-ParameterName=Transmit PDO Mapping Parameter
-ObjectType=0x9
-SubNumber=1
-
-[1a03sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1f50]
-ParameterName=Download Program Data
-ObjectType=0x8
-SubNumber=2
-
-[1f50sub0]
-ParameterName=Number of elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=3
-PDOMapping=0
-
-[1f50sub3]
-ParameterName=Download Program Data - HW Settings
-ObjectType=0x7
-DataType=0x000F
-AccessType=rw
-PDOMapping=0
-
-[6000]
-ParameterName=Read Digital Input 8-bit
-ObjectType=0x8
-SubNumber=2
-
-[6000sub0]
-ParameterName=Number of Elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=1
-PDOMapping=0
-
-[6000sub1]
-ParameterName=DigInput8_1
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-PDOMapping=1
-
-[6002]
-ParameterName=Polarity Digital Input
-ObjectType=0x8
-SubNumber=2
-
-[6002sub0]
-ParameterName=Number of Elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=1
-PDOMapping=0
-
-[6002sub1]
-ParameterName=Polarity8_1
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6200]
-ParameterName=Write Digital Output 8-bit
-ObjectType=0x8
-SubNumber=2
-
-[6200sub0]
-ParameterName=Number of elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=1
-PDOMapping=0
-
-[6200sub1]
-ParameterName=DigOutput8_1
-ObjectType=0x7
-DataType=0x0005
-AccessType=rww
-PDOMapping=1
-
-[6202]
-ParameterName=Polarity Digital Output
-ObjectType=0x8
-SubNumber=2
-
-[6202sub0]
-ParameterName=Number of Elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=1
-PDOMapping=0
-
-[6202sub1]
-ParameterName=Polarity8_1
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6206]
-ParameterName=Error Mode Digital Output
-ObjectType=0x8
-SubNumber=2
-
-[6206sub0]
-ParameterName=Number of elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=1
-PDOMapping=0
-
-[6206sub1]
-ParameterName=Error Mode 1
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6207]
-ParameterName=Error Value Digital Output
-ObjectType=0x8
-SubNumber=2
-
-[6207sub0]
-ParameterName=Number of elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=1
-PDOMapping=0
-
-[6207sub1]
-ParameterName=Error Value 1
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6401]
-ParameterName=Read Analog Input 16-bit
-ObjectType=0x8
-SubNumber=9
-
-[6401sub0]
-ParameterName=Number of elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=8
-PDOMapping=0
-
-[6401sub1]
-ParameterName=AnalogInput16_1
-ObjectType=0x7
-DataType=0x0003
-AccessType=ro
-PDOMapping=1
-
-[6401sub2]
-ParameterName=AnalogInput16_2
-ObjectType=0x7
-DataType=0x0003
-AccessType=ro
-PDOMapping=1
-
-[6401sub3]
-ParameterName=AnalogInput16_3
-ObjectType=0x7
-DataType=0x0003
-AccessType=ro
-PDOMapping=1
-
-[6401sub4]
-ParameterName=AnalogInput16_4
-ObjectType=0x7
-DataType=0x0003
-AccessType=ro
-PDOMapping=1
-
-[6401sub5]
-ParameterName=AnalogInput16_5
-ObjectType=0x7
-DataType=0x0003
-AccessType=ro
-PDOMapping=1
-
-[6401sub6]
-ParameterName=AnalogInput16_6
-ObjectType=0x7
-DataType=0x0003
-AccessType=ro
-PDOMapping=1
-
-[6401sub7]
-ParameterName=AnalogInput16_7
-ObjectType=0x7
-DataType=0x0003
-AccessType=ro
-PDOMapping=1
-
-[6401sub8]
-ParameterName=AnalogInput16_8
-ObjectType=0x7
-DataType=0x0003
-AccessType=ro
-PDOMapping=1
-
-[6411]
-ParameterName=Write Analog Output 16-bit
-ObjectType=0x8
-SubNumber=5
-
-[6411sub0]
-ParameterName=Number of elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=4
-PDOMapping=0
-
-[6411sub1]
-ParameterName=AnalogOutput16_1
-ObjectType=0x7
-DataType=0x0003
-AccessType=rww
-PDOMapping=1
-
-[6411sub2]
-ParameterName=AnalogOutput16_2
-ObjectType=0x7
-DataType=0x0003
-AccessType=rww
-PDOMapping=1
-
-[6411sub3]
-ParameterName=AnalogOutput16_3
-ObjectType=0x7
-DataType=0x0003
-AccessType=rww
-PDOMapping=1
-
-[6411sub4]
-ParameterName=AnalogOutput16_4
-ObjectType=0x7
-DataType=0x0003
-AccessType=rww
-PDOMapping=1
-
-[6423]
-ParameterName=Analog Input Global Interrupt
-ObjectType=0x7
-DataType=0x0001
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6426]
-ParameterName=Analog Input Interrupt Delta
-ObjectType=0x8
-SubNumber=9
-
-[6426sub0]
-ParameterName=NrOfObjects
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=8
-PDOMapping=0
-
-[6426sub1]
-ParameterName=Analog Input Delta 1
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6426sub2]
-ParameterName=Analog Input Delta 2
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6426sub3]
-ParameterName=Analog Input Delta 3
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6426sub4]
-ParameterName=Analog Input Delta 4
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6426sub5]
-ParameterName=Analog Input Delta 5
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6426sub6]
-ParameterName=Analog Input Delta 6
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6426sub7]
-ParameterName=Analog Input Delta 7
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6426sub8]
-ParameterName=Analog Input Delta 8
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6443]
-ParameterName=Error Mode Analog Output
-ObjectType=0x8
-SubNumber=5
-
-[6443sub0]
-ParameterName=Number of elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=4
-PDOMapping=0
-
-[6443sub1]
-ParameterName=Error Mode 1
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6443sub2]
-ParameterName=Error Mode 2
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6443sub3]
-ParameterName=Error Mode 3
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6443sub4]
-ParameterName=Error Mode 4
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6444]
-ParameterName=Error Value Analog Output
-ObjectType=0x8
-SubNumber=5
-
-[6444sub0]
-ParameterName=Number of elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=4
-PDOMapping=0
-
-[6444sub1]
-ParameterName=Error Value 1
-ObjectType=0x7
-DataType=0x0004
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6444sub2]
-ParameterName=Error Value 2
-ObjectType=0x7
-DataType=0x0004
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6444sub3]
-ParameterName=Error Value 3
-ObjectType=0x7
-DataType=0x0004
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6444sub4]
-ParameterName=Error Value 4
-ObjectType=0x7
-DataType=0x0004
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[ManufacturerObjects]
-SupportedObjects=0
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/canfestival/test_config/master.od
--- a/plugins/canfestival/test_config/master.od Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,314 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Read Inputs
-
-
-
-
-
-
- Read Inputs
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-master
-
-TestMaster
-
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/canfestival/test_config/nodelist.cpj
--- a/plugins/canfestival/test_config/nodelist.cpj Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-[TOPOLOGY]
-NetName=None
-Nodes=0x01
-Node64Present=0x01
-Node64Name=micromod
-Node64DCFName=PEAK MicroMod.eds
-EDSBaseName=eds
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/canfestival/test_config/result.txt
--- a/plugins/canfestival/test_config/result.txt Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,257 +0,0 @@
-1000 (Device Type): 12E
-1001 (Error Register): 0
-1005 (SYNC COB ID): 40000080
-1006 (Communication / Cycle Period): C350
-1016 (Consumer Heartbeat Time):
-1016 01 (Consumer Heartbeat Time): 4005DC
-1018 (Identity):
-1018 01 (Vendor ID): 0
-1018 02 (Product Code): 0
-1018 03 (Revision Number): 0
-1018 04 (Serial Number): 0
-1280 (Client SDO 1 Parameter):
-1280 01 (COB ID Client to Server (Transmit SDO)): 640
-1280 02 (COB ID Server to Client (Receive SDO)): 5C0
-1280 03 (Node ID of the SDO Server): 40
-1400 (Receive PDO 1 Parameter):
-1400 01 (COB ID used by PDO): 1C0
-1400 02 (Transmission Type): 1
-1400 03 (Inhibit Time): 0
-1400 04 (Compatibility Entry): 0
-1400 05 (Event Timer): 0
-1401 (Receive PDO 2 Parameter):
-1401 01 (COB ID used by PDO): 2C0
-1401 02 (Transmission Type): 1
-1401 03 (Inhibit Time): 0
-1401 04 (Compatibility Entry): 0
-1401 05 (Event Timer): 0
-1402 (Receive PDO 3 Parameter):
-1402 01 (COB ID used by PDO): 182
-1402 02 (Transmission Type): 1
-1402 03 (Inhibit Time): 0
-1402 04 (Compatibility Entry): 0
-1402 05 (Event Timer): 0
-1403 (Receive PDO 4 Parameter):
-1403 01 (COB ID used by PDO): 183
-1403 02 (Transmission Type): 1
-1403 03 (Inhibit Time): 0
-1403 04 (Compatibility Entry): 0
-1403 05 (Event Timer): 0
-1404 (Receive PDO 5 Parameter):
-1404 01 (COB ID used by PDO): 181
-1404 02 (Transmission Type): 1
-1404 03 (Inhibit Time): 0
-1404 04 (Compatibility Entry): 0
-1404 05 (Event Timer): 0
-1600 (Receive PDO 1 Mapping):
-1600 01 (PDO 1 Mapping for an application object 1): 22400108
-1600 02 (PDO 1 Mapping for an application object 2): 0
-1601 (Receive PDO 2 Mapping):
-1601 01 (PDO 2 Mapping for an application object 1): 20000310
-1601 02 (PDO 2 Mapping for an application object 2): 23400110
-1601 03 (PDO 2 Mapping for an application object 3): 23400210
-1601 04 (PDO 2 Mapping for an application object 4): 20000310
-1602 (Receive PDO 3 Mapping):
-1602 01 (PDO 3 Mapping for an application object 1): 24400120
-1602 02 (PDO 3 Mapping for an application object 2): 24400220
-1603 (Receive PDO 4 Mapping):
-1603 01 (PDO 4 Mapping for an application object 1): 24400320
-1604 (Receive PDO 5 Mapping):
-1604 01 (PDO 5 Mapping for an application object 1): 22400208
-1604 02 (PDO 5 Mapping for an application object 2): 24400420
-1800 (Transmit PDO 1 Parameter):
-1800 01 (COB ID used by PDO): {True:"$NODEID+0x%X80"%(base+1),False:0x80000000}[base<4]
-1800 02 (Transmission Type): 0
-1800 03 (Inhibit Time): 0
-1800 04 (Compatibility Entry): 0
-1800 05 (Event Timer): 0
-1801 (Transmit PDO 2 Parameter):
-1801 01 (COB ID used by PDO): 340
-1801 02 (Transmission Type): 1
-1801 03 (Inhibit Time): 0
-1801 04 (Compatibility Entry): 0
-1801 05 (Event Timer): 0
-1A00 (Transmit PDO 1 Mapping):
-1A00 01 (PDO 1 Mapping for a process data variable 1): 10010008
-1A01 (Transmit PDO 2 Mapping):
-1A01 01 (PDO 2 Mapping for a process data variable 1): 43400110
-1A01 02 (PDO 2 Mapping for a process data variable 2): 20000310
-1A01 03 (PDO 2 Mapping for a process data variable 3): 20000310
-1A01 04 (PDO 2 Mapping for a process data variable 4): 20000310
-1F22 (Concise DCF):
-1F22 01 (Concise DCF for Node 1):
-1F22 02 (Concise DCF for Node 2):
-1F22 03 (Concise DCF for Node 3):
-1F22 04 (Concise DCF for Node 4):
-1F22 05 (Concise DCF for Node 5):
-1F22 06 (Concise DCF for Node 6):
-1F22 07 (Concise DCF for Node 7):
-1F22 08 (Concise DCF for Node 8):
-1F22 09 (Concise DCF for Node 9):
-1F22 0A (Concise DCF for Node 10):
-1F22 0B (Concise DCF for Node 11):
-1F22 0C (Concise DCF for Node 12):
-1F22 0D (Concise DCF for Node 13):
-1F22 0E (Concise DCF for Node 14):
-1F22 0F (Concise DCF for Node 15):
-1F22 10 (Concise DCF for Node 16):
-1F22 11 (Concise DCF for Node 17):
-1F22 12 (Concise DCF for Node 18):
-1F22 13 (Concise DCF for Node 19):
-1F22 14 (Concise DCF for Node 20):
-1F22 15 (Concise DCF for Node 21):
-1F22 16 (Concise DCF for Node 22):
-1F22 17 (Concise DCF for Node 23):
-1F22 18 (Concise DCF for Node 24):
-1F22 19 (Concise DCF for Node 25):
-1F22 1A (Concise DCF for Node 26):
-1F22 1B (Concise DCF for Node 27):
-1F22 1C (Concise DCF for Node 28):
-1F22 1D (Concise DCF for Node 29):
-1F22 1E (Concise DCF for Node 30):
-1F22 1F (Concise DCF for Node 31):
-1F22 20 (Concise DCF for Node 32):
-1F22 21 (Concise DCF for Node 33):
-1F22 22 (Concise DCF for Node 34):
-1F22 23 (Concise DCF for Node 35):
-1F22 24 (Concise DCF for Node 36):
-1F22 25 (Concise DCF for Node 37):
-1F22 26 (Concise DCF for Node 38):
-1F22 27 (Concise DCF for Node 39):
-1F22 28 (Concise DCF for Node 40):
-1F22 29 (Concise DCF for Node 41):
-1F22 2A (Concise DCF for Node 42):
-1F22 2B (Concise DCF for Node 43):
-1F22 2C (Concise DCF for Node 44):
-1F22 2D (Concise DCF for Node 45):
-1F22 2E (Concise DCF for Node 46):
-1F22 2F (Concise DCF for Node 47):
-1F22 30 (Concise DCF for Node 48):
-1F22 31 (Concise DCF for Node 49):
-1F22 32 (Concise DCF for Node 50):
-1F22 33 (Concise DCF for Node 51):
-1F22 34 (Concise DCF for Node 52):
-1F22 35 (Concise DCF for Node 53):
-1F22 36 (Concise DCF for Node 54):
-1F22 37 (Concise DCF for Node 55):
-1F22 38 (Concise DCF for Node 56):
-1F22 39 (Concise DCF for Node 57):
-1F22 3A (Concise DCF for Node 58):
-1F22 3B (Concise DCF for Node 59):
-1F22 3C (Concise DCF for Node 60):
-1F22 3D (Concise DCF for Node 61):
-1F22 3E (Concise DCF for Node 62):
-1F22 3F (Concise DCF for Node 63):
-1F22 40 (Concise DCF for Node 64): 23 arg defined
-1F22 40, arg 1: 1800 01 00000004 800001C0
-1F22 40, arg 2: 1800 02 00000001 01
-1F22 40, arg 3: 1800 01 00000004 000001C0
-1F22 40, arg 4: 1801 01 00000004 800002C0
-1F22 40, arg 5: 1801 02 00000001 01
-1F22 40, arg 6: 1801 01 00000004 000002C0
-1F22 40, arg 7: 1401 01 00000004 80000340
-1F22 40, arg 8: 1401 02 00000001 01
-1F22 40, arg 9: 1401 01 00000004 00000340
-1F22 40, arg 10: 1804 01 00000004 80000181
-1F22 40, arg 11: 1804 02 00000001 01
-1F22 40, arg 12: 1804 01 00000004 00000181
-1F22 40, arg 13: 1A04 01 00000004 60020108
-1F22 40, arg 14: 1A04 02 00000004 64260120
-1F22 40, arg 15: 1805 01 00000004 80000182
-1F22 40, arg 16: 1805 02 00000001 01
-1F22 40, arg 17: 1805 01 00000004 00000182
-1F22 40, arg 18: 1A05 01 00000004 64260220
-1F22 40, arg 19: 1A05 02 00000004 64260320
-1F22 40, arg 20: 1806 01 00000004 80000183
-1F22 40, arg 21: 1806 02 00000001 01
-1F22 40, arg 22: 1806 01 00000004 00000183
-1F22 40, arg 23: 1A06 01 00000004 64260420
-1F22 41 (Concise DCF for Node 65):
-1F22 42 (Concise DCF for Node 66):
-1F22 43 (Concise DCF for Node 67):
-1F22 44 (Concise DCF for Node 68):
-1F22 45 (Concise DCF for Node 69):
-1F22 46 (Concise DCF for Node 70):
-1F22 47 (Concise DCF for Node 71):
-1F22 48 (Concise DCF for Node 72):
-1F22 49 (Concise DCF for Node 73):
-1F22 4A (Concise DCF for Node 74):
-1F22 4B (Concise DCF for Node 75):
-1F22 4C (Concise DCF for Node 76):
-1F22 4D (Concise DCF for Node 77):
-1F22 4E (Concise DCF for Node 78):
-1F22 4F (Concise DCF for Node 79):
-1F22 50 (Concise DCF for Node 80):
-1F22 51 (Concise DCF for Node 81):
-1F22 52 (Concise DCF for Node 82):
-1F22 53 (Concise DCF for Node 83):
-1F22 54 (Concise DCF for Node 84):
-1F22 55 (Concise DCF for Node 85):
-1F22 56 (Concise DCF for Node 86):
-1F22 57 (Concise DCF for Node 87):
-1F22 58 (Concise DCF for Node 88):
-1F22 59 (Concise DCF for Node 89):
-1F22 5A (Concise DCF for Node 90):
-1F22 5B (Concise DCF for Node 91):
-1F22 5C (Concise DCF for Node 92):
-1F22 5D (Concise DCF for Node 93):
-1F22 5E (Concise DCF for Node 94):
-1F22 5F (Concise DCF for Node 95):
-1F22 60 (Concise DCF for Node 96):
-1F22 61 (Concise DCF for Node 97):
-1F22 62 (Concise DCF for Node 98):
-1F22 63 (Concise DCF for Node 99):
-1F22 64 (Concise DCF for Node 100):
-1F22 65 (Concise DCF for Node 101):
-1F22 66 (Concise DCF for Node 102):
-1F22 67 (Concise DCF for Node 103):
-1F22 68 (Concise DCF for Node 104):
-1F22 69 (Concise DCF for Node 105):
-1F22 6A (Concise DCF for Node 106):
-1F22 6B (Concise DCF for Node 107):
-1F22 6C (Concise DCF for Node 108):
-1F22 6D (Concise DCF for Node 109):
-1F22 6E (Concise DCF for Node 110):
-1F22 6F (Concise DCF for Node 111):
-1F22 70 (Concise DCF for Node 112):
-1F22 71 (Concise DCF for Node 113):
-1F22 72 (Concise DCF for Node 114):
-1F22 73 (Concise DCF for Node 115):
-1F22 74 (Concise DCF for Node 116):
-1F22 75 (Concise DCF for Node 117):
-1F22 76 (Concise DCF for Node 118):
-1F22 77 (Concise DCF for Node 119):
-1F22 78 (Concise DCF for Node 120):
-1F22 79 (Concise DCF for Node 121):
-1F22 7A (Concise DCF for Node 122):
-1F22 7B (Concise DCF for Node 123):
-1F22 7C (Concise DCF for Node 124):
-1F22 7D (Concise DCF for Node 125):
-1F22 7E (Concise DCF for Node 126):
-1F22 7F (Concise DCF for Node 127):
-2000 (Read Inputs): 0
-2240 (beremiz__IB0_1_64):
-2240 01 (24576_1): 0
-2240 02 (24578_1): 0
-2340 (beremiz__IW0_1_64):
-2340 01 (25601_2): 0
-2340 02 (25601_3): 0
-2440 (beremiz__ID0_1_64):
-2440 01 (25638_2): 0
-2440 02 (25638_3): 0
-2440 03 (25638_4): 0
-2440 04 (25638_1): 0
-4340 (beremiz__QW0_1_64):
-4340 01 (25617_1): 0
-
-********POINTERS*********
-{(4096, 0): '__ID0_1_4096_0',
- (8768, 1): '__IB0_1_64_24576_1',
- (8768, 2): '__IB0_1_64_24578_1',
- (9024, 1): '__IW0_1_64_25601_2',
- (9024, 2): '__IW0_1_64_25601_3',
- (9280, 1): '__ID0_1_64_25638_2',
- (9280, 2): '__ID0_1_64_25638_3',
- (9280, 3): '__ID0_1_64_25638_4',
- (9280, 4): '__ID0_1_64_25638_1',
- (17216, 1): '__QW0_1_64_25617_1'}
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/PythonEditor.py
--- a/plugins/python/PythonEditor.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,505 +0,0 @@
-import wx, wx.grid
-import wx.stc as stc
-import keyword
-
-from controls import EditorPanel
-
-if wx.Platform == '__WXMSW__':
- faces = { 'times': 'Times New Roman',
- 'mono' : 'Courier New',
- 'helv' : 'Arial',
- 'other': 'Comic Sans MS',
- 'size' : 10,
- 'size2': 8,
- }
-elif wx.Platform == '__WXMAC__':
- faces = { 'times': 'Times New Roman',
- 'mono' : 'Monaco',
- 'helv' : 'Arial',
- 'other': 'Comic Sans MS',
- 'size' : 12,
- 'size2': 10,
- }
-else:
- faces = { 'times': 'Times',
- 'mono' : 'Courier',
- 'helv' : 'Helvetica',
- 'other': 'new century schoolbook',
- 'size' : 12,
- 'size2': 10,
- }
-
-[ID_PYTHONEDITOR,
-] = [wx.NewId() for _init_ctrls in range(1)]
-
-def GetCursorPos(old, new):
- old_length = len(old)
- new_length = len(new)
- common_length = min(old_length, new_length)
- i = 0
- for i in xrange(common_length):
- if old[i] != new[i]:
- break
- if old_length < new_length:
- if common_length > 0 and old[i] != new[i]:
- return i + new_length - old_length
- else:
- return i + new_length - old_length + 1
- elif old_length > new_length or i < min(old_length, new_length) - 1:
- if common_length > 0 and old[i] != new[i]:
- return i
- else:
- return i + 1
- else:
- return None
-
-class PythonEditor(EditorPanel):
-
- fold_symbols = 3
-
- def _init_Editor(self, prnt):
- self.Editor = stc.StyledTextCtrl(id=ID_PYTHONEDITOR, parent=prnt,
- name="TextViewer", pos=wx.DefaultPosition,
- size=wx.DefaultSize, style=0)
-
- self.Editor.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
- self.Editor.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
-
- self.Editor.SetLexer(stc.STC_LEX_PYTHON)
- self.Editor.SetKeyWords(0, " ".join(keyword.kwlist))
-
- self.Editor.SetProperty("fold", "1")
- self.Editor.SetProperty("tab.timmy.whinge.level", "1")
- self.Editor.SetMargins(0,0)
-
- self.Editor.SetViewWhiteSpace(False)
-
- self.Editor.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
- self.Editor.SetEdgeColumn(78)
-
- # Set up the numbers in the margin for margin #1
- self.Editor.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
- # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
- self.Editor.SetMarginWidth(1, 40)
-
- # Setup a margin to hold fold markers
- self.Editor.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
- self.Editor.SetMarginMask(2, stc.STC_MASK_FOLDERS)
- self.Editor.SetMarginSensitive(2, True)
- self.Editor.SetMarginWidth(2, 12)
-
- if self.fold_symbols == 0:
- # Arrow pointing right for contracted folders, arrow pointing down for expanded
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_ARROWDOWN, "black", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_ARROW, "black", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "black", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "black", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
-
- elif self.fold_symbols == 1:
- # Plus for contracted folders, minus for expanded
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_MINUS, "white", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_PLUS, "white", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "white", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "white", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
-
- elif self.fold_symbols == 2:
- # Like a flattened tree control using circular headers and curved joins
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_CIRCLEMINUS, "white", "#404040")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_CIRCLEPLUS, "white", "#404040")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#404040")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNERCURVE, "white", "#404040")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_CIRCLEPLUSCONNECTED, "white", "#404040")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE, "white", "#404040")
-
- elif self.fold_symbols == 3:
- # Like a flattened tree control using square headers
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "#808080")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "#808080")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#808080")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "#808080")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "#808080")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
- self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "#808080")
-
-
- self.Editor.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
- self.Editor.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
- self.Editor.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
-
- # Global default style
- if wx.Platform == '__WXMSW__':
- self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier New')
- elif wx.Platform == '__WXMAC__':
- # TODO: if this looks fine on Linux too, remove the Mac-specific case
- # and use this whenever OS != MSW.
- self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Monaco')
- else:
- defsize = wx.SystemSettings.GetFont(wx.SYS_ANSI_FIXED_FONT).GetPointSize()
- self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier,size:%d'%defsize)
-
- # Clear styles and revert to default.
- self.Editor.StyleClearAll()
-
- # Following style specs only indicate differences from default.
- # The rest remains unchanged.
-
- # Line numbers in margin
- self.Editor.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2')
- # Highlighted brace
- self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00')
- # Unmatched brace
- self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000')
- # Indentation guide
- self.Editor.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD")
-
- # Python styles
- self.Editor.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000')
- # Comments
- self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, 'fore:#008000,back:#F0FFF0')
- self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0')
- # Numbers
- self.Editor.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080')
- # Strings and characters
- self.Editor.StyleSetSpec(wx.stc.STC_P_STRING, 'fore:#800080')
- self.Editor.StyleSetSpec(wx.stc.STC_P_CHARACTER, 'fore:#800080')
- # Keywords
- self.Editor.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold')
- # Triple quotes
- self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA')
- self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA')
- # Class names
- self.Editor.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold')
- # Function names
- self.Editor.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold')
- # Operators
- self.Editor.StyleSetSpec(wx.stc.STC_P_OPERATOR, 'fore:#800000,bold')
- # Identifiers. I leave this as not bold because everything seems
- # to be an identifier if it doesn't match the above criterae
- self.Editor.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, 'fore:#000000')
-
- # Caret color
- self.Editor.SetCaretForeground("BLUE")
- # Selection background
- self.Editor.SetSelBackground(1, '#66CCFF')
-
- self.Editor.SetSelBackground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT))
- self.Editor.SetSelForeground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT))
-
- # register some images for use in the AutoComplete box.
- #self.RegisterImage(1, images.getSmilesBitmap())
- self.Editor.RegisterImage(1,
- wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16)))
- self.Editor.RegisterImage(2,
- wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16)))
- self.Editor.RegisterImage(3,
- wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
-
- # Indentation and tab stuff
- self.Editor.SetIndent(4) # Proscribed indent size for wx
- self.Editor.SetIndentationGuides(True) # Show indent guides
- self.Editor.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
- self.Editor.SetTabIndents(True) # Tab key indents
- self.Editor.SetTabWidth(4) # Proscribed tab size for wx
- self.Editor.SetUseTabs(False) # Use spaces rather than tabs, or
- # TabTimmy will complain!
- # White space
- self.Editor.SetViewWhiteSpace(False) # Don't view white space
-
- # EOL: Since we are loading/saving ourselves, and the
- # strings will always have \n's in them, set the STC to
- # edit them that way.
- self.Editor.SetEOLMode(wx.stc.STC_EOL_LF)
- self.Editor.SetViewEOL(False)
-
- # No right-edge mode indicator
- self.Editor.SetEdgeMode(stc.STC_EDGE_NONE)
-
- self.Editor.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE)
-
- self.Editor.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_PYTHONEDITOR)
- self.Editor.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
- self.Editor.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_PYTHONEDITOR)
-
-
- def __init__(self, parent, controler, window):
- EditorPanel.__init__(self, parent, "", window, controler)
-
- self.DisableEvents = False
- self.CurrentAction = None
-
- img = wx.Bitmap(self.Controler.GetIconPath("Cfile.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
- self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
-
- def __del__(self):
- self.Controler.OnCloseEditor(self)
-
- def GetTitle(self):
- fullname = self.Controler.PlugFullName()
- if not self.Controler.PythonIsSaved():
- return "~%s~" % fullname
- return fullname
-
- def GetBufferState(self):
- return self.Controler.GetBufferState()
-
- def Undo(self):
- self.Controler.LoadPrevious()
- self.RefreshView()
-
- def Redo(self):
- self.Controler.LoadNext()
- self.RefreshView()
-
- def HasNoModel(self):
- return False
-
- def OnModification(self, event):
- if not self.DisableEvents:
- mod_type = event.GetModificationType()
- if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO):
- if mod_type&wx.stc.STC_MOD_BEFOREINSERT:
- if self.CurrentAction is None:
- self.StartBuffering()
- elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
- self.Controler.EndBuffering()
- self.StartBuffering()
- self.CurrentAction = ("Add", event.GetPosition())
- wx.CallAfter(self.RefreshModel)
- elif mod_type&wx.stc.STC_MOD_BEFOREDELETE:
- if self.CurrentAction == None:
- self.StartBuffering()
- elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
- self.Controler.EndBuffering()
- self.StartBuffering()
- self.CurrentAction = ("Delete", event.GetPosition())
- wx.CallAfter(self.RefreshModel)
- event.Skip()
-
- def OnDoDrop(self, event):
- self.ResetBuffer()
- wx.CallAfter(self.RefreshModel)
- event.Skip()
-
- # Buffer the last model state
- def RefreshBuffer(self):
- self.Controler.BufferPython()
- if self.ParentWindow is not None:
- self.ParentWindow.RefreshTitle()
- self.ParentWindow.RefreshFileMenu()
- self.ParentWindow.RefreshEditMenu()
- self.ParentWindow.RefreshPageTitles()
-
- def StartBuffering(self):
- self.Controler.StartBuffering()
- if self.ParentWindow is not None:
- self.ParentWindow.RefreshTitle()
- self.ParentWindow.RefreshFileMenu()
- self.ParentWindow.RefreshEditMenu()
- self.ParentWindow.RefreshPageTitles()
-
- def ResetBuffer(self):
- if self.CurrentAction != None:
- self.Controler.EndBuffering()
- self.CurrentAction = None
-
- def RefreshView(self):
- self.ResetBuffer()
- self.DisableEvents = True
- old_cursor_pos = self.Editor.GetCurrentPos()
- old_text = self.Editor.GetText()
- new_text = self.Controler.GetPythonCode()
- self.Editor.SetText(new_text)
- new_cursor_pos = GetCursorPos(old_text, new_text)
- if new_cursor_pos != None:
- self.Editor.GotoPos(new_cursor_pos)
- else:
- self.Editor.GotoPos(old_cursor_pos)
- self.Editor.ScrollToColumn(0)
- self.Editor.EmptyUndoBuffer()
- self.DisableEvents = False
-
- self.Editor.Colourise(0, -1)
-
- def RefreshModel(self):
- self.Controler.SetPythonCode(self.Editor.GetText())
-
- def OnKeyPressed(self, event):
- if self.Editor.CallTipActive():
- self.Editor.CallTipCancel()
- key = event.GetKeyCode()
-
- if key == 32 and event.ControlDown():
- pos = self.Editor.GetCurrentPos()
-
- # Tips
- if event.ShiftDown():
- pass
-## self.CallTipSetBackground("yellow")
-## self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n'
-## 'show some suff, maybe parameters..\n\n'
-## 'fubar(param1, param2)')
- # Code completion
- else:
- self.Editor.AutoCompSetIgnoreCase(False) # so this needs to match
-
- # Images are specified with a appended "?type"
- self.Editor.AutoCompShow(0, " ".join([word + "?1" for word in keyword.kwlist]))
- else:
- event.Skip()
-
- def OnKillFocus(self, event):
- self.Editor.AutoCompCancel()
- event.Skip()
-
- def OnUpdateUI(self, evt):
- # check for matching braces
- braceAtCaret = -1
- braceOpposite = -1
- charBefore = None
- caretPos = self.Editor.GetCurrentPos()
-
- if caretPos > 0:
- charBefore = self.Editor.GetCharAt(caretPos - 1)
- styleBefore = self.Editor.GetStyleAt(caretPos - 1)
-
- # check before
- if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
- braceAtCaret = caretPos - 1
-
- # check after
- if braceAtCaret < 0:
- charAfter = self.Editor.GetCharAt(caretPos)
- styleAfter = self.Editor.GetStyleAt(caretPos)
-
- if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
- braceAtCaret = caretPos
-
- if braceAtCaret >= 0:
- braceOpposite = self.Editor.BraceMatch(braceAtCaret)
-
- if braceAtCaret != -1 and braceOpposite == -1:
- self.Editor.BraceBadLight(braceAtCaret)
- else:
- self.Editor.BraceHighlight(braceAtCaret, braceOpposite)
- #pt = self.Editor.PointFromPosition(braceOpposite)
- #self.Editor.Refresh(True, wxRect(pt.x, pt.y, 5,5))
- #print pt
- #self.Editor.Refresh(False)
-
-
- def OnMarginClick(self, evt):
- # fold and unfold as needed
- if evt.GetMargin() == 2:
- if evt.GetShift() and evt.GetControl():
- self.FoldAll()
- else:
- lineClicked = self.Editor.LineFromPosition(evt.GetPosition())
-
- if self.Editor.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
- if evt.GetShift():
- self.Editor.SetFoldExpanded(lineClicked, True)
- self.Expand(lineClicked, True, True, 1)
- elif evt.GetControl():
- if self.Editor.GetFoldExpanded(lineClicked):
- self.Editor.SetFoldExpanded(lineClicked, False)
- self.Expand(lineClicked, False, True, 0)
- else:
- self.Editor.SetFoldExpanded(lineClicked, True)
- self.Expand(lineClicked, True, True, 100)
- else:
- self.Editor.ToggleFold(lineClicked)
-
-
- def FoldAll(self):
- lineCount = self.Editor.GetLineCount()
- expanding = True
-
- # find out if we are folding or unfolding
- for lineNum in range(lineCount):
- if self.Editor.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
- expanding = not self.Editor.GetFoldExpanded(lineNum)
- break
-
- lineNum = 0
-
- while lineNum < lineCount:
- level = self.Editor.GetFoldLevel(lineNum)
- if level & stc.STC_FOLDLEVELHEADERFLAG and \
- (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
-
- if expanding:
- self.Editor.SetFoldExpanded(lineNum, True)
- lineNum = self.Expand(lineNum, True)
- lineNum = lineNum - 1
- else:
- lastChild = self.Editor.GetLastChild(lineNum, -1)
- self.Editor.SetFoldExpanded(lineNum, False)
-
- if lastChild > lineNum:
- self.Editor.HideLines(lineNum+1, lastChild)
-
- lineNum = lineNum + 1
-
-
-
- def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
- lastChild = self.Editor.GetLastChild(line, level)
- line = line + 1
-
- while line <= lastChild:
- if force:
- if visLevels > 0:
- self.Editor.ShowLines(line, line)
- else:
- self.Editor.HideLines(line, line)
- else:
- if doExpand:
- self.Editor.ShowLines(line, line)
-
- if level == -1:
- level = self.Editor.GetFoldLevel(line)
-
- if level & stc.STC_FOLDLEVELHEADERFLAG:
- if force:
- if visLevels > 1:
- self.Editor.SetFoldExpanded(line, True)
- else:
- self.Editor.SetFoldExpanded(line, False)
-
- line = self.Expand(line, doExpand, force, visLevels-1)
-
- else:
- if doExpand and self.Editor.GetFoldExpanded(line):
- line = self.Expand(line, True, force, visLevels-1)
- else:
- line = self.Expand(line, False, force, visLevels-1)
- else:
- line = line + 1
-
- return line
-
- def Cut(self):
- self.ResetBuffer()
- self.DisableEvents = True
- self.Editor.CmdKeyExecute(wx.stc.STC_CMD_CUT)
- self.DisableEvents = False
- self.RefreshModel()
- self.RefreshBuffer()
-
- def Copy(self):
- self.Editor.CmdKeyExecute(wx.stc.STC_CMD_COPY)
-
- def Paste(self):
- self.ResetBuffer()
- self.DisableEvents = True
- self.Editor.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
- self.DisableEvents = False
- self.RefreshModel()
- self.RefreshBuffer()
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/README
--- a/plugins/python/README Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Asynchronous Python Interpreter
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/__init__.py
--- a/plugins/python/__init__.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-from python import *
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/__init__.py
--- a/plugins/python/modules/__init__.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-from os import listdir, path
-
-_base_path = path.split(__file__)[0]
-
-__all__ = [name for name in listdir(_base_path) if path.isdir(path.join(_base_path, name)) and name.upper() != "CVS" or name.endswith(".py") and not name.startswith("__")]
-
-helps = []
-for name in __all__:
- helpfilename = path.join(_base_path, name, "README")
- if path.isfile(helpfilename):
- helps.append(open(helpfilename).readline().strip())
- else:
- helps.append(name)
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/svgui/README
--- a/plugins/python/modules/svgui/README Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-SVGUI HMI
\ No newline at end of file
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/svgui/__init__.py
--- a/plugins/python/modules/svgui/__init__.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-from svgui import *
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/svgui/livesvg.js
--- a/plugins/python/modules/svgui/livesvg.js Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-// import Nevow.Athena
-// import Divmod.Base
-
-function updateAttr(id, param, value) {
- Nevow.Athena.Widget.fromAthenaID(1).callRemote('HMIexec', 'setattr', id, param, value);
-}
-
-var svguiWidgets = new Array();
-
-var currentObject = null;
-function setCurrentObject(obj) {
- currentObject = obj;
-}
-function isCurrentObject(obj) {
- return currentObject == obj;
-}
-
-function getSVGElementById(id) {
- return document.getElementById(id);
-}
-
-function blockSVGElementDrag(element) {
- element.addEventListener("draggesture", function(event){event.stopPropagation()}, true);
-}
-
-LiveSVGPage.LiveSVGWidget = Nevow.Athena.Widget.subclass('LiveSVGPage.LiveSVGWidget');
-LiveSVGPage.LiveSVGWidget.methods(
-
- function handleEvent(self, evt) {
- if (currentObject != null) {
- currentObject.handleEvent(evt);
- }
- },
-
- function receiveData(self, data){
- dataReceived = json_parse(data);
- gadget = svguiWidgets[dataReceived.id]
- if (gadget) {
- gadget.updateValues(json_parse(dataReceived.kwargs));
- }
- //console.log("OBJET : " + dataReceived.back_id + " STATE : " + newState);
- },
-
- function init(self, arg1){
- //console.log("Object received : " + arg1);
- for (ind in arg1) {
- gad = json_parse(arg1[ind]);
- args = json_parse(gad.kwargs);
- gadget = new svguilib[gad.__class__](self, gad.id, args);
- svguiWidgets[gadget.id]=gadget;
- //console.log('GADGET :' + gadget);
- }
- var elements = document.getElementsByTagName("svg");
- for (var i = 0; i < elements.length; i++) {
- elements[i].addEventListener("mouseup", self, false);
- }
- //console.log("SVGUIWIDGETS : " + svguiWidgets);
- }
-);
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/svgui/pous.xml
--- a/plugins/python/modules/svgui/pous.xml Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1428 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 'createSVGUIControl("textControl", back_id="'
-
-
-
-
-
-
- back_id
-
-
-
-
-
-
- '")'
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- BOOL#1
-
-
-
-
-
-
-
-
-
-
- ID
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ID
-
-
-
-
-
-
- set_text
-
-
-
-
-
-
- 'setAttr('
-
-
-
-
-
-
- ',"text","'
-
-
-
-
-
-
- '")'
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 'createSVGUIControl("button",back_id="'
-
-
-
-
-
-
- '",sele_id="'
-
-
-
-
-
-
- ',active=True)'
-
-
-
-
-
-
- BOOL#1
-
-
-
-
-
-
- back_id
-
-
-
-
-
-
- sele_id
-
-
-
-
-
-
- set_state
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ID
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- state_in
-
-
-
-
-
-
-
-
-
-
- state_out
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ID
-
-
-
-
-
-
- 'setAttr('
-
-
-
-
-
-
- ',"state",'
-
-
-
-
-
-
- ')'
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ID
-
-
-
-
-
-
- 'int(getAttr('
-
-
-
-
-
-
- ',"state",False))'
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- '",toggle='
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- toggle
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 'createSVGUIControl("button",back_id="'
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- '",sele_id="'
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ID
-
-
-
-
-
-
- '",toggle=True,active=False)'
-
-
-
-
-
-
- BOOL#1
-
-
-
-
-
-
- back_id
-
-
-
-
-
-
- sele_id
-
-
-
-
-
-
- 'setAttr('
-
-
-
-
-
-
- ',"state",'
-
-
-
-
-
-
- ')'
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ID
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- state_in
-
-
-
-
-
-
-
-
-
-
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/svgui/pyjs/__init__.py
--- a/plugins/python/modules/svgui/pyjs/__init__.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-from pyjs import *
-
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/svgui/pyjs/build.py
--- a/plugins/python/modules/svgui/pyjs/build.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,724 +0,0 @@
-#!/usr/bin/env python
-
-import sys
-import os
-import shutil
-from copy import copy
-from os.path import join, dirname, basename, abspath, split, isfile, isdir
-from optparse import OptionParser
-import pyjs
-from cStringIO import StringIO
-try:
- # Python 2.5 and above
- from hashlib import md5
-except:
- import md5
-import re
-
-usage = """
- usage: %prog [options]
-
-This is the command line builder for the pyjamas project, which can
-be used to build Ajax applications from Python.
-For more information, see the website at http://pyjs.org/
-"""
-
-# GWT1.2 Impl | GWT1.2 Output | Pyjamas 0.2 Platform | Pyjamas 0.2 Output
-# -------------+-----------------------+----------------------+----------------------
-# IE6 | ie6 | IE6 | ie6
-# Opera | opera | Opera | opera
-# Safari | safari | Safari | safari
-# -- | gecko1_8 | Mozilla | mozilla
-# -- | gecko | OldMoz | oldmoz
-# Standard | all | (default code) | all
-# Mozilla | gecko1_8, gecko | -- | --
-# Old | safari, gecko, opera | -- | --
-
-version = "%prog pyjamas version 2006-08-19"
-
-# these names in lowercase need match the strings
-# returned by "provider$user.agent" in order to be selected corretly
-app_platforms = ['IE6', 'Opera', 'OldMoz', 'Safari', 'Mozilla']
-
-# usually defaults to e.g. /usr/share/pyjamas
-_data_dir = os.path.join(pyjs.prefix, "share/pyjamas")
-
-
-# .cache.html files produces look like this
-CACHE_HTML_PAT=re.compile('^[a-z]*.[0-9a-f]{32}\.cache\.html$')
-
-# ok these are the three "default" library directories, containing
-# the builtins (str, List, Dict, ord, round, len, range etc.)
-# the main pyjamas libraries (pyjamas.ui, pyjamas.Window etc.)
-# and the contributed addons
-
-for p in ["library/builtins",
- "library",
- "addons"]:
- p = os.path.join(_data_dir, p)
- if os.path.isdir(p):
- pyjs.path.append(p)
-
-
-def read_boilerplate(data_dir, filename):
- return open(join(data_dir, "builder/boilerplate", filename)).read()
-
-def copy_boilerplate(data_dir, filename, output_dir):
- filename = join(data_dir, "builder/boilerplate", filename)
- shutil.copy(filename, output_dir)
-
-
-# taken and modified from python2.4
-def copytree_exists(src, dst, symlinks=False):
- if not os.path.exists(src):
- return
-
- names = os.listdir(src)
- try:
- os.mkdir(dst)
- except:
- pass
-
- errors = []
- for name in names:
- if name.startswith('CVS'):
- continue
- if name.startswith('.git'):
- continue
- if name.startswith('.svn'):
- continue
-
- srcname = os.path.join(src, name)
- dstname = os.path.join(dst, name)
- try:
- if symlinks and os.path.islink(srcname):
- linkto = os.readlink(srcname)
- os.symlink(linkto, dstname)
- elif isdir(srcname):
- copytree_exists(srcname, dstname, symlinks)
- else:
- shutil.copy2(srcname, dstname)
- except (IOError, os.error), why:
- errors.append((srcname, dstname, why))
- if errors:
- print errors
-
-def check_html_file(source_file, dest_path):
- """ Checks if a base HTML-file is available in the PyJamas
- output directory.
- If the HTML-file isn't available, it will be created.
-
- If a CSS-file with the same name is available
- in the output directory, a reference to this CSS-file
- is included.
-
- If no CSS-file is found, this function will look for a special
- CSS-file in the output directory, with the name
- "pyjamas_default.css", and if found it will be referenced
- in the generated HTML-file.
-
- [thank you to stef mientki for contributing this function]
- """
-
- base_html = """\
-
-
-
-
- %(css)s
- %(title)s
-
-
-
-
-
-"""
-
- filename = os.path.split ( source_file )[1]
- mod_name = os.path.splitext ( filename )[0]
- file_name = os.path.join ( dest_path, mod_name + '.html' )
-
- # if html file in output directory exists, leave it alone.
- if os.path.exists ( file_name ):
- return 0
-
- if os.path.exists (
- os.path.join ( dest_path, mod_name + '.css' ) ) :
- css = ""
- elif os.path.exists (
- os.path.join ( dest_path, 'pyjamas_default.css' ) ) :
- css = ""
-
- else:
- css = ''
-
- title = 'PyJamas Auto-Generated HTML file ' + mod_name
-
- base_html = base_html % {'modulename': mod_name, 'title': title, 'css': css}
-
- fh = open (file_name, 'w')
- fh.write (base_html)
- fh.close ()
-
- return 1
-
-
-def build(app_name, output, js_includes=(), debug=False, dynamic=0,
- data_dir=None, cache_buster=False, optimize=False):
-
- # make sure the output directory is always created in the current working
- # directory or at the place given if it is an absolute path.
- output = os.path.abspath(output)
- msg = "Building '%(app_name)s' to output directory '%(output)s'" % locals()
- if debug:
- msg += " with debugging statements"
- print msg
-
- # check the output directory
- if os.path.exists(output) and not os.path.isdir(output):
- print >>sys.stderr, "Output destination %s exists and is not a directory" % output
- return
- if not os.path.isdir(output):
- try:
- print "Creating output directory"
- os.mkdir(output)
- except StandardError, e:
- print >>sys.stderr, "Exception creating output directory %s: %s" % (output, e)
-
- ## public dir
- for p in pyjs.path:
- pub_dir = join(p, 'public')
- if isdir(pub_dir):
- print "Copying: public directory of library %r" % p
- copytree_exists(pub_dir, output)
-
- ## AppName.html - can be in current or public directory
- html_input_filename = app_name + ".html"
- html_output_filename = join(output, basename(html_input_filename))
- if os.path.isfile(html_input_filename):
- if not os.path.isfile(html_output_filename) or \
- os.path.getmtime(html_input_filename) > \
- os.path.getmtime(html_output_filename):
- try:
- shutil.copy(html_input_filename, html_output_filename)
- except:
- print >>sys.stderr, "Warning: Missing module HTML file %s" % html_input_filename
-
- print "Copying: %(html_input_filename)s" % locals()
-
- if check_html_file(html_input_filename, output):
- print >>sys.stderr, "Warning: Module HTML file %s has been auto-generated" % html_input_filename
-
- ## pygwt.js
-
- print "Copying: pygwt.js"
-
- pygwt_js_template = read_boilerplate(data_dir, "pygwt.js")
- pygwt_js_output = open(join(output, "pygwt.js"), "w")
-
- print >>pygwt_js_output, pygwt_js_template
-
- pygwt_js_output.close()
-
- ## Images
-
- print "Copying: Images and History"
- copy_boilerplate(data_dir, "corner_dialog_topleft_black.png", output)
- copy_boilerplate(data_dir, "corner_dialog_topright_black.png", output)
- copy_boilerplate(data_dir, "corner_dialog_bottomright_black.png", output)
- copy_boilerplate(data_dir, "corner_dialog_bottomleft_black.png", output)
- copy_boilerplate(data_dir, "corner_dialog_edge_black.png", output)
- copy_boilerplate(data_dir, "corner_dialog_topleft.png", output)
- copy_boilerplate(data_dir, "corner_dialog_topright.png", output)
- copy_boilerplate(data_dir, "corner_dialog_bottomright.png", output)
- copy_boilerplate(data_dir, "corner_dialog_bottomleft.png", output)
- copy_boilerplate(data_dir, "corner_dialog_edge.png", output)
- copy_boilerplate(data_dir, "tree_closed.gif", output)
- copy_boilerplate(data_dir, "tree_open.gif", output)
- copy_boilerplate(data_dir, "tree_white.gif", output)
- copy_boilerplate(data_dir, "history.html", output)
-
-
- ## all.cache.html
- app_files = generateAppFiles(data_dir, js_includes, app_name, debug,
- output, dynamic, cache_buster, optimize)
-
- ## AppName.nocache.html
-
- print "Creating: %(app_name)s.nocache.html" % locals()
-
- home_nocache_html_template = read_boilerplate(data_dir, "home.nocache.html")
- home_nocache_html_output = open(join(output, app_name + ".nocache.html"),
- "w")
-
- # the selector templ is added to the selectScript function
- select_tmpl = """O(["true","%s"],"%s");"""
- script_selectors = StringIO()
-
- for platform, file_prefix in app_files:
- print >> script_selectors, select_tmpl % (platform, file_prefix)
-
- print >>home_nocache_html_output, home_nocache_html_template % dict(
- app_name = app_name,
- script_selectors = script_selectors.getvalue(),
- )
-
- home_nocache_html_output.close()
-
- print "Done. You can run your app by opening '%(html_output_filename)s' in a browser" % locals()
-
-
-def generateAppFiles(data_dir, js_includes, app_name, debug, output, dynamic,
- cache_buster, optimize):
-
- all_cache_html_template = read_boilerplate(data_dir, "all.cache.html")
- mod_cache_html_template = read_boilerplate(data_dir, "mod.cache.html")
-
- # clean out the old ones first
- for name in os.listdir(output):
- if CACHE_HTML_PAT.match(name):
- p = join(output, name)
- print "Deleting existing app file %s" % p
- os.unlink(p)
-
- app_files = []
- tmpl = read_boilerplate(data_dir, "all.cache.html")
- parser = pyjs.PlatformParser("platform")
- app_headers = ''
- scripts = [''%script \
- for script in js_includes]
- app_body = '\n'.join(scripts)
-
- mod_code = {}
- mod_libs = {}
- modules = {}
- app_libs = {}
- early_app_libs = {}
- app_code = {}
- overrides = {}
- pover = {}
- app_modnames = {}
- mod_levels = {}
-
- # First, generate all the code.
- # Second, (dynamic only), post-analyse the places where modules
- # haven't changed
- # Third, write everything out.
-
- for platform in app_platforms:
-
- mod_code[platform] = {}
- mod_libs[platform] = {}
- modules[platform] = []
- pover[platform] = {}
- app_libs[platform] = ''
- early_app_libs[platform] = ''
- app_code[platform] = {}
- app_modnames[platform] = {}
-
- # Application.Platform.cache.html
-
- parser.setPlatform(platform)
- app_translator = pyjs.AppTranslator(
- parser=parser, dynamic=dynamic, optimize=optimize)
- early_app_libs[platform], appcode = \
- app_translator.translate(None, is_app=False,
- debug=debug,
- library_modules=['dynamicajax.js',
- '_pyjs.js', 'sys',
- 'pyjslib'])
- pover[platform].update(app_translator.overrides.items())
- for mname, name in app_translator.overrides.items():
- pd = overrides.setdefault(mname, {})
- pd[platform] = name
-
- print appcode
- #mod_code[platform][app_name] = appcode
-
- # platform.Module.cache.js
-
- modules_done = ['pyjslib', 'sys', '_pyjs.js']
- #modules_to_do = [app_name] + app_translator.library_modules
- modules_to_do = [app_name] + app_translator.library_modules
-
- dependencies = {}
-
- deps = map(pyjs.strip_py, modules_to_do)
- for d in deps:
- sublist = add_subdeps(dependencies, d)
- modules_to_do += sublist
- deps = uniquify(deps)
- #dependencies[app_name] = deps
-
- modules[platform] = modules_done + modules_to_do
-
- while modules_to_do:
-
- #print "modules to do", modules_to_do
-
- mn = modules_to_do.pop()
- mod_name = pyjs.strip_py(mn)
-
- if mod_name in modules_done:
- continue
-
- modules_done.append(mod_name)
-
- mod_cache_name = "%s.%s.cache.js" % (platform.lower(), mod_name)
-
- parser.setPlatform(platform)
- mod_translator = pyjs.AppTranslator(parser=parser, optimize=optimize)
- mod_libs[platform][mod_name], mod_code[platform][mod_name] = \
- mod_translator.translate(mod_name,
- is_app=False,
- debug=debug)
- pover[platform].update(mod_translator.overrides.items())
- for mname, name in mod_translator.overrides.items():
- pd = overrides.setdefault(mname, {})
- pd[platform] = name
-
- mods = mod_translator.library_modules
- modules_to_do += mods
- modules[platform] += mods
-
- deps = map(pyjs.strip_py, mods)
- sd = subdeps(mod_name)
- if len(sd) > 1:
- deps += sd[:-1]
- while mod_name in deps:
- deps.remove(mod_name)
-
- #print
- #print
- #print "modname preadd:", mod_name, deps
- #print
- #print
- for d in deps:
- sublist = add_subdeps(dependencies, d)
- modules_to_do += sublist
- modules_to_do += add_subdeps(dependencies, mod_name)
- #print "modname:", mod_name, deps
- deps = uniquify(deps)
- #print "modname:", mod_name, deps
- dependencies[mod_name] = deps
-
- # work out the dependency ordering of the modules
-
- mod_levels[platform] = make_deps(None, dependencies, modules_done)
-
- # now write everything out
-
- for platform in app_platforms:
-
- early_app_libs_ = early_app_libs[platform]
- app_libs_ = app_libs[platform]
- app_code_ = app_code[platform]
- #modules_ = filter_mods(app_name, modules[platform])
- mods = flattenlist(mod_levels[platform])
- mods.reverse()
- modules_ = filter_mods(None, mods)
-
- for mod_name in modules_:
-
- mod_code_ = mod_code[platform][mod_name]
-
- mod_name = pyjs.strip_py(mod_name)
-
- override_name = "%s.%s" % (platform.lower(), mod_name)
- if pover[platform].has_key(override_name):
- mod_cache_name = "%s.cache.js" % (override_name)
- else:
- mod_cache_name = "%s.cache.js" % (mod_name)
-
- print "Creating: " + mod_cache_name
-
- modlevels = make_deps(None, dependencies, dependencies[mod_name])
-
- modnames = []
-
- for md in modlevels:
- mnames = map(lambda x: "'%s'" % x, md)
- mnames = "new pyjslib.List([\n\t\t\t%s])" % ',\n\t\t\t'.join(mnames)
- modnames.append(mnames)
-
- modnames.reverse()
- modnames = "new pyjslib.List([\n\t\t%s\n\t])" % ',\n\t\t'.join(modnames)
-
- # convert the overrides
-
- overnames = map(lambda x: "'%s': '%s'" % x, pover[platform].items())
- overnames = "new pyjslib.Dict({\n\t\t%s\n\t})" % ',\n\t\t'.join(overnames)
-
- if dynamic:
- mod_cache_html_output = open(join(output, mod_cache_name), "w")
- else:
- mod_cache_html_output = StringIO()
-
- print >>mod_cache_html_output, mod_cache_html_template % dict(
- mod_name = mod_name,
- app_name = app_name,
- modnames = modnames,
- overrides = overnames,
- mod_libs = mod_libs[platform][mod_name],
- dynamic = dynamic,
- mod_code = mod_code_,
- )
-
- if dynamic:
- mod_cache_html_output.close()
- else:
- mod_cache_html_output.seek(0)
- app_libs_ += mod_cache_html_output.read()
-
- # write out the dependency ordering of the modules
-
- app_modnames = []
-
- for md in mod_levels[platform]:
- mnames = map(lambda x: "'%s'" % x, md)
- mnames = "new pyjslib.List([\n\t\t\t%s])" % ',\n\t\t\t'.join(mnames)
- app_modnames.append(mnames)
-
- app_modnames.reverse()
- app_modnames = "new pyjslib.List([\n\t\t%s\n\t])" % ',\n\t\t'.join(app_modnames)
-
- # convert the overrides
-
- overnames = map(lambda x: "'%s': '%s'" % x, pover[platform].items())
- overnames = "new pyjslib.Dict({\n\t\t%s\n\t})" % ',\n\t\t'.join(overnames)
-
- #print "platform names", platform, overnames
- #print pover
-
- # now write app.allcache including dependency-ordered list of
- # library modules
-
- file_contents = all_cache_html_template % dict(
- app_name = app_name,
- early_app_libs = early_app_libs_,
- app_libs = app_libs_,
- app_code = app_code_,
- app_body = app_body,
- overrides = overnames,
- platform = platform.lower(),
- dynamic = dynamic,
- app_modnames = app_modnames,
- app_headers = app_headers
- )
- if cache_buster:
- digest = md5.new(file_contents).hexdigest()
- file_name = "%s.%s.%s" % (platform.lower(), app_name, digest)
- else:
- file_name = "%s.%s" % (platform.lower(), app_name)
- file_name += ".cache.html"
- out_path = join(output, file_name)
- out_file = open(out_path, 'w')
- out_file.write(file_contents)
- out_file.close()
- app_files.append((platform.lower(), file_name))
- print "Created app file %s:%s: %s" % (
- app_name, platform, out_path)
-
- return app_files
-
-def flattenlist(ll):
- res = []
- for l in ll:
- res += l
- return res
-
-# creates sub-dependencies e.g. pyjamas.ui.Widget
-# creates pyjamas.ui.Widget, pyjamas.ui and pyjamas.
-def subdeps(m):
- d = []
- m = m.split(".")
- for i in range(0, len(m)):
- d.append('.'.join(m[:i+1]))
- return d
-
-import time
-
-def add_subdeps(deps, mod_name):
- sd = subdeps(mod_name)
- if len(sd) == 1:
- return []
- #print "subdeps", mod_name, sd
- #print "deps", deps
- res = []
- for i in range(0, len(sd)-1):
- parent = sd[i]
- child = sd[i+1]
- l = deps.get(child, [])
- l.append(parent)
- deps[child] = l
- if parent not in res:
- res.append(parent)
- #print deps
- return res
-
-# makes unique and preserves list order
-def uniquify(md):
- res = []
- for m in md:
- if m not in res:
- res.append(m)
- return res
-
-def filter_mods(app_name, md):
- while 'sys' in md:
- md.remove('sys')
- while 'pyjslib' in md:
- md.remove('pyjslib')
- while app_name in md:
- md.remove(app_name)
- md = filter(lambda x: not x.endswith('.js'), md)
- md = map(pyjs.strip_py, md)
-
- return uniquify(md)
-
-def filter_deps(app_name, deps):
-
- res = {}
- for (k, l) in deps.items():
- mods = filter_mods(k, l)
- while k in mods:
- mods.remove(k)
- res[k] = mods
- return res
-
-def has_nodeps(mod, deps):
- if not deps.has_key(mod) or not deps[mod]:
- return True
- return False
-
-def nodeps_list(mod_list, deps):
- res = []
- for mod in mod_list:
- if has_nodeps(mod, deps):
- res.append(mod)
- return res
-
-# this function takes a dictionary of dependent modules and
-# creates a list of lists. the first list will be modules
-# that have no dependencies; the second list will be those
-# modules that have the first list as dependencies; the
-# third will be those modules that have the first and second...
-# etc.
-
-
-def make_deps(app_name, deps, mod_list):
- print "Calculating Dependencies ..."
- mod_list = filter_mods(app_name, mod_list)
- deps = filter_deps(app_name, deps)
-
- if not mod_list:
- return []
-
- #print mod_list
- #print deps
-
- ordered_deps = []
- last_len = -1
- while deps:
- l_deps = len(deps)
- #print l_deps
- if l_deps==last_len:
- for m, dl in deps.items():
- for d in dl:
- if m in deps.get(d, []):
- raise Exception('Circular Imports found: \n%s %s -> %s %s'
- % (m, dl, d, deps[d]))
- #raise Exception('Could not calculate dependencies: \n%s' % deps)
- break
- last_len = l_deps
- #print "modlist", mod_list
- nodeps = nodeps_list(mod_list, deps)
- #print "nodeps", nodeps
- mod_list = filter(lambda x: x not in nodeps, mod_list)
- newdeps = {}
- for k in deps.keys():
- depslist = deps[k]
- depslist = filter(lambda x: x not in nodeps, depslist)
- if depslist:
- newdeps[k] = depslist
- #print "newdeps", newdeps
- deps = newdeps
- ordered_deps.append(nodeps)
- #time.sleep(0)
-
- if mod_list:
- ordered_deps.append(mod_list) # last dependencies - usually the app(s)
-
- ordered_deps.reverse()
-
- return ordered_deps
-
-def main():
- global app_platforms
-
- parser = OptionParser(usage = usage, version = version)
- parser.add_option("-o", "--output", dest="output",
- help="directory to which the webapp should be written")
- parser.add_option("-j", "--include-js", dest="js_includes", action="append",
- help="javascripts to load into the same frame as the rest of the script")
- parser.add_option("-I", "--library_dir", dest="library_dirs",
- action="append", help="additional paths appended to PYJSPATH")
- parser.add_option("-D", "--data_dir", dest="data_dir",
- help="path for data directory")
- parser.add_option("-m", "--dynamic-modules", action="store_true",
- dest="dynamic", default=False,
- help="Split output into separate dynamically-loaded modules (experimental)")
- parser.add_option("-P", "--platforms", dest="platforms",
- help="platforms to build for, comma-separated")
- parser.add_option("-d", "--debug", action="store_true", dest="debug")
- parser.add_option("-O", "--optimize", action="store_true",
- dest="optimize", default=False,
- help="Optimize generated code (removes all print statements)",
- )
- parser.add_option("-c", "--cache_buster", action="store_true",
- dest="cache_buster",
- help="Enable browser cache-busting (MD5 hash added to output filenames)")
-
- parser.set_defaults(output = "output", js_includes=[], library_dirs=[],
- platforms=(','.join(app_platforms)),
- data_dir=os.path.join(sys.prefix, "share/pyjamas"),
- dynamic=False,
- cache_buster=False,
- debug=False)
- (options, args) = parser.parse_args()
- if len(args) != 1:
- parser.error("incorrect number of arguments")
-
- data_dir = abspath(options.data_dir)
-
- app_path = args[0]
- if app_path.endswith('.py'):
- app_path = abspath(app_path)
- if not isfile(app_path):
- parser.error("Application file not found %r" % app_path)
- app_path, app_name = split(app_path)
- app_name = app_name[:-3]
- pyjs.path.append(app_path)
- elif os.path.sep in app_path:
- parser.error("Not a valid module declaration %r" % app_path)
- else:
- app_name = app_path
-
- for d in options.library_dirs:
- pyjs.path.append(abspath(d))
-
- if options.platforms:
- app_platforms = options.platforms.split(',')
-
- # this is mostly for getting boilerplate stuff
- data_dir = os.path.abspath(options.data_dir)
-
- build(app_name, options.output, options.js_includes,
- options.debug, options.dynamic and 1 or 0, data_dir,
- options.cache_buster, options.optimize)
-
-if __name__ == "__main__":
- main()
-
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/svgui/pyjs/jsonrpc/README.txt
--- a/plugins/python/modules/svgui/pyjs/jsonrpc/README.txt Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-These classes are intended for use server-side.
-
-e.g. in a django view.py :
-
- from pyjs.jsonrpc.django import JSONService, jsonremote
-
- jsonservice = JSONRPCService()
-
- @jsonremote(jsonservice)
- def test(request, echo_param):
- return "echoing the param back: %s" % echo_param
-
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/svgui/pyjs/jsonrpc/django/jsonrpc.py
--- a/plugins/python/modules/svgui/pyjs/jsonrpc/django/jsonrpc.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,226 +0,0 @@
-# jsonrpc.py
-# original code: http://trac.pyworks.org/pyjamas/wiki/DjangoWithPyJamas
-# also from: http://www.pimentech.fr/technologies/outils
-from django.utils import simplejson
-from django.http import HttpResponse
-import sys
-
-from pyjs.jsonrpc import JSONRPCServiceBase
-# JSONRPCService and jsonremote are used in combination to drastically
-# simplify the provision of JSONRPC services. use as follows:
-#
-# jsonservice = JSONRPCService()
-#
-# @jsonremote(jsonservice)
-# def test(request, echo_param):
-# return "echoing the param back: %s" % echo_param
-#
-# dump jsonservice into urlpatterns:
-# (r'^service1/$', 'djangoapp.views.jsonservice'),
-
-class JSONRPCService(JSONRPCServiceBase):
-
- def __call__(self, request, extra=None):
- return self.process(request.raw_post_data)
-
-def jsonremote(service):
- """Make JSONRPCService a decorator so that you can write :
-
- from jsonrpc import JSONRPCService
- chatservice = JSONRPCService()
-
- @jsonremote(chatservice)
- def login(request, user_name):
- (...)
- """
- def remotify(func):
- if isinstance(service, JSONRPCService):
- service.add_method(func.__name__, func)
- else:
- emsg = 'Service "%s" not found' % str(service.__name__)
- raise NotImplementedError, emsg
- return func
- return remotify
-
-
-# FormProcessor provides a mechanism for turning Django Forms into JSONRPC
-# Services. If you have an existing Django app which makes prevalent
-# use of Django Forms it will save you rewriting the app.
-# use as follows. in djangoapp/views.py :
-#
-# class SimpleForm(forms.Form):
-# testfield = forms.CharField(max_length=100)
-#
-# class SimpleForm2(forms.Form):
-# testfield = forms.CharField(max_length=20)
-#
-# processor = FormProcessor({'processsimpleform': SimpleForm,
-# 'processsimpleform2': SimpleForm2})
-#
-# this will result in a JSONRPC service being created with two
-# RPC functions. dump "processor" into urlpatterns to make it
-# part of the app:
-# (r'^formsservice/$', 'djangoapp.views.processor'),
-
-from django import forms
-
-def builderrors(form):
- d = {}
- for error in form.errors.keys():
- if error not in d:
- d[error] = []
- for errorval in form.errors[error]:
- d[error].append(unicode(errorval))
- return d
-
-
-# contains the list of arguments in each field
-field_names = {
- 'CharField': ['max_length', 'min_length'],
- 'IntegerField': ['max_value', 'min_value'],
- 'FloatField': ['max_value', 'min_value'],
- 'DecimalField': ['max_value', 'min_value', 'max_digits', 'decimal_places'],
- 'DateField': ['input_formats'],
- 'DateTimeField': ['input_formats'],
- 'TimeField': ['input_formats'],
- 'RegexField': ['max_length', 'min_length'], # sadly we can't get the expr
- 'EmailField': ['max_length', 'min_length'],
- 'URLField': ['max_length', 'min_length', 'verify_exists', 'user_agent'],
- 'ChoiceField': ['choices'],
- 'FilePathField': ['path', 'match', 'recursive', 'choices'],
- 'IPAddressField': ['max_length', 'min_length'],
- }
-
-def describe_field_errors(field):
- res = {}
- field_type = field.__class__.__name__
- msgs = {}
- for n, m in field.error_messages.items():
- msgs[n] = unicode(m)
- res['error_messages'] = msgs
- if field_type in ['ComboField', 'MultiValueField', 'SplitDateTimeField']:
- res['fields'] = map(describe_field, field.fields)
- return res
-
-def describe_fields_errors(fields, field_names):
- res = {}
- if not field_names:
- field_names = fields.keys()
- for name in field_names:
- field = fields[name]
- res[name] = describe_field_errors(field)
- return res
-
-def describe_field(field):
- res = {}
- field_type = field.__class__.__name__
- for fname in field_names.get(field_type, []) + \
- ['help_text', 'label', 'initial', 'required']:
- res[fname] = getattr(field, fname)
- if field_type in ['ComboField', 'MultiValueField', 'SplitDateTimeField']:
- res['fields'] = map(describe_field, field.fields)
- return res
-
-def describe_fields(fields, field_names):
- res = {}
- if not field_names:
- field_names = fields.keys()
- for name in field_names:
- field = fields[name]
- res[name] = describe_field(field)
- return res
-
-class FormProcessor(JSONRPCService):
- def __init__(self, forms, _formcls=None):
-
- if _formcls is None:
- JSONRPCService.__init__(self)
- for k in forms.keys():
- s = FormProcessor({}, forms[k])
- self.add_method(k, s.__process)
- else:
- JSONRPCService.__init__(self, forms)
- self.formcls = _formcls
-
- def __process(self, request, params, command=None):
-
- f = self.formcls(params)
-
- if command is None: # just validate
- if not f.is_valid():
- return {'success':False, 'errors': builderrors(f)}
- return {'success':True}
-
- elif command.has_key('describe_errors'):
- field_names = command['describe_errors']
- return describe_fields_errors(f.fields, field_names)
-
- elif command.has_key('describe'):
- field_names = command['describe']
- return describe_fields(f.fields, field_names)
-
- elif command.has_key('save'):
- if not f.is_valid():
- return {'success':False, 'errors': builderrors(f)}
- instance = f.save() # XXX: if you want more, over-ride save.
- return {'success': True, 'instance': json_convert(instance) }
-
- elif command.has_key('html'):
- return {'success': True, 'html': f.as_table()}
-
- return "unrecognised command"
-
-
-
-
-# The following is incredibly convenient for saving vast amounts of
-# coding, avoiding doing silly things like this:
-# jsonresult = {'field1': djangoobject.field1,
-# 'field2': djangoobject.date.strftime('%Y.%M'),
-# ..... }
-#
-# The date/time flatten function is there because JSONRPC doesn't
-# support date/time objects or formats, so conversion to a string
-# is the most logical choice. pyjamas, being python, can easily
-# be used to parse the string result at the other end.
-#
-# use as follows:
-#
-# jsonservice = JSONRPCService()
-#
-# @jsonremote(jsonservice)
-# def list_some_model(request, start=0, count=10):
-# l = SomeDjangoModelClass.objects.filter()
-# res = json_convert(l[start:end])
-#
-# @jsonremote(jsonservice)
-# def list_another_model(request, start=0, count=10):
-# l = AnotherDjangoModelClass.objects.filter()
-# res = json_convert(l[start:end])
-#
-# dump jsonservice into urlpatterns to make the two RPC functions,
-# list_some_model and list_another_model part of the django app:
-# (r'^service1/$', 'djangoapp.views.jsonservice'),
-
-from django.core.serializers import serialize
-import datetime
-from datetime import date
-
-def dict_datetimeflatten(item):
- d = {}
- for k, v in item.items():
- k = str(k)
- if isinstance(v, datetime.date):
- d[k] = str(v)
- elif isinstance(v, dict):
- d[k] = dict_datetimeflatten(v)
- else:
- d[k] = v
- return d
-
-def json_convert(l, fields=None):
- res = []
- for item in serialize('python', l, fields=fields):
- res.append(dict_datetimeflatten(item))
- return res
-
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/svgui/pyjs/jsonrpc/jsonrpc.py
--- a/plugins/python/modules/svgui/pyjs/jsonrpc/jsonrpc.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-import gluon.contrib.simplejson as simplejson
-import types
-import sys
-
-class JSONRPCServiceBase:
-
- def __init__(self):
- self.methods={}
-
- def response(self, id, result):
- return simplejson.dumps({'version': '1.1', 'id':id,
- 'result':result, 'error':None})
- def error(self, id, code, message):
- return simplejson.dumps({'id': id,
- 'version': '1.1',
- 'error': {'name': 'JSONRPCError',
- 'code': code,
- 'message': message
- }
- })
-
- def add_method(self, name, method):
- self.methods[name] = method
-
- def process(self, data):
- data = simplejson.loads(data)
- id, method, params = data["id"], data["method"], data["params"]
- if method in self.methods:
- try:
- result =self.methods[method](*params)
- return self.response(id, result)
- except BaseException:
- etype, eval, etb = sys.exc_info()
- return self.error(id, 100, '%s: %s' %(etype.__name__, eval))
- except:
- etype, eval, etb = sys.exc_info()
- return self.error(id, 100, 'Exception %s: %s' %(etype, eval))
- else:
- return self.error(id, 100, 'method "%s" does not exist' % method)
-
- def listmethods(self):
- return self.methods.keys()
-
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/svgui/pyjs/jsonrpc/web2py/jsonrpc.py
--- a/plugins/python/modules/svgui/pyjs/jsonrpc/web2py/jsonrpc.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-from pyjs.jsonrpc import JSONRPCServiceBase
-
-class JSONRPCService(JSONRPCServiceBase):
-
- def serve(self):
- return self.process(request.body.read())
-
- def __call__(self,func):
- self.methods[func.__name__]=func
- return func
-
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/svgui/pyjs/lib/_pyjs.js
--- a/plugins/python/modules/svgui/pyjs/lib/_pyjs.js Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-function pyjs_extend(klass, base) {
- function klass_object_inherit() {}
- klass_object_inherit.prototype = base.prototype;
- klass_object = new klass_object_inherit();
- for (var i in base.prototype.__class__) {
- v = base.prototype.__class__[i];
- if (typeof v == "function" && (v.class_method || v.static_method || v.unbound_method))
- {
- klass_object[i] = v;
- }
- }
-
- function klass_inherit() {}
- klass_inherit.prototype = klass_object;
- klass.prototype = new klass_inherit();
- klass_object.constructor = klass;
- klass.prototype.__class__ = klass_object;
-
- for (var i in base.prototype) {
- v = base.prototype[i];
- if (typeof v == "function" && v.instance_method)
- {
- klass.prototype[i] = v;
- }
- }
-}
-
-/* creates a class, derived from bases, with methods and variables */
-function pyjs_type(clsname, bases, methods)
-{
- var fn_cls = function() {};
- fn_cls.__name__ = clsname;
- var fn = function() {
- var instance = new fn_cls();
- if(instance.__init__) instance.__init__.apply(instance, arguments);
- return instance;
- }
- fn_cls.__initialize__ = function() {
- if (fn_cls.__was_initialized__) return;
- fn_cls.__was_initialized__ = true;
- fn_cls.__extend_baseclasses();
- fn_cls.prototype.__class__.__new__ = fn;
- fn_cls.prototype.__class__.__name__ = clsname;
- }
- fn_cls.__extend_baseclasses = function() {
- var bi;
- for (bi in fn_cls.__baseclasses)
- {
- var b = fn_cls.__baseclasses[bi];
- if (b.__was_initialized__)
- {
- continue;
- }
- b.__initialize__();
- }
- for (bi in fn_cls.__baseclasses)
- {
- var b = fn_cls.__baseclasses[bi];
- pyjs_extend(fn_cls, b);
- }
- }
- if (!bases) {
- bases = [pyjslib.__Object];
- }
- fn_cls.__baseclasses = bases;
-
- fn_cls.__initialize__();
-
- for (k in methods) {
- var mth = methods[k];
- var mtype = typeof mth;
- if (mtype == "function" ) {
- fn_cls.prototype[k] = mth;
- fn_cls.prototype.__class__[k] = function () {
- return fn_cls.prototype[k].call.apply(
- fn_cls.prototype[k], arguments);
- };
- fn_cls.prototype.__class__[k].unbound_method = true;
- fn_cls.prototype.instance_method = true;
- fn_cls.prototype.__class__[k].__name__ = k;
- fn_cls.prototype[k].__name__ = k;
- } else {
- fn_cls.prototype.__class__[k] = mth;
- }
- }
- return fn;
-}
-function pyjs_kwargs_call(obj, func, star_args, args)
-{
- var call_args;
-
- if (star_args)
- {
- if (!pyjslib.isIteratable(star_args))
- {
- throw (pyjslib.TypeError(func.__name__ + "() arguments after * must be a sequence" + pyjslib.repr(star_args)));
- }
- call_args = Array();
- var __i = star_args.__iter__();
- var i = 0;
- try {
- while (true) {
- call_args[i]=__i.next();
- i++;
- }
- } catch (e) {
- if (e != pyjslib.StopIteration) {
- throw e;
- }
- }
-
- if (args)
- {
- var n = star_args.length;
- for (var i=0; i < args.length; i++) {
- call_args[n+i]=args[i];
- }
- }
- }
- else
- {
- call_args = args;
- }
- return func.apply(obj, call_args);
-}
-
-function pyjs_kwargs_function_call(func, star_args, args)
-{
- return pyjs_kwargs_call(null, func, star_args, args);
-}
-
-function pyjs_kwargs_method_call(obj, method_name, star_args, args)
-{
- var method = obj[method_name];
- if (method.parse_kwargs)
- {
- args = method.parse_kwargs.apply(null, args);
- }
- return pyjs_kwargs_call(obj, method, star_args, args);
-}
-
-//String.prototype.__getitem__ = String.prototype.charAt;
-//String.prototype.upper = String.prototype.toUpperCase;
-//String.prototype.lower = String.prototype.toLowerCase;
-//String.prototype.find=pyjslib.String_find;
-//String.prototype.join=pyjslib.String_join;
-//String.prototype.isdigit=pyjslib.String_isdigit;
-//String.prototype.__iter__=pyjslib.String___iter__;
-//
-//String.prototype.__replace=String.prototype.replace;
-//String.prototype.replace=pyjslib.String_replace;
-//
-//String.prototype.split=pyjslib.String_split;
-//String.prototype.strip=pyjslib.String_strip;
-//String.prototype.lstrip=pyjslib.String_lstrip;
-//String.prototype.rstrip=pyjslib.String_rstrip;
-//String.prototype.startswith=pyjslib.String_startswith;
-
-var str = String;
-
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/svgui/pyjs/lib/json.js
--- a/plugins/python/modules/svgui/pyjs/lib/json.js Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,293 +0,0 @@
-json_parse = (function () {
-
-// This is a function that can parse a JSON text, producing a JavaScript
-// data structure. It is a simple, recursive descent parser. It does not use
-// eval or regular expressions, so it can be used as a model for implementing
-// a JSON parser in other languages.
-
-// We are defining the function inside of another function to avoid creating
-// global variables.
-
- var at, // The index of the current character
- ch, // The current character
- escapee = {
- '"': '"',
- '\\': '\\',
- '/': '/',
- b: '\b',
- f: '\f',
- n: '\n',
- r: '\r',
- t: '\t'
- },
- text,
-
- error = function (m) {
-
-// Call error when something is wrong.
-
- throw {
- name: 'SyntaxError',
- message: m,
- at: at,
- text: text
- };
- },
-
- next = function (c) {
-
-// If a c parameter is provided, verify that it matches the current character.
-
- if (c && c !== ch) {
- error("Expected '" + c + "' instead of '" + ch + "'");
- }
-
-// Get the next character. When there are no more characters,
-// return the empty string.
-
- ch = text.charAt(at);
- at += 1;
- return ch;
- },
-
- number = function () {
-
-// Parse a number value.
-
- var number,
- string = '';
-
- if (ch === '-') {
- string = '-';
- next('-');
- }
- while (ch >= '0' && ch <= '9') {
- string += ch;
- next();
- }
- if (ch === '.') {
- string += '.';
- while (next() && ch >= '0' && ch <= '9') {
- string += ch;
- }
- }
- if (ch === 'e' || ch === 'E') {
- string += ch;
- next();
- if (ch === '-' || ch === '+') {
- string += ch;
- next();
- }
- while (ch >= '0' && ch <= '9') {
- string += ch;
- next();
- }
- }
- number = +string;
- if (isNaN(number)) {
- error("Bad number");
- } else {
- return number;
- }
- },
-
- string = function () {
-
-// Parse a string value.
-
- var hex,
- i,
- string = '',
- uffff;
-
-// When parsing for string values, we must look for " and \ characters.
-
- if (ch === '"') {
- while (next()) {
- if (ch === '"') {
- next();
- return string;
- } else if (ch === '\\') {
- next();
- if (ch === 'u') {
- uffff = 0;
- for (i = 0; i < 4; i += 1) {
- hex = parseInt(next(), 16);
- if (!isFinite(hex)) {
- break;
- }
- uffff = uffff * 16 + hex;
- }
- string += String.fromCharCode(uffff);
- } else if (typeof escapee[ch] === 'string') {
- string += escapee[ch];
- } else {
- break;
- }
- } else {
- string += ch;
- }
- }
- }
- error("Bad string");
- },
-
- white = function () {
-
-// Skip whitespace.
-
- while (ch && ch <= ' ') {
- next();
- }
- },
-
- word = function () {
-
-// true, false, or null.
-
- switch (ch) {
- case 't':
- next('t');
- next('r');
- next('u');
- next('e');
- return true;
- case 'f':
- next('f');
- next('a');
- next('l');
- next('s');
- next('e');
- return false;
- case 'n':
- next('n');
- next('u');
- next('l');
- next('l');
- return null;
- }
- error("Unexpected '" + ch + "'");
- },
-
- value, // Place holder for the value function.
-
- array = function () {
-
-// Parse an array value.
-
- var array = [];
-
- if (ch === '[') {
- next('[');
- white();
- if (ch === ']') {
- next(']');
- return array; // empty array
- }
- while (ch) {
- array.push(value());
- white();
- if (ch === ']') {
- next(']');
- return array;
- }
- next(',');
- white();
- }
- }
- error("Bad array");
- },
-
- object = function () {
-
-// Parse an object value.
-
- var key,
- object = {};
-
- if (ch === '{') {
- next('{');
- white();
- if (ch === '}') {
- next('}');
- return object; // empty object
- }
- while (ch) {
- key = string();
- white();
- next(':');
- if (Object.hasOwnProperty.call(object, key)) {
- error('Duplicate key "' + key + '"');
- }
- object[key] = value();
- white();
- if (ch === '}') {
- next('}');
- return object;
- }
- next(',');
- white();
- }
- }
- error("Bad object");
- };
-
- value = function () {
-
-// Parse a JSON value. It could be an object, an array, a string, a number,
-// or a word.
-
- white();
- switch (ch) {
- case '{':
- return object();
- case '[':
- return array();
- case '"':
- return string();
- case '-':
- return number();
- default:
- return ch >= '0' && ch <= '9' ? number() : word();
- }
- };
-
-// Return the json_parse function. It will have access to all of the above
-// functions and variables.
-
- return function (source, reviver) {
- var result;
-
- text = source;
- at = 0;
- ch = ' ';
- result = value();
- white();
- if (ch) {
- error("Syntax error");
- }
-
-// If there is a reviver function, we recursively walk the new structure,
-// passing each name/value pair to the reviver function for possible
-// transformation, starting with a temporary root object that holds the result
-// in an empty key. If there is not a reviver function, we simply return the
-// result.
-
- return typeof reviver === 'function' ? (function walk(holder, key) {
- var k, v, value = holder[key];
- if (value && typeof value === 'object') {
- for (k in value) {
- if (Object.hasOwnProperty.call(value, k)) {
- v = walk(value, k);
- if (v !== undefined) {
- value[k] = v;
- } else {
- delete value[k];
- }
- }
- }
- }
- return reviver.call(holder, key, value);
- }({'': result}, '')) : result;
- };
-}());
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/svgui/pyjs/lib/pyjslib.py
--- a/plugins/python/modules/svgui/pyjs/lib/pyjslib.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1365 +0,0 @@
-# Copyright 2006 James Tauber and contributors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-# iteration from Bob Ippolito's Iteration in JavaScript
-
-from __pyjamas__ import JS
-
-# must declare import _before_ importing sys
-
-def import_module(path, parent_module, module_name, dynamic=1, async=False):
- """
- """
-
- JS("""
- var cache_file;
-
- if (module_name == "sys" || module_name == 'pyjslib')
- {
- /*module_load_request[module_name] = 1;*/
- return;
- }
-
- if (path == null)
- {
- path = './';
- }
-
- var override_name = sys.platform + "." + module_name;
- if (((sys.overrides != null) &&
- (sys.overrides.has_key(override_name))))
- {
- cache_file = sys.overrides.__getitem__(override_name) ;
- }
- else
- {
- cache_file = module_name ;
- }
-
- cache_file = (path + cache_file + '.cache.js' ) ;
-
- //alert("cache " + cache_file + " " + module_name + " " + parent_module);
-
- /* already loaded? */
- if (module_load_request[module_name])
- {
- if (module_load_request[module_name] >= 3 && parent_module != null)
- {
- //onload_fn = parent_module + '.' + module_name + ' = ' + module_name + ';';
- //pyjs_eval(onload_fn); /* set up the parent-module namespace */
- }
- return;
- }
- if (typeof (module_load_request[module_name]) == 'undefined')
- {
- module_load_request[module_name] = 1;
- }
-
- /* following a load, this first executes the script
- * "preparation" function MODULENAME_loaded_fn()
- * and then sets up the loaded module in the namespace
- * of the parent.
- */
-
- onload_fn = ''; // module_name + "_loaded_fn();"
-
- if (parent_module != null)
- {
- //onload_fn += parent_module + '.' + module_name + ' = ' + module_name + ';';
- /*pmod = parent_module + '.' + module_name;
- onload_fn += 'alert("' + pmod + '"+' + pmod+');';*/
- }
-
-
- if (dynamic)
- {
- /* this one tacks the script onto the end of the DOM
- */
-
- pyjs_load_script(cache_file, onload_fn, async);
-
- /* this one actually RUNS the script (eval) into the page.
- my feeling is that this would be better for non-async
- but i can't get it to work entirely yet.
- */
- /*pyjs_ajax_eval(cache_file, onload_fn, async);*/
- }
- else
- {
- if (module_name != "pyjslib" &&
- module_name != "sys")
- pyjs_eval(onload_fn);
- }
-
- """)
-
-JS("""
-function import_wait(proceed_fn, parent_mod, dynamic) {
-
- var data = '';
- var element = $doc.createElement("div");
- $doc.body.appendChild(element);
- function write_dom(txt) {
- element.innerHTML = txt + '
';
- }
-
- var timeoutperiod = 1;
- if (dynamic)
- var timeoutperiod = 1;
-
- var wait = function() {
-
- var status = '';
- for (l in module_load_request)
- {
- var m = module_load_request[l];
- if (l == "sys" || l == 'pyjslib')
- continue;
- status += l + m + " ";
- }
-
- //write_dom( " import wait " + wait_count + " " + status + " parent_mod " + parent_mod);
- wait_count += 1;
-
- if (status == '')
- {
- setTimeout(wait, timeoutperiod);
- return;
- }
-
- for (l in module_load_request)
- {
- var m = module_load_request[l];
- if (l == "sys" || l == 'pyjslib')
- {
- module_load_request[l] = 4;
- continue;
- }
- if ((parent_mod != null) && (l == parent_mod))
- {
- if (m == 1)
- {
- setTimeout(wait, timeoutperiod);
- return;
- }
- if (m == 2)
- {
- /* cheat and move app on to next stage */
- module_load_request[l] = 3;
- }
- }
- if (m == 1 || m == 2)
- {
- setTimeout(wait, timeoutperiod);
- return;
- }
- if (m == 3)
- {
- //alert("waited for module " + l + ": loaded");
- module_load_request[l] = 4;
- mod_fn = modules[l];
- }
- }
- //alert("module wait done");
-
- if (proceed_fn.importDone)
- proceed_fn.importDone(proceed_fn);
- else
- proceed_fn();
- }
-
- wait();
-}
-""")
-
-class Object:
- pass
-
-object = Object
-
-class Modload:
-
- def __init__(self, path, app_modlist, app_imported_fn, dynamic,
- parent_mod):
- self.app_modlist = app_modlist
- self.app_imported_fn = app_imported_fn
- self.path = path
- self.idx = 0;
- self.dynamic = dynamic
- self.parent_mod = parent_mod
-
- def next(self):
-
- for i in range(len(self.app_modlist[self.idx])):
- app = self.app_modlist[self.idx][i]
- import_module(self.path, self.parent_mod, app, self.dynamic, True);
- self.idx += 1
-
- if self.idx >= len(self.app_modlist):
- import_wait(self.app_imported_fn, self.parent_mod, self.dynamic)
- else:
- import_wait(getattr(self, "next"), self.parent_mod, self.dynamic)
-
-def get_module(module_name):
- ev = "__mod = %s;" % module_name
- JS("pyjs_eval(ev);")
- return __mod
-
-def preload_app_modules(path, app_modnames, app_imported_fn, dynamic,
- parent_mod=None):
-
- loader = Modload(path, app_modnames, app_imported_fn, dynamic, parent_mod)
- loader.next()
-
-import sys
-
-class BaseException:
-
- name = "BaseException"
-
- def __init__(self, *args):
- self.args = args
-
- def __str__(self):
- if len(self.args) is 0:
- return ''
- elif len(self.args) is 1:
- return repr(self.args[0])
- return repr(self.args)
-
- def toString(self):
- return str(self)
-
-class Exception(BaseException):
-
- name = "Exception"
-
-class TypeError(BaseException):
- name = "TypeError"
-
-class StandardError(Exception):
- name = "StandardError"
-
-class LookupError(StandardError):
- name = "LookupError"
-
- def toString(self):
- return self.name + ": " + self.args[0]
-
-class KeyError(LookupError):
- name = "KeyError"
-
-class AttributeError(StandardError):
-
- name = "AttributeError"
-
- def toString(self):
- return "AttributeError: %s of %s" % (self.args[1], self.args[0])
-
-JS("""
-pyjslib.StopIteration = function () { };
-pyjslib.StopIteration.prototype = new Error();
-pyjslib.StopIteration.name = 'StopIteration';
-pyjslib.StopIteration.message = 'StopIteration';
-
-pyjslib.String_find = function(sub, start, end) {
- var pos=this.indexOf(sub, start);
- if (pyjslib.isUndefined(end)) return pos;
-
- if (pos + sub.length>end) return -1;
- return pos;
-}
-
-pyjslib.String_join = function(data) {
- var text="";
-
- if (pyjslib.isArray(data)) {
- return data.join(this);
- }
- else if (pyjslib.isIteratable(data)) {
- var iter=data.__iter__();
- try {
- text+=iter.next();
- while (true) {
- var item=iter.next();
- text+=this + item;
- }
- }
- catch (e) {
- if (e != pyjslib.StopIteration) throw e;
- }
- }
-
- return text;
-}
-
-pyjslib.String_isdigit = function() {
- return (this.match(/^\d+$/g) != null);
-}
-
-pyjslib.String_replace = function(old, replace, count) {
- var do_max=false;
- var start=0;
- var new_str="";
- var pos=0;
-
- if (!pyjslib.isString(old)) return this.__replace(old, replace);
- if (!pyjslib.isUndefined(count)) do_max=true;
-
- while (start= s.length) {
- throw pyjslib.StopIteration;
- }
- return s.substring(i++, i, 1);
- },
- '__iter__': function() {
- return this;
- }
- };
-}
-
-pyjslib.String_strip = function(chars) {
- return this.lstrip(chars).rstrip(chars);
-}
-
-pyjslib.String_lstrip = function(chars) {
- if (pyjslib.isUndefined(chars)) return this.replace(/^\s+/, "");
-
- return this.replace(new RegExp("^[" + chars + "]+"), "");
-}
-
-pyjslib.String_rstrip = function(chars) {
- if (pyjslib.isUndefined(chars)) return this.replace(/\s+$/, "");
-
- return this.replace(new RegExp("[" + chars + "]+$"), "");
-}
-
-pyjslib.String_startswith = function(prefix, start) {
- if (pyjslib.isUndefined(start)) start = 0;
-
- if (this.substring(start, prefix.length) == prefix) return true;
- return false;
-}
-
-pyjslib.abs = Math.abs;
-
-""")
-
-class Class:
- def __init__(self, name):
- self.name = name
-
- def __str___(self):
- return self.name
-
-def eq(a,b):
- JS("""
- if (pyjslib.hasattr(a, "__cmp__")) {
- return a.__cmp__(b) == 0;
- } else if (pyjslib.hasattr(b, "__cmp__")) {
- return b.__cmp__(a) == 0;
- }
- return a == b;
- """)
-
-def cmp(a,b):
- if hasattr(a, "__cmp__"):
- return a.__cmp__(b)
- elif hasattr(b, "__cmp__"):
- return -b.__cmp__(a)
- if a > b:
- return 1
- elif b > a:
- return -1
- else:
- return 0
-
-def bool(v):
- # this needs to stay in native code without any dependencies here,
- # because this is used by if and while, we need to prevent
- # recursion
- JS("""
- if (!v) return false;
- switch(typeof v){
- case 'boolean':
- return v;
- case 'object':
- if (v.__nonzero__){
- return v.__nonzero__();
- }else if (v.__len__){
- return v.__len__()>0;
- }
- return true;
- }
- return Boolean(v);
- """)
-
-class List:
- def __init__(self, data=None):
- JS("""
- this.l = [];
- this.extend(data);
- """)
-
- def append(self, item):
- JS(""" this.l[this.l.length] = item;""")
-
- def extend(self, data):
- JS("""
- if (pyjslib.isArray(data)) {
- n = this.l.length;
- for (var i=0; i < data.length; i++) {
- this.l[n+i]=data[i];
- }
- }
- else if (pyjslib.isIteratable(data)) {
- var iter=data.__iter__();
- var i=this.l.length;
- try {
- while (true) {
- var item=iter.next();
- this.l[i++]=item;
- }
- }
- catch (e) {
- if (e != pyjslib.StopIteration) throw e;
- }
- }
- """)
-
- def remove(self, value):
- JS("""
- var index=this.index(value);
- if (index<0) return false;
- this.l.splice(index, 1);
- return true;
- """)
-
- def index(self, value, start=0):
- JS("""
- var length=this.l.length;
- for (var i=start; i= 0
-
- def __iter__(self):
- JS("""
- var i = 0;
- var l = this.l;
- return {
- 'next': function() {
- if (i >= l.length) {
- throw pyjslib.StopIteration;
- }
- return l[i++];
- },
- '__iter__': function() {
- return this;
- }
- };
- """)
-
- def reverse(self):
- JS(""" this.l.reverse();""")
-
- def sort(self, compareFunc=None, keyFunc=None, reverse=False):
- if not compareFunc:
- global cmp
- compareFunc = cmp
- if keyFunc and reverse:
- def thisSort1(a,b):
- return -compareFunc(keyFunc(a), keyFunc(b))
- self.l.sort(thisSort1)
- elif keyFunc:
- def thisSort2(a,b):
- return compareFunc(keyFunc(a), keyFunc(b))
- self.l.sort(thisSort2)
- elif reverse:
- def thisSort3(a,b):
- return -compareFunc(a, b)
- self.l.sort(thisSort3)
- else:
- self.l.sort(compareFunc)
-
- def getArray(self):
- """
- Access the javascript Array that is used internally by this list
- """
- return self.l
-
- def __str__(self):
- return repr(self)
-
-list = List
-
-class Tuple:
- def __init__(self, data=None):
- JS("""
- this.l = [];
- this.extend(data);
- """)
-
- def append(self, item):
- JS(""" this.l[this.l.length] = item;""")
-
- def extend(self, data):
- JS("""
- if (pyjslib.isArray(data)) {
- n = this.l.length;
- for (var i=0; i < data.length; i++) {
- this.l[n+i]=data[i];
- }
- }
- else if (pyjslib.isIteratable(data)) {
- var iter=data.__iter__();
- var i=this.l.length;
- try {
- while (true) {
- var item=iter.next();
- this.l[i++]=item;
- }
- }
- catch (e) {
- if (e != pyjslib.StopIteration) throw e;
- }
- }
- """)
-
- def remove(self, value):
- JS("""
- var index=this.index(value);
- if (index<0) return false;
- this.l.splice(index, 1);
- return true;
- """)
-
- def index(self, value, start=0):
- JS("""
- var length=this.l.length;
- for (var i=start; i= 0
-
- def __iter__(self):
- JS("""
- var i = 0;
- var l = this.l;
- return {
- 'next': function() {
- if (i >= l.length) {
- throw pyjslib.StopIteration;
- }
- return l[i++];
- },
- '__iter__': function() {
- return this;
- }
- };
- """)
-
- def reverse(self):
- JS(""" this.l.reverse();""")
-
- def sort(self, compareFunc=None, keyFunc=None, reverse=False):
- if not compareFunc:
- global cmp
- compareFunc = cmp
- if keyFunc and reverse:
- def thisSort1(a,b):
- return -compareFunc(keyFunc(a), keyFunc(b))
- self.l.sort(thisSort1)
- elif keyFunc:
- def thisSort2(a,b):
- return compareFunc(keyFunc(a), keyFunc(b))
- self.l.sort(thisSort2)
- elif reverse:
- def thisSort3(a,b):
- return -compareFunc(a, b)
- self.l.sort(thisSort3)
- else:
- self.l.sort(compareFunc)
-
- def getArray(self):
- """
- Access the javascript Array that is used internally by this list
- """
- return self.l
-
- def __str__(self):
- return repr(self)
-
-tuple = Tuple
-
-
-class Dict:
- def __init__(self, data=None):
- JS("""
- this.d = {};
-
- if (pyjslib.isArray(data)) {
- for (var i in data) {
- var item=data[i];
- this.__setitem__(item[0], item[1]);
- //var sKey=pyjslib.hash(item[0]);
- //this.d[sKey]=item[1];
- }
- }
- else if (pyjslib.isIteratable(data)) {
- var iter=data.__iter__();
- try {
- while (true) {
- var item=iter.next();
- this.__setitem__(item.__getitem__(0), item.__getitem__(1));
- }
- }
- catch (e) {
- if (e != pyjslib.StopIteration) throw e;
- }
- }
- else if (pyjslib.isObject(data)) {
- for (var key in data) {
- this.__setitem__(key, data[key]);
- }
- }
- """)
-
- def __setitem__(self, key, value):
- JS("""
- var sKey = pyjslib.hash(key);
- this.d[sKey]=[key, value];
- """)
-
- def __getitem__(self, key):
- JS("""
- var sKey = pyjslib.hash(key);
- var value=this.d[sKey];
- if (pyjslib.isUndefined(value)){
- throw pyjslib.KeyError(key);
- }
- return value[1];
- """)
-
- def __nonzero__(self):
- JS("""
- for (var i in this.d){
- return true;
- }
- return false;
- """)
-
- def __len__(self):
- JS("""
- var size=0;
- for (var i in this.d) size++;
- return size;
- """)
-
- def has_key(self, key):
- return self.__contains__(key)
-
- def __delitem__(self, key):
- JS("""
- var sKey = pyjslib.hash(key);
- delete this.d[sKey];
- """)
-
- def __contains__(self, key):
- JS("""
- var sKey = pyjslib.hash(key);
- return (pyjslib.isUndefined(this.d[sKey])) ? false : true;
- """)
-
- def keys(self):
- JS("""
- var keys=new pyjslib.List();
- for (var key in this.d) {
- keys.append(this.d[key][0]);
- }
- return keys;
- """)
-
- def values(self):
- JS("""
- var values=new pyjslib.List();
- for (var key in this.d) values.append(this.d[key][1]);
- return values;
- """)
-
- def items(self):
- JS("""
- var items = new pyjslib.List();
- for (var key in this.d) {
- var kv = this.d[key];
- items.append(new pyjslib.List(kv))
- }
- return items;
- """)
-
- def __iter__(self):
- return self.keys().__iter__()
-
- def iterkeys(self):
- return self.__iter__()
-
- def itervalues(self):
- return self.values().__iter__();
-
- def iteritems(self):
- return self.items().__iter__();
-
- def setdefault(self, key, default_value):
- if not self.has_key(key):
- self[key] = default_value
-
- def get(self, key, default_=None):
- if not self.has_key(key):
- return default_
- return self[key]
-
- def update(self, d):
- for k,v in d.iteritems():
- self[k] = v
-
- def getObject(self):
- """
- Return the javascript Object which this class uses to store
- dictionary keys and values
- """
- return self.d
-
- def copy(self):
- return Dict(self.items())
-
- def __str__(self):
- return repr(self)
-
-dict = Dict
-
-# taken from mochikit: range( [start,] stop[, step] )
-def range():
- JS("""
- var start = 0;
- var stop = 0;
- var step = 1;
-
- if (arguments.length == 2) {
- start = arguments[0];
- stop = arguments[1];
- }
- else if (arguments.length == 3) {
- start = arguments[0];
- stop = arguments[1];
- step = arguments[2];
- }
- else if (arguments.length>0) stop = arguments[0];
-
- return {
- 'next': function() {
- if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) throw pyjslib.StopIteration;
- var rval = start;
- start += step;
- return rval;
- },
- '__iter__': function() {
- return this;
- }
- }
- """)
-
-def slice(object, lower, upper):
- JS("""
- if (pyjslib.isString(object)) {
- if (lower < 0) {
- lower = object.length + lower;
- }
- if (upper < 0) {
- upper = object.length + upper;
- }
- if (pyjslib.isNull(upper)) upper=object.length;
- return object.substring(lower, upper);
- }
- if (pyjslib.isObject(object) && object.slice)
- return object.slice(lower, upper);
-
- return null;
- """)
-
-def str(text):
- JS("""
- if (pyjslib.hasattr(text,"__str__")) {
- return text.__str__();
- }
- return String(text);
- """)
-
-def ord(x):
- if(isString(x) and len(x) is 1):
- JS("""
- return x.charCodeAt(0);
- """)
- else:
- JS("""
- throw pyjslib.TypeError();
- """)
- return None
-
-def chr(x):
- JS("""
- return String.fromCharCode(x)
- """)
-
-def is_basetype(x):
- JS("""
- var t = typeof(x);
- return t == 'boolean' ||
- t == 'function' ||
- t == 'number' ||
- t == 'string' ||
- t == 'undefined'
- ;
- """)
-
-def get_pyjs_classtype(x):
- JS("""
- if (pyjslib.hasattr(x, "__class__"))
- if (pyjslib.hasattr(x.__class__, "__new__"))
- var src = x.__class__.__name__;
- return src;
- return null;
- """)
-
-def repr(x):
- """ Return the string representation of 'x'.
- """
- JS("""
- if (x === null)
- return "null";
-
- if (x === undefined)
- return "undefined";
-
- var t = typeof(x);
-
- //alert("repr typeof " + t + " : " + x);
-
- if (t == "boolean")
- return x.toString();
-
- if (t == "function")
- return "";
-
- if (t == "number")
- return x.toString();
-
- if (t == "string") {
- if (x.indexOf("'") == -1)
- return "'" + x + "'";
- if (x.indexOf('"') == -1)
- return '"' + x + '"';
- var s = x.replace(new RegExp('"', "g"), '\\\\"');
- return '"' + s + '"';
- };
-
- if (t == "undefined")
- return "undefined";
-
- // If we get here, x is an object. See if it's a Pyjamas class.
-
- if (!pyjslib.hasattr(x, "__init__"))
- return "<" + x.toString() + ">";
-
- // Handle the common Pyjamas data types.
-
- var constructor = "UNKNOWN";
-
- constructor = pyjslib.get_pyjs_classtype(x);
-
- //alert("repr constructor: " + constructor);
-
- if (constructor == "Tuple") {
- var contents = x.getArray();
- var s = "(";
- for (var i=0; i < contents.length; i++) {
- s += pyjslib.repr(contents[i]);
- if (i < contents.length - 1)
- s += ", ";
- };
- s += ")"
- return s;
- };
-
- if (constructor == "List") {
- var contents = x.getArray();
- var s = "[";
- for (var i=0; i < contents.length; i++) {
- s += pyjslib.repr(contents[i]);
- if (i < contents.length - 1)
- s += ", ";
- };
- s += "]"
- return s;
- };
-
- if (constructor == "Dict") {
- var keys = new Array();
- for (var key in x.d)
- keys.push(key);
-
- var s = "{";
- for (var i=0; i return the class name.
- // Note that we replace underscores with dots so that the name will
- // (hopefully!) look like the original Python name.
-
- //var s = constructor.replace(new RegExp('_', "g"), '.');
- return "<" + constructor + " object>";
- """)
-
-def float(text):
- JS("""
- return parseFloat(text);
- """)
-
-def int(text, radix=0):
- JS("""
- return parseInt(text, radix);
- """)
-
-def len(object):
- JS("""
- if (object==null) return 0;
- if (pyjslib.isObject(object) && object.__len__) return object.__len__();
- return object.length;
- """)
-
-def isinstance(object_, classinfo):
- if pyjslib.isUndefined(object_):
- return False
- if not pyjslib.isObject(object_):
-
- return False
- if _isinstance(classinfo, Tuple):
- for ci in classinfo:
- if isinstance(object_, ci):
- return True
- return False
- else:
- return _isinstance(object_, classinfo)
-
-def _isinstance(object_, classinfo):
- if not pyjslib.isObject(object_):
- return False
- JS("""
- if (object_.__class__){
- var res = object_ instanceof classinfo.constructor;
- return res;
- }
- return false;
- """)
-
-def getattr(obj, name, default_):
- JS("""
- if ((!pyjslib.isObject(obj))||(pyjslib.isUndefined(obj[name]))){
- if (pyjslib.isUndefined(default_)){
- throw pyjslib.AttributeError(obj, name);
- }else{
- return default_;
- }
- }
- if (!pyjslib.isFunction(obj[name])) return obj[name];
- var fnwrap = function() {
- var args = [];
- for (var i = 0; i < arguments.length; i++) {
- args.push(arguments[i]);
- }
- return obj[name].apply(obj,args);
- }
- fnwrap.__name__ = name;
- return fnwrap;
- """)
-
-def setattr(obj, name, value):
- JS("""
- if (!pyjslib.isObject(obj)) return null;
-
- obj[name] = value;
-
- """)
-
-def hasattr(obj, name):
- JS("""
- if (!pyjslib.isObject(obj)) return false;
- if (pyjslib.isUndefined(obj[name])) return false;
-
- return true;
- """)
-
-def dir(obj):
- JS("""
- var properties=new pyjslib.List();
- for (property in obj) properties.append(property);
- return properties;
- """)
-
-def filter(obj, method, sequence=None):
- # object context is LOST when a method is passed, hence object must be passed separately
- # to emulate python behaviour, should generate this code inline rather than as a function call
- items = []
- if sequence is None:
- sequence = method
- method = obj
-
- for item in sequence:
- if method(item):
- items.append(item)
- else:
- for item in sequence:
- if method.call(obj, item):
- items.append(item)
-
- return items
-
-
-def map(obj, method, sequence=None):
- items = []
-
- if sequence is None:
- sequence = method
- method = obj
-
- for item in sequence:
- items.append(method(item))
- else:
- for item in sequence:
- items.append(method.call(obj, item))
-
- return items
-
-
-def enumerate(sequence):
- enumeration = []
- nextIndex = 0
- for item in sequence:
- enumeration.append([nextIndex, item])
- nextIndex = nextIndex + 1
- return enumeration
-
-
-def min(*sequence):
- minValue = None
- for item in sequence:
- if minValue is None:
- minValue = item
- elif item < minValue:
- minValue = item
- return minValue
-
-
-def max(*sequence):
- maxValue = None
- for item in sequence:
- if maxValue is None:
- maxValue = item
- elif item > maxValue:
- maxValue = item
- return maxValue
-
-
-next_hash_id = 0
-
-def hash(obj):
- JS("""
- if (obj == null) return null;
-
- if (obj.$H) return obj.$H;
- if (obj.__hash__) return obj.__hash__();
- if (obj.constructor == String || obj.constructor == Number || obj.constructor == Date) return obj;
-
- obj.$H = ++pyjslib.next_hash_id;
- return obj.$H;
- """)
-
-
-# type functions from Douglas Crockford's Remedial Javascript: http://www.crockford.com/javascript/remedial.html
-def isObject(a):
- JS("""
- return (a != null && (typeof a == 'object')) || pyjslib.isFunction(a);
- """)
-
-def isFunction(a):
- JS("""
- return typeof a == 'function';
- """)
-
-def isString(a):
- JS("""
- return typeof a == 'string';
- """)
-
-def isNull(a):
- JS("""
- return typeof a == 'object' && !a;
- """)
-
-def isArray(a):
- JS("""
- return pyjslib.isObject(a) && a.constructor == Array;
- """)
-
-def isUndefined(a):
- JS("""
- return typeof a == 'undefined';
- """)
-
-def isIteratable(a):
- JS("""
- return pyjslib.isString(a) || (pyjslib.isObject(a) && a.__iter__);
- """)
-
-def isNumber(a):
- JS("""
- return typeof a == 'number' && isFinite(a);
- """)
-
-def toJSObjects(x):
- """
- Convert the pyjs pythonic List and Dict objects into javascript Object and Array
- objects, recursively.
- """
- if isArray(x):
- JS("""
- var result = [];
- for(var k=0; k < x.length; k++) {
- var v = x[k];
- var tv = pyjslib.toJSObjects(v);
- result.push(tv);
- }
- return result;
- """)
- if isObject(x):
- if isinstance(x, Dict):
- JS("""
- var o = x.getObject();
- var result = {};
- for (var i in o) {
- result[o[i][0].toString()] = o[i][1];
- }
- return pyjslib.toJSObjects(result)
- """)
- elif isinstance(x, List):
- return toJSObjects(x.l)
- elif hasattr(x, '__class__'):
- # we do not have a special implementation for custom
- # classes, just pass it on
- return x
- if isObject(x):
- JS("""
- var result = {};
- for(var k in x) {
- var v = x[k];
- var tv = pyjslib.toJSObjects(v)
- result[k] = tv;
- }
- return result;
- """)
- return x
-
-def printFunc(objs):
- JS("""
- if ($wnd.console==undefined) return;
- var s = "";
- for(var i=0; i < objs.length; i++) {
- if(s != "") s += " ";
- s += objs[i];
- }
- console.debug(s)
- """)
-
-def type(clsname, bases=None, methods=None):
- """ creates a class, derived from bases, with methods and variables
- """
-
- JS(" var mths = {}; ")
- if methods:
- for k in methods.keys():
- mth = methods[k]
- JS(" mths[k] = mth; ")
-
- JS(" var bss = null; ")
- if bases:
- JS("bss = bases.l;")
- JS(" return pyjs_type(clsname, bss, mths); ")
-
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/svgui/pyjs/lib/sys.py
--- a/plugins/python/modules/svgui/pyjs/lib/sys.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-# the platform name (PyV8, smjs, Mozilla, IE6, Opera, Safari etc.)
-platform = '' # to be updated by app, on compile
-
-# a dictionary of module override names (platform-specific)
-overrides = None # to be updated by app, on compile
-
-# the remote path for loading modules
-loadpath = None
-
-stacktrace = None
-
-appname = None
-
-def setloadpath(lp):
- global loadpath
- loadpath = lp
-
-def setappname(an):
- global appname
- appname = an
-
-def getloadpath():
- global loadpath
- return loadpath
-
-def addoverride(module_name, path):
- global overrides
- overrides[module_name] = path
-
-def addstack(linedebug):
- JS("""
- if (pyjslib.bool((sys.stacktrace === null))) {
- sys.stacktrace = new pyjslib.List([]);
- }
- sys.stacktrace.append(linedebug);
- """)
-def popstack():
- JS("""
- sys.stacktrace.pop()
- """)
-
-def printstack():
- JS("""
- var res = '';
-
- var __l = sys.stacktrace.__iter__();
- try {
- while (true) {
- var l = __l.next();
- res += ( l + '\\n' ) ;
- }
- } catch (e) {
- if (e != pyjslib.StopIteration) {
- throw e;
- }
- }
-
- return res;
- """)
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/svgui/pyjs/pyjs.py
--- a/plugins/python/modules/svgui/pyjs/pyjs.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1777 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2006 James Tauber and contributors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-import sys
-from types import StringType
-import compiler
-from compiler import ast
-import os
-import copy
-
-# the standard location for builtins (e.g. pyjslib) can be
-# over-ridden by changing this. it defaults to sys.prefix
-# so that on a system-wide install of pyjamas the builtins
-# can be found in e.g. {sys.prefix}/share/pyjamas
-#
-# over-rides can be done by either explicitly modifying
-# pyjs.prefix or by setting an environment variable, PYJSPREFIX.
-
-prefix = sys.prefix
-
-if os.environ.has_key('PYJSPREFIX'):
- prefix = os.environ['PYJSPREFIX']
-
-# pyjs.path is the list of paths, just like sys.path, from which
-# library modules will be searched for, for compile purposes.
-# obviously we don't want to use sys.path because that would result
-# in compiling standard python modules into javascript!
-
-path = [os.path.abspath('')]
-
-if os.environ.has_key('PYJSPATH'):
- for p in os.environ['PYJSPATH'].split(os.pathsep):
- p = os.path.abspath(p)
- if os.path.isdir(p):
- path.append(p)
-
-# this is the python function used to wrap native javascript
-NATIVE_JS_FUNC_NAME = "JS"
-
-UU = ""
-
-PYJSLIB_BUILTIN_FUNCTIONS=("cmp",
- "map",
- "filter",
- "dir",
- "getattr",
- "setattr",
- "hasattr",
- "int",
- "float",
- "str",
- "repr",
- "range",
- "len",
- "hash",
- "abs",
- "ord",
- "chr",
- "enumerate",
- "min",
- "max",
- "bool",
- "type",
- "isinstance")
-
-PYJSLIB_BUILTIN_CLASSES=("BaseException",
- "Exception",
- "StandardError",
- "StopIteration",
- "AttributeError",
- "TypeError",
- "KeyError",
- "LookupError",
- "list",
- "dict",
- "object",
- "tuple",
- )
-
-def pyjs_builtin_remap(name):
- # XXX HACK!
- if name == 'list':
- name = 'List'
- if name == 'object':
- name = '__Object'
- if name == 'dict':
- name = 'Dict'
- if name == 'tuple':
- name = 'Tuple'
- return name
-
-# XXX: this is a hack: these should be dealt with another way
-# however, console is currently the only global name which is causing
-# problems.
-PYJS_GLOBAL_VARS=("console")
-
-# This is taken from the django project.
-# Escape every ASCII character with a value less than 32.
-JS_ESCAPES = (
- ('\\', r'\x5C'),
- ('\'', r'\x27'),
- ('"', r'\x22'),
- ('>', r'\x3E'),
- ('<', r'\x3C'),
- ('&', r'\x26'),
- (';', r'\x3B')
- ) + tuple([('%c' % z, '\\x%02X' % z) for z in range(32)])
-
-def escapejs(value):
- """Hex encodes characters for use in JavaScript strings."""
- for bad, good in JS_ESCAPES:
- value = value.replace(bad, good)
- return value
-
-def uuprefix(name, leave_alone=0):
- name = name.split(".")
- name = name[:leave_alone] + map(lambda x: "__%s" % x, name[leave_alone:])
- return '.'.join(name)
-
-class Klass:
-
- klasses = {}
-
- def __init__(self, name, name_):
- self.name = name
- self.name_ = name_
- self.klasses[name] = self
- self.functions = set()
-
- def set_base(self, base_name):
- self.base = self.klasses.get(base_name)
-
- def add_function(self, function_name):
- self.functions.add(function_name)
-
-
-class TranslationError(Exception):
- def __init__(self, message, node):
- self.message = "line %s:\n%s\n%s" % (node.lineno, message, node)
-
- def __str__(self):
- return self.message
-
-def strip_py(name):
- return name
-
-def mod_var_name_decl(raw_module_name):
- """ function to get the last component of the module e.g.
- pyjamas.ui.DOM into the "namespace". i.e. doing
- "import pyjamas.ui.DOM" actually ends up with _two_
- variables - one pyjamas.ui.DOM, the other just "DOM".
- but "DOM" is actually local, hence the "var" prefix.
-
- for PyV8, this might end up causing problems - we'll have
- to see: gen_mod_import and mod_var_name_decl might have
- to end up in a library-specific module, somewhere.
- """
- name = raw_module_name.split(".")
- if len(name) == 1:
- return ''
- child_name = name[-1]
- return "var %s = %s;\n" % (child_name, raw_module_name)
-
-def gen_mod_import(parentName, importName, dynamic=1):
- #pyjs_ajax_eval("%(n)s.cache.js", null, true);
- return """
- pyjslib.import_module(sys.loadpath, '%(p)s', '%(n)s', %(d)d, false);
- """ % ({'p': parentName, 'd': dynamic, 'n': importName}) + \
- mod_var_name_decl(importName)
-
-class Translator:
-
- def __init__(self, mn, module_name, raw_module_name, src, debug, mod, output,
- dynamic=0, optimize=False,
- findFile=None):
-
- if module_name:
- self.module_prefix = module_name + "."
- else:
- self.module_prefix = ""
- self.raw_module_name = raw_module_name
- src = src.replace("\r\n", "\n")
- src = src.replace("\n\r", "\n")
- src = src.replace("\r", "\n")
- self.src = src.split("\n")
- self.debug = debug
- self.imported_modules = []
- self.imported_modules_as = []
- self.imported_js = set()
- self.top_level_functions = set()
- self.top_level_classes = set()
- self.top_level_vars = set()
- self.local_arg_stack = [[]]
- self.output = output
- self.imported_classes = {}
- self.method_imported_globals = set()
- self.method_self = None
- self.nextTupleAssignID = 1
- self.dynamic = dynamic
- self.optimize = optimize
- self.findFile = findFile
-
- if module_name.find(".") >= 0:
- vdec = ''
- else:
- vdec = 'var '
- print >>self.output, UU+"%s%s = function (__mod_name__) {" % (vdec, module_name)
-
- print >>self.output, " if("+module_name+".__was_initialized__) return;"
- print >>self.output, " "+UU+module_name+".__was_initialized__ = true;"
- print >>self.output, UU+"if (__mod_name__ == null) __mod_name__ = '%s';" % (mn)
- print >>self.output, UU+"%s.__name__ = __mod_name__;" % (raw_module_name)
-
- decl = mod_var_name_decl(raw_module_name)
- if decl:
- print >>self.output, decl
-
-
- if self.debug:
- haltException = self.module_prefix + "HaltException"
- print >>self.output, haltException + ' = function () {'
- print >>self.output, ' this.message = "Program Halted";'
- print >>self.output, ' this.name = "' + haltException + '";'
- print >>self.output, '}'
- print >>self.output, ''
- print >>self.output, haltException + ".prototype.__str__ = function()"
- print >>self.output, '{'
- print >>self.output, 'return this.message ;'
- print >>self.output, '}'
-
- print >>self.output, haltException + ".prototype.toString = function()"
- print >>self.output, '{'
- print >>self.output, 'return this.name + ": \\"" + this.message + "\\"";'
- print >>self.output, '}'
-
- isHaltFunction = self.module_prefix + "IsHaltException"
- print >>self.output, """
- %s = function (s) {
- var suffix="HaltException";
- if (s.length < suffix.length) {
- //alert(s + " " + suffix);
- return false;
- } else {
- var ss = s.substring(s.length, (s.length - suffix.length));
- //alert(s + " " + suffix + " " + ss);
- return ss == suffix;
- }
- }
- """ % isHaltFunction
- for child in mod.node:
- if isinstance(child, ast.Function):
- self.top_level_functions.add(child.name)
- elif isinstance(child, ast.Class):
- self.top_level_classes.add(child.name)
-
- for child in mod.node:
- if isinstance(child, ast.Function):
- self._function(child, False)
- elif isinstance(child, ast.Class):
- self._class(child)
- elif isinstance(child, ast.Import):
- importName = child.names[0][0]
- if importName == '__pyjamas__': # special module to help make pyjamas modules loadable in the python interpreter
- pass
- elif importName.endswith('.js'):
- self.imported_js.add(importName)
- else:
- self.add_imported_module(strip_py(importName))
- elif isinstance(child, ast.From):
- if child.modname == '__pyjamas__': # special module to help make pyjamas modules loadable in the python interpreter
- pass
- else:
- self.add_imported_module(child.modname)
- self._from(child)
- elif isinstance(child, ast.Discard):
- self._discard(child, None)
- elif isinstance(child, ast.Assign):
- self._assign(child, None, True)
- elif isinstance(child, ast.AugAssign):
- self._augassign(child, None)
- elif isinstance(child, ast.If):
- self._if(child, None)
- elif isinstance(child, ast.For):
- self._for(child, None)
- elif isinstance(child, ast.While):
- self._while(child, None)
- elif isinstance(child, ast.Subscript):
- self._subscript_stmt(child, None)
- elif isinstance(child, ast.Global):
- self._global(child, None)
- elif isinstance(child, ast.Printnl):
- self._print(child, None)
- elif isinstance(child, ast.Print):
- self._print(child, None)
- elif isinstance(child, ast.TryExcept):
- self._tryExcept(child, None)
- elif isinstance(child, ast.Raise):
- self._raise(child, None)
- elif isinstance(child, ast.Stmt):
- self._stmt(child, None)
- else:
- raise TranslationError("unsupported type (in __init__)", child)
-
- # Initialize all classes for this module
- #print >> self.output, "__"+self.modpfx()+\
- # "classes_initialize = function() {\n"
- #for className in self.top_level_classes:
- # print >> self.output, "\t"+UU+self.modpfx()+"__"+className+"_initialize();"
- #print >> self.output, "};\n"
-
- print >> self.output, "return this;\n"
- print >> self.output, "}; /* end %s */ \n" % module_name
-
- def module_imports(self):
- return self.imported_modules + self.imported_modules_as
-
- def add_local_arg(self, varname):
- local_vars = self.local_arg_stack[-1]
- if varname not in local_vars:
- local_vars.append(varname)
-
- def add_imported_module(self, importName):
-
- if importName in self.imported_modules:
- return
- self.imported_modules.append(importName)
- name = importName.split(".")
- if len(name) != 1:
- # add the name of the module to the namespace,
- # but don't add the short name to imported_modules
- # because then the short name would be attempted to be
- # added to the dependencies, and it's half way up the
- # module import directory structure!
- child_name = name[-1]
- self.imported_modules_as.append(child_name)
- print >> self.output, gen_mod_import(self.raw_module_name,
- strip_py(importName),
- self.dynamic)
-
- def _default_args_handler(self, node, arg_names, current_klass,
- output=None):
- if len(node.defaults):
- output = output or self.output
- default_pos = len(arg_names) - len(node.defaults)
- if arg_names and arg_names[0] == self.method_self:
- default_pos -= 1
- for default_node in node.defaults:
- if isinstance(default_node, ast.Const):
- default_value = self._const(default_node)
- elif isinstance(default_node, ast.Name):
- default_value = self._name(default_node, current_klass)
- elif isinstance(default_node, ast.UnarySub):
- default_value = self._unarysub(default_node, current_klass)
- else:
- raise TranslationError("unsupported type (in _method)", default_node)
-
- default_name = arg_names[default_pos]
- default_pos += 1
- print >> output, " if (typeof %s == 'undefined') %s=%s;" % (default_name, default_name, default_value)
-
- def _varargs_handler(self, node, varargname, arg_names, current_klass):
- print >>self.output, " var", varargname, '= new pyjslib.Tuple();'
- print >>self.output, " for(var __va_arg="+str(len(arg_names))+"; __va_arg < arguments.length; __va_arg++) {"
- print >>self.output, " var __arg = arguments[__va_arg];"
- print >>self.output, " "+varargname+".append(__arg);"
- print >>self.output, " }"
-
- def _kwargs_parser(self, node, function_name, arg_names, current_klass):
- if len(node.defaults) or node.kwargs:
- default_pos = len(arg_names) - len(node.defaults)
- if arg_names and arg_names[0] == self.method_self:
- default_pos -= 1
- print >>self.output, function_name+'.parse_kwargs = function (', ", ".join(["__kwargs"]+arg_names), ") {"
- for default_node in node.defaults:
- default_value = self.expr(default_node, current_klass)
-# if isinstance(default_node, ast.Const):
-# default_value = self._const(default_node)
-# elif isinstance(default_node, ast.Name):
-# default_value = self._name(default_node)
-# elif isinstance(default_node, ast.UnarySub):
-# default_value = self._unarysub(default_node, current_klass)
-# else:
-# raise TranslationError("unsupported type (in _method)", default_node)
-
- default_name = arg_names[default_pos]
- print >>self.output, " if (typeof %s == 'undefined')"%(default_name)
- print >>self.output, " %s=__kwargs.%s;"% (default_name, default_name)
- default_pos += 1
-
- #self._default_args_handler(node, arg_names, current_klass)
- if node.kwargs: arg_names += ["pyjslib.Dict(__kwargs)"]
- print >>self.output, " var __r = "+"".join(["[", ", ".join(arg_names), "]"])+";"
- if node.varargs:
- self._varargs_handler(node, "__args", arg_names, current_klass)
- print >>self.output, " __r.push.apply(__r, __args.getArray())"
- print >>self.output, " return __r;"
- print >>self.output, "};"
-
- def _function(self, node, local=False):
- if local:
- function_name = node.name
- self.add_local_arg(function_name)
- else:
- function_name = UU + self.modpfx() + node.name
-
- arg_names = list(node.argnames)
- normal_arg_names = list(arg_names)
- if node.kwargs: kwargname = normal_arg_names.pop()
- if node.varargs: varargname = normal_arg_names.pop()
- declared_arg_names = list(normal_arg_names)
- if node.kwargs: declared_arg_names.append(kwargname)
-
- function_args = "(" + ", ".join(declared_arg_names) + ")"
- print >>self.output, "%s = function%s {" % (function_name, function_args)
- self._default_args_handler(node, normal_arg_names, None)
-
- local_arg_names = normal_arg_names + declared_arg_names
-
- if node.varargs:
- self._varargs_handler(node, varargname, declared_arg_names, None)
- local_arg_names.append(varargname)
-
- # stack of local variable names for this function call
- self.local_arg_stack.append(local_arg_names)
-
- for child in node.code:
- self._stmt(child, None)
-
- # remove the top local arg names
- self.local_arg_stack.pop()
-
- # we need to return null always, so it is not undefined
- lastStmt = [p for p in node.code][-1]
- if not isinstance(lastStmt, ast.Return):
- if not self._isNativeFunc(lastStmt):
- print >>self.output, " return null;"
-
- print >>self.output, "};"
- print >>self.output, "%s.__name__ = '%s';\n" % (function_name, node.name)
-
-
- self._kwargs_parser(node, function_name, normal_arg_names, None)
-
-
- def _return(self, node, current_klass):
- expr = self.expr(node.value, current_klass)
- # in python a function call always returns None, so we do it
- # here too
- print >>self.output, " return " + expr + ";"
-
-
- def _break(self, node, current_klass):
- print >>self.output, " break;"
-
-
- def _continue(self, node, current_klass):
- print >>self.output, " continue;"
-
-
- def _callfunc(self, v, current_klass):
-
- if isinstance(v.node, ast.Name):
- if v.node.name in self.top_level_functions:
- call_name = self.modpfx() + v.node.name
- elif v.node.name in self.top_level_classes:
- call_name = self.modpfx() + v.node.name
- elif self.imported_classes.has_key(v.node.name):
- call_name = self.imported_classes[v.node.name] + '.' + v.node.name
- elif v.node.name in PYJSLIB_BUILTIN_FUNCTIONS:
- call_name = 'pyjslib.' + v.node.name
- elif v.node.name in PYJSLIB_BUILTIN_CLASSES:
- name = pyjs_builtin_remap(v.node.name)
- call_name = 'pyjslib.' + name
- elif v.node.name == "callable":
- call_name = "pyjslib.isFunction"
- else:
- call_name = v.node.name
- call_args = []
- elif isinstance(v.node, ast.Getattr):
- attr_name = v.node.attrname
-
- if isinstance(v.node.expr, ast.Name):
- call_name = self._name2(v.node.expr, current_klass, attr_name)
- call_args = []
- elif isinstance(v.node.expr, ast.Getattr):
- call_name = self._getattr2(v.node.expr, current_klass, attr_name)
- call_args = []
- elif isinstance(v.node.expr, ast.CallFunc):
- call_name = self._callfunc(v.node.expr, current_klass) + "." + v.node.attrname
- call_args = []
- elif isinstance(v.node.expr, ast.Subscript):
- call_name = self._subscript(v.node.expr, current_klass) + "." + v.node.attrname
- call_args = []
- elif isinstance(v.node.expr, ast.Const):
- call_name = self.expr(v.node.expr, current_klass) + "." + v.node.attrname
- call_args = []
- else:
- raise TranslationError("unsupported type (in _callfunc)", v.node.expr)
- else:
- raise TranslationError("unsupported type (in _callfunc)", v.node)
-
- call_name = strip_py(call_name)
-
- kwargs = []
- star_arg_name = None
- if v.star_args:
- star_arg_name = self.expr(v.star_args, current_klass)
-
- for ch4 in v.args:
- if isinstance(ch4, ast.Keyword):
- kwarg = ch4.name + ":" + self.expr(ch4.expr, current_klass)
- kwargs.append(kwarg)
- else:
- arg = self.expr(ch4, current_klass)
- call_args.append(arg)
-
- if kwargs:
- fn_args = ", ".join(['{' + ', '.join(kwargs) + '}']+call_args)
- else:
- fn_args = ", ".join(call_args)
-
- if kwargs or star_arg_name:
- if not star_arg_name:
- star_arg_name = 'null'
- try: call_this, method_name = call_name.rsplit(".", 1)
- except ValueError:
- # Must be a function call ...
- return ("pyjs_kwargs_function_call("+call_name+", "
- + star_arg_name
- + ", ["+fn_args+"]"
- + ")" )
- else:
- return ("pyjs_kwargs_method_call("+call_this+", '"+method_name+"', "
- + star_arg_name
- + ", ["+fn_args+"]"
- + ")")
- else:
- return call_name + "(" + ", ".join(call_args) + ")"
-
- def _print(self, node, current_klass):
- if self.optimize:
- return
- call_args = []
- for ch4 in node.nodes:
- arg = self.expr(ch4, current_klass)
- call_args.append(arg)
-
- print >>self.output, "pyjslib.printFunc([", ', '.join(call_args), "],", int(isinstance(node, ast.Printnl)), ");"
-
- def _tryExcept(self, node, current_klass):
- if len(node.handlers) != 1:
- raise TranslationError("except statements in this form are" +
- " not supported", node)
-
- expr = node.handlers[0][0]
- as_ = node.handlers[0][1]
- if as_:
- errName = as_.name
- else:
- errName = 'err'
-
- # XXX TODO: check that this should instead be added as a _separate_
- # local scope, temporary to the function. oh dearie me.
- self.add_local_arg(errName)
-
- print >>self.output, " try {"
- for stmt in node.body.nodes:
- self._stmt(stmt, current_klass)
- print >> self.output, " } catch(%s) {" % errName
- if expr:
- l = []
- if isinstance(expr, ast.Tuple):
- for x in expr.nodes:
- l.append("(%(err)s.__name__ == %(expr)s.__name__)" % dict (err=errName, expr=self.expr(x, current_klass)))
- else:
- l = [ " (%(err)s.__name__ == %(expr)s.__name__) " % dict (err=errName, expr=self.expr(expr, current_klass)) ]
- print >> self.output, " if(%s) {" % '||\n\t\t'.join(l)
- for stmt in node.handlers[0][2]:
- self._stmt(stmt, current_klass)
- if expr:
- #print >> self.output, "} else { throw(%s); } " % errName
- print >> self.output, "}"
- if node.else_ != None:
- print >>self.output, " } finally {"
- for stmt in node.else_:
- self._stmt(stmt, current_klass)
- print >>self.output, " }"
-
- # XXX: change use_getattr to True to enable "strict" compilation
- # but incurring a 100% performance penalty. oops.
- def _getattr(self, v, current_klass, use_getattr=False):
- attr_name = v.attrname
- if isinstance(v.expr, ast.Name):
- obj = self._name(v.expr, current_klass, return_none_for_module=True)
- if obj == None and v.expr.name in self.module_imports():
- # XXX TODO: distinguish between module import classes
- # and variables. right now, this is a hack to get
- # the sys module working.
- #if v.expr.name == 'sys':
- return v.expr.name+'.'+attr_name
- #return v.expr.name+'.__'+attr_name+'.prototype.__class__'
- if not use_getattr or attr_name == '__class__' or \
- attr_name == '__name__':
- return obj + "." + attr_name
- return "pyjslib.getattr(%s, '%s')" % (obj, attr_name)
- elif isinstance(v.expr, ast.Getattr):
- return self._getattr(v.expr, current_klass) + "." + attr_name
- elif isinstance(v.expr, ast.Subscript):
- return self._subscript(v.expr, self.modpfx()) + "." + attr_name
- elif isinstance(v.expr, ast.CallFunc):
- return self._callfunc(v.expr, self.modpfx()) + "." + attr_name
- else:
- raise TranslationError("unsupported type (in _getattr)", v.expr)
-
-
- def modpfx(self):
- return strip_py(self.module_prefix)
-
- def _name(self, v, current_klass, top_level=False,
- return_none_for_module=False):
-
- if v.name == 'ilikesillynamesfornicedebugcode':
- print top_level, current_klass, repr(v)
- print self.top_level_vars
- print self.top_level_functions
- print self.local_arg_stack
- print "error..."
-
- local_var_names = None
- las = len(self.local_arg_stack)
- if las > 0:
- local_var_names = self.local_arg_stack[-1]
-
- if v.name == "True":
- return "true"
- elif v.name == "False":
- return "false"
- elif v.name == "None":
- return "null"
- elif v.name == '__name__' and current_klass is None:
- return self.modpfx() + v.name
- elif v.name == self.method_self:
- return "this"
- elif v.name in self.top_level_functions:
- return UU+self.modpfx() + v.name
- elif v.name in self.method_imported_globals:
- return UU+self.modpfx() + v.name
- elif not current_klass and las == 1 and v.name in self.top_level_vars:
- return UU+self.modpfx() + v.name
- elif v.name in local_var_names:
- return v.name
- elif self.imported_classes.has_key(v.name):
- return UU+self.imported_classes[v.name] + '.__' + v.name + ".prototype.__class__"
- elif v.name in self.top_level_classes:
- return UU+self.modpfx() + "__" + v.name + ".prototype.__class__"
- elif v.name in self.module_imports() and return_none_for_module:
- return None
- elif v.name in PYJSLIB_BUILTIN_CLASSES:
- return "pyjslib." + pyjs_builtin_remap( v.name )
- elif current_klass:
- if v.name not in local_var_names and \
- v.name not in self.top_level_vars and \
- v.name not in PYJS_GLOBAL_VARS and \
- v.name not in self.top_level_functions:
-
- cls_name = current_klass
- if hasattr(cls_name, "name"):
- cls_name_ = cls_name.name_
- cls_name = cls_name.name
- else:
- cls_name_ = current_klass + "_" # XXX ???
- name = UU+cls_name_ + ".prototype.__class__." \
- + v.name
- if v.name == 'listener':
- name = 'listener+' + name
- return name
-
- return v.name
-
- def _name2(self, v, current_klass, attr_name):
- obj = v.name
-
- if obj in self.method_imported_globals:
- call_name = UU+self.modpfx() + obj + "." + attr_name
- elif self.imported_classes.has_key(obj):
- #attr_str = ""
- #if attr_name != "__init__":
- attr_str = ".prototype.__class__." + attr_name
- call_name = UU+self.imported_classes[obj] + '.__' + obj + attr_str
- elif obj in self.module_imports():
- call_name = obj + "." + attr_name
- elif obj[0] == obj[0].upper(): # XXX HACK ALERT
- call_name = UU + self.modpfx() + "__" + obj + ".prototype.__class__." + attr_name
- else:
- call_name = UU+self._name(v, current_klass) + "." + attr_name
-
- return call_name
-
-
- def _getattr2(self, v, current_klass, attr_name):
- if isinstance(v.expr, ast.Getattr):
- call_name = self._getattr2(v.expr, current_klass, v.attrname + "." + attr_name)
- elif isinstance(v.expr, ast.Name) and v.expr.name in self.module_imports():
- call_name = UU+v.expr.name + '.__' +v.attrname+".prototype.__class__."+attr_name
- else:
- obj = self.expr(v.expr, current_klass)
- call_name = obj + "." + v.attrname + "." + attr_name
-
- return call_name
-
-
- def _class(self, node):
- """
- Handle a class definition.
-
- In order to translate python semantics reasonably well, the following
- structure is used:
-
- A special object is created for the class, which inherits attributes
- from the superclass, or Object if there's no superclass. This is the
- class object; the object which you refer to when specifying the
- class by name. Static, class, and unbound methods are copied
- from the superclass object.
-
- A special constructor function is created with the same name as the
- class, which is used to create instances of that class.
-
- A javascript class (e.g. a function with a prototype attribute) is
- created which is the javascript class of created instances, and
- which inherits attributes from the class object. Bound methods are
- copied from the superclass into this class rather than inherited,
- because the class object contains unbound, class, and static methods
- that we don't necessarily want to inherit.
-
- The type of a method can now be determined by inspecting its
- static_method, unbound_method, class_method, or instance_method
- attribute; only one of these should be true.
-
- Much of this work is done in pyjs_extend, is pyjslib.py
- """
- class_name = self.modpfx() + uuprefix(node.name, 1)
- class_name_ = self.modpfx() + uuprefix(node.name)
- current_klass = Klass(class_name, class_name_)
- init_method = None
- for child in node.code:
- if isinstance(child, ast.Function):
- current_klass.add_function(child.name)
- if child.name == "__init__":
- init_method = child
-
-
- if len(node.bases) == 0:
- base_class = "pyjslib.__Object"
- elif len(node.bases) == 1:
- if isinstance(node.bases[0], ast.Name):
- if self.imported_classes.has_key(node.bases[0].name):
- base_class_ = self.imported_classes[node.bases[0].name] + '.__' + node.bases[0].name
- base_class = self.imported_classes[node.bases[0].name] + '.' + node.bases[0].name
- else:
- base_class_ = self.modpfx() + "__" + node.bases[0].name
- base_class = self.modpfx() + node.bases[0].name
- elif isinstance(node.bases[0], ast.Getattr):
- # the bases are not in scope of the class so do not
- # pass our class to self._name
- base_class_ = self._name(node.bases[0].expr, None) + \
- ".__" + node.bases[0].attrname
- base_class = self._name(node.bases[0].expr, None) + \
- "." + node.bases[0].attrname
- else:
- raise TranslationError("unsupported type (in _class)", node.bases[0])
-
- current_klass.set_base(base_class)
- else:
- raise TranslationError("more than one base (in _class)", node)
-
- print >>self.output, UU+class_name_ + " = function () {"
- # call superconstructor
- #if base_class:
- # print >>self.output, " __" + base_class + ".call(this);"
- print >>self.output, "}"
-
- if not init_method:
- init_method = ast.Function([], "__init__", ["self"], [], 0, None, [])
- #self._method(init_method, current_klass, class_name)
-
- # Generate a function which constructs the object
- clsfunc = ast.Function([],
- node.name,
- init_method.argnames[1:],
- init_method.defaults,
- init_method.flags,
- None,
- [ast.Discard(ast.CallFunc(ast.Name("JS"), [ast.Const(
-# I attempted lazy initialization, but then you can't access static class members
-# " if(!__"+base_class+".__was_initialized__)"+
-# " __" + class_name + "_initialize();\n" +
- " var instance = new " + UU + class_name_ + "();\n" +
- " if(instance.__init__) instance.__init__.apply(instance, arguments);\n" +
- " return instance;"
- )]))])
-
- self._function(clsfunc, False)
- print >>self.output, UU+class_name_ + ".__initialize__ = function () {"
- print >>self.output, " if("+UU+class_name_+".__was_initialized__) return;"
- print >>self.output, " "+UU+class_name_+".__was_initialized__ = true;"
- cls_obj = UU+class_name_ + '.prototype.__class__'
-
- if class_name == "pyjslib.__Object":
- print >>self.output, " "+cls_obj+" = {};"
- else:
- if base_class and base_class not in ("object", "pyjslib.__Object"):
- print >>self.output, " if(!"+UU+base_class_+".__was_initialized__)"
- print >>self.output, " "+UU+base_class_+".__initialize__();"
- print >>self.output, " pyjs_extend(" + UU+class_name_ + ", "+UU+base_class_+");"
- else:
- print >>self.output, " pyjs_extend(" + UU+class_name_ + ", "+UU+"pyjslib.__Object);"
-
- print >>self.output, " "+cls_obj+".__new__ = "+UU+class_name+";"
- print >>self.output, " "+cls_obj+".__name__ = '"+UU+node.name+"';"
-
- for child in node.code:
- if isinstance(child, ast.Pass):
- pass
- elif isinstance(child, ast.Function):
- self._method(child, current_klass, class_name, class_name_)
- elif isinstance(child, ast.Assign):
- self.classattr(child, current_klass)
- elif isinstance(child, ast.Discard) and isinstance(child.expr, ast.Const):
- # Probably a docstring, turf it
- pass
- else:
- raise TranslationError("unsupported type (in _class)", child)
- print >>self.output, "}"
-
- print >> self.output, class_name_+".__initialize__();"
-
-
- def classattr(self, node, current_klass):
- self._assign(node, current_klass, True)
-
- def _raise(self, node, current_klass):
- if node.expr2:
- raise TranslationError("More than one expression unsupported",
- node)
- print >> self.output, "throw (%s);" % self.expr(
- node.expr1, current_klass)
-
- def _method(self, node, current_klass, class_name, class_name_):
- # reset global var scope
- self.method_imported_globals = set()
-
- arg_names = list(node.argnames)
-
- classmethod = False
- staticmethod = False
- if node.decorators:
- for d in node.decorators:
- if d.name == "classmethod":
- classmethod = True
- elif d.name == "staticmethod":
- staticmethod = True
-
- if staticmethod:
- staticfunc = ast.Function([], class_name_+"."+node.name, node.argnames, node.defaults, node.flags, node.doc, node.code, node.lineno)
- self._function(staticfunc, True)
- print >>self.output, " " + UU+class_name_ + ".prototype.__class__." + node.name + " = " + class_name_+"."+node.name+";";
- print >>self.output, " " + UU+class_name_ + ".prototype.__class__." + node.name + ".static_method = true;";
- return
- else:
- if len(arg_names) == 0:
- raise TranslationError("methods must take an argument 'self' (in _method)", node)
- self.method_self = arg_names[0]
-
- #if not classmethod and arg_names[0] != "self":
- # raise TranslationError("first arg not 'self' (in _method)", node)
-
- normal_arg_names = arg_names[1:]
- if node.kwargs: kwargname = normal_arg_names.pop()
- if node.varargs: varargname = normal_arg_names.pop()
- declared_arg_names = list(normal_arg_names)
- if node.kwargs: declared_arg_names.append(kwargname)
-
- function_args = "(" + ", ".join(declared_arg_names) + ")"
-
- if classmethod:
- fexpr = UU + class_name_ + ".prototype.__class__." + node.name
- else:
- fexpr = UU + class_name_ + ".prototype." + node.name
- print >>self.output, " "+fexpr + " = function" + function_args + " {"
-
- # default arguments
- self._default_args_handler(node, normal_arg_names, current_klass)
-
- local_arg_names = normal_arg_names + declared_arg_names
-
- if node.varargs:
- self._varargs_handler(node, varargname, declared_arg_names, current_klass)
- local_arg_names.append(varargname)
-
-
- # stack of local variable names for this function call
- self.local_arg_stack.append(local_arg_names)
-
- for child in node.code:
- self._stmt(child, current_klass)
-
- # remove the top local arg names
- self.local_arg_stack.pop()
-
- print >>self.output, " };"
-
- self._kwargs_parser(node, fexpr, normal_arg_names, current_klass)
-
- if classmethod:
- # Have to create a version on the instances which automatically passes the
- # class as "self"
- altexpr = UU + class_name_ + ".prototype." + node.name
- print >>self.output, " "+altexpr + " = function() {"
- print >>self.output, " return " + fexpr + ".apply(this.__class__, arguments);"
- print >>self.output, " };"
- print >>self.output, " "+fexpr+".class_method = true;"
- print >>self.output, " "+altexpr+".instance_method = true;"
- else:
- # For instance methods, we need an unbound version in the class object
- altexpr = UU + class_name_ + ".prototype.__class__." + node.name
- print >>self.output, " "+altexpr + " = function() {"
- print >>self.output, " return " + fexpr + ".call.apply("+fexpr+", arguments);"
- print >>self.output, " };"
- print >>self.output, " "+altexpr+".unbound_method = true;"
- print >>self.output, " "+fexpr+".instance_method = true;"
- print >>self.output, " "+altexpr+".__name__ = '%s';" % node.name
-
- print >>self.output, UU + class_name_ + ".prototype.%s.__name__ = '%s';" % \
- (node.name, node.name)
-
- if node.kwargs or len(node.defaults):
- print >>self.output, " "+altexpr + ".parse_kwargs = " + fexpr + ".parse_kwargs;"
-
- self.method_self = None
- self.method_imported_globals = set()
-
- def _isNativeFunc(self, node):
- if isinstance(node, ast.Discard):
- if isinstance(node.expr, ast.CallFunc):
- if isinstance(node.expr.node, ast.Name) and \
- node.expr.node.name == NATIVE_JS_FUNC_NAME:
- return True
- return False
-
- def _stmt(self, node, current_klass):
- debugStmt = self.debug and not self._isNativeFunc(node)
- if debugStmt:
- print >>self.output, ' try {'
-
- if isinstance(node, ast.Return):
- self._return(node, current_klass)
- elif isinstance(node, ast.Break):
- self._break(node, current_klass)
- elif isinstance(node, ast.Continue):
- self._continue(node, current_klass)
- elif isinstance(node, ast.Assign):
- self._assign(node, current_klass)
- elif isinstance(node, ast.AugAssign):
- self._augassign(node, current_klass)
- elif isinstance(node, ast.Discard):
- self._discard(node, current_klass)
- elif isinstance(node, ast.If):
- self._if(node, current_klass)
- elif isinstance(node, ast.For):
- self._for(node, current_klass)
- elif isinstance(node, ast.While):
- self._while(node, current_klass)
- elif isinstance(node, ast.Subscript):
- self._subscript_stmt(node, current_klass)
- elif isinstance(node, ast.Global):
- self._global(node, current_klass)
- elif isinstance(node, ast.Pass):
- pass
- elif isinstance(node, ast.Function):
- self._function(node, True)
- elif isinstance(node, ast.Printnl):
- self._print(node, current_klass)
- elif isinstance(node, ast.Print):
- self._print(node, current_klass)
- elif isinstance(node, ast.TryExcept):
- self._tryExcept(node, current_klass)
- elif isinstance(node, ast.Raise):
- self._raise(node, current_klass)
- else:
- raise TranslationError("unsupported type (in _stmt)", node)
-
- if debugStmt:
-
- lt = self.get_line_trace(node)
-
- haltException = self.module_prefix + "HaltException"
- isHaltFunction = self.module_prefix + "IsHaltException"
-
- print >>self.output, ' } catch (__err) {'
- print >>self.output, ' if (' + isHaltFunction + '(__err.name)) {'
- print >>self.output, ' throw __err;'
- print >>self.output, ' } else {'
- print >>self.output, " st = sys.printstack() + "\
- + '"%s"' % lt + "+ '\\n' ;"
- print >>self.output, ' alert("' + "Error in " \
- + lt + '"' \
- + '+"\\n"+__err.name+": "+__err.message'\
- + '+"\\n\\nStack trace:\\n"' \
- + '+st' \
- + ');'
- print >>self.output, ' debugger;'
-
- print >>self.output, ' throw new ' + self.module_prefix + "HaltException();"
- print >>self.output, ' }'
- print >>self.output, ' }'
-
-
- def get_line_trace(self, node):
- lineNum = "Unknown"
- srcLine = ""
- if hasattr(node, "lineno"):
- if node.lineno != None:
- lineNum = node.lineno
- srcLine = self.src[min(lineNum, len(self.src))-1]
- srcLine = srcLine.replace('\\', '\\\\')
- srcLine = srcLine.replace('"', '\\"')
- srcLine = srcLine.replace("'", "\\'")
-
- return self.raw_module_name + ".py, line " \
- + str(lineNum) + ":"\
- + "\\n" \
- + " " + srcLine
-
- def _augassign(self, node, current_klass):
- v = node.node
- if isinstance(v, ast.Getattr):
- # XXX HACK! don't allow += on return result of getattr.
- # TODO: create a temporary variable or something.
- lhs = self._getattr(v, current_klass, False)
- else:
- lhs = self._name(node.node, current_klass)
- op = node.op
- rhs = self.expr(node.expr, current_klass)
- print >>self.output, " " + lhs + " " + op + " " + rhs + ";"
-
-
- def _assign(self, node, current_klass, top_level = False):
- if len(node.nodes) != 1:
- tempvar = '__temp'+str(node.lineno)
- tnode = ast.Assign([ast.AssName(tempvar, "OP_ASSIGN", node.lineno)], node.expr, node.lineno)
- self._assign(tnode, current_klass, top_level)
- for v in node.nodes:
- tnode2 = ast.Assign([v], ast.Name(tempvar, node.lineno), node.lineno)
- self._assign(tnode2, current_klass, top_level)
- return
-
- local_var_names = None
- if len(self.local_arg_stack) > 0:
- local_var_names = self.local_arg_stack[-1]
-
- def _lhsFromAttr(v, current_klass):
- attr_name = v.attrname
- if isinstance(v.expr, ast.Name):
- obj = v.expr.name
- lhs = self._name(v.expr, current_klass) + "." + attr_name
- elif isinstance(v.expr, ast.Getattr):
- lhs = self._getattr(v, current_klass)
- elif isinstance(v.expr, ast.Subscript):
- lhs = self._subscript(v.expr, current_klass) + "." + attr_name
- else:
- raise TranslationError("unsupported type (in _assign)", v.expr)
- return lhs
-
- def _lhsFromName(v, top_level, current_klass):
- if top_level:
- if current_klass:
- lhs = UU+current_klass.name_ + ".prototype.__class__." \
- + v.name
- else:
- self.top_level_vars.add(v.name)
- vname = self.modpfx() + v.name
- if not self.modpfx() and v.name not in\
- self.method_imported_globals:
- lhs = "var " + vname
- else:
- lhs = UU + vname
- self.add_local_arg(v.name)
- else:
- if v.name in local_var_names:
- lhs = v.name
- elif v.name in self.method_imported_globals:
- lhs = self.modpfx() + v.name
- else:
- lhs = "var " + v.name
- self.add_local_arg(v.name)
- return lhs
-
- dbg = 0
- v = node.nodes[0]
- if isinstance(v, ast.AssAttr):
- lhs = _lhsFromAttr(v, current_klass)
- if v.flags == "OP_ASSIGN":
- op = "="
- else:
- raise TranslationError("unsupported flag (in _assign)", v)
-
- elif isinstance(v, ast.AssName):
- lhs = _lhsFromName(v, top_level, current_klass)
- if v.flags == "OP_ASSIGN":
- op = "="
- else:
- raise TranslationError("unsupported flag (in _assign)", v)
- elif isinstance(v, ast.Subscript):
- if v.flags == "OP_ASSIGN":
- obj = self.expr(v.expr, current_klass)
- if len(v.subs) != 1:
- raise TranslationError("must have one sub (in _assign)", v)
- idx = self.expr(v.subs[0], current_klass)
- value = self.expr(node.expr, current_klass)
- print >>self.output, " " + obj + ".__setitem__(" + idx + ", " + value + ");"
- return
- else:
- raise TranslationError("unsupported flag (in _assign)", v)
- elif isinstance(v, (ast.AssList, ast.AssTuple)):
- uniqueID = self.nextTupleAssignID
- self.nextTupleAssignID += 1
- tempName = "__tupleassign" + str(uniqueID) + "__"
- print >>self.output, " var " + tempName + " = " + \
- self.expr(node.expr, current_klass) + ";"
- for index,child in enumerate(v.getChildNodes()):
- rhs = tempName + ".__getitem__(" + str(index) + ")"
-
- if isinstance(child, ast.AssAttr):
- lhs = _lhsFromAttr(child, current_klass)
- elif isinstance(child, ast.AssName):
- lhs = _lhsFromName(child, top_level, current_klass)
- elif isinstance(child, ast.Subscript):
- if child.flags == "OP_ASSIGN":
- obj = self.expr(child.expr, current_klass)
- if len(child.subs) != 1:
- raise TranslationError("must have one sub " +
- "(in _assign)", child)
- idx = self.expr(child.subs[0], current_klass)
- value = self.expr(node.expr, current_klass)
- print >>self.output, " " + obj + ".__setitem__(" \
- + idx + ", " + rhs + ");"
- continue
- print >>self.output, " " + lhs + " = " + rhs + ";"
- return
- else:
- raise TranslationError("unsupported type (in _assign)", v)
-
- rhs = self.expr(node.expr, current_klass)
- if dbg:
- print "b", repr(node.expr), rhs
- print >>self.output, " " + lhs + " " + op + " " + rhs + ";"
-
-
- def _discard(self, node, current_klass):
-
- if isinstance(node.expr, ast.CallFunc):
- debugStmt = self.debug and not self._isNativeFunc(node)
- if debugStmt and isinstance(node.expr.node, ast.Name) and \
- node.expr.node.name == 'import_wait':
- debugStmt = False
- if debugStmt:
- st = self.get_line_trace(node)
- print >>self.output, "sys.addstack('%s');\n" % st
- if isinstance(node.expr.node, ast.Name) and node.expr.node.name == NATIVE_JS_FUNC_NAME:
- if len(node.expr.args) != 1:
- raise TranslationError("native javascript function %s must have one arg" % NATIVE_JS_FUNC_NAME, node.expr)
- if not isinstance(node.expr.args[0], ast.Const):
- raise TranslationError("native javascript function %s must have constant arg" % NATIVE_JS_FUNC_NAME, node.expr)
- raw_js = node.expr.args[0].value
- print >>self.output, raw_js
- else:
- expr = self._callfunc(node.expr, current_klass)
- print >>self.output, " " + expr + ";"
-
- if debugStmt:
- print >>self.output, "sys.popstack();\n"
-
- elif isinstance(node.expr, ast.Const):
- if node.expr.value is not None: # Empty statements generate ignore None
- print >>self.output, self._const(node.expr)
- else:
- raise TranslationError("unsupported type (in _discard)", node.expr)
-
-
- def _if(self, node, current_klass):
- for i in range(len(node.tests)):
- test, consequence = node.tests[i]
- if i == 0:
- keyword = "if"
- else:
- keyword = "else if"
-
- self._if_test(keyword, test, consequence, current_klass)
-
- if node.else_:
- keyword = "else"
- test = None
- consequence = node.else_
-
- self._if_test(keyword, test, consequence, current_klass)
-
-
- def _if_test(self, keyword, test, consequence, current_klass):
- if test:
- expr = self.expr(test, current_klass)
-
- print >>self.output, " " + keyword + " (pyjslib.bool(" + expr + ")) {"
- else:
- print >>self.output, " " + keyword + " {"
-
- if isinstance(consequence, ast.Stmt):
- for child in consequence.nodes:
- self._stmt(child, current_klass)
- else:
- raise TranslationError("unsupported type (in _if_test)", consequence)
-
- print >>self.output, " }"
-
-
- def _from(self, node):
- for name in node.names:
- # look up "hack" in AppTranslator as to how findFile gets here
- module_name = node.modname + "." + name[0]
- try:
- ff = self.findFile(module_name + ".py")
- except Exception:
- ff = None
- if ff:
- self.add_imported_module(module_name)
- else:
- self.imported_classes[name[0]] = node.modname
-
-
- def _compare(self, node, current_klass):
- lhs = self.expr(node.expr, current_klass)
-
- if len(node.ops) != 1:
- raise TranslationError("only one ops supported (in _compare)", node)
-
- op = node.ops[0][0]
- rhs_node = node.ops[0][1]
- rhs = self.expr(rhs_node, current_klass)
-
- if op == "==":
- return "pyjslib.eq(%s, %s)" % (lhs, rhs)
- if op == "in":
- return rhs + ".__contains__(" + lhs + ")"
- elif op == "not in":
- return "!" + rhs + ".__contains__(" + lhs + ")"
- elif op == "is":
- op = "==="
- elif op == "is not":
- op = "!=="
-
- return "(" + lhs + " " + op + " " + rhs + ")"
-
-
- def _not(self, node, current_klass):
- expr = self.expr(node.expr, current_klass)
-
- return "!(" + expr + ")"
-
- def _or(self, node, current_klass):
- expr = "("+(") || (".join([self.expr(child, current_klass) for child in node.nodes]))+')'
- return expr
-
- def _and(self, node, current_klass):
- expr = "("+(") && (".join([self.expr(child, current_klass) for child in node.nodes]))+")"
- return expr
-
- def _for(self, node, current_klass):
- assign_name = ""
- assign_tuple = ""
-
- # based on Bob Ippolito's Iteration in Javascript code
- if isinstance(node.assign, ast.AssName):
- assign_name = node.assign.name
- self.add_local_arg(assign_name)
- if node.assign.flags == "OP_ASSIGN":
- op = "="
- elif isinstance(node.assign, ast.AssTuple):
- op = "="
- i = 0
- for child in node.assign:
- child_name = child.name
- if assign_name == "":
- assign_name = "temp_" + child_name
- self.add_local_arg(child_name)
- assign_tuple += """
- var %(child_name)s %(op)s %(assign_name)s.__getitem__(%(i)i);
- """ % locals()
- i += 1
- else:
- raise TranslationError("unsupported type (in _for)", node.assign)
-
- if isinstance(node.list, ast.Name):
- list_expr = self._name(node.list, current_klass)
- elif isinstance(node.list, ast.Getattr):
- list_expr = self._getattr(node.list, current_klass)
- elif isinstance(node.list, ast.CallFunc):
- list_expr = self._callfunc(node.list, current_klass)
- else:
- raise TranslationError("unsupported type (in _for)", node.list)
-
- lhs = "var " + assign_name
- iterator_name = "__" + assign_name
-
- print >>self.output, """
- var %(iterator_name)s = %(list_expr)s.__iter__();
- try {
- while (true) {
- %(lhs)s %(op)s %(iterator_name)s.next();
- %(assign_tuple)s
- """ % locals()
- for node in node.body.nodes:
- self._stmt(node, current_klass)
- print >>self.output, """
- }
- } catch (e) {
- if (e.__name__ != pyjslib.StopIteration.__name__) {
- throw e;
- }
- }
- """ % locals()
-
-
- def _while(self, node, current_klass):
- test = self.expr(node.test, current_klass)
- print >>self.output, " while (pyjslib.bool(" + test + ")) {"
- if isinstance(node.body, ast.Stmt):
- for child in node.body.nodes:
- self._stmt(child, current_klass)
- else:
- raise TranslationError("unsupported type (in _while)", node.body)
- print >>self.output, " }"
-
-
- def _const(self, node):
- if isinstance(node.value, int):
- return str(node.value)
- elif isinstance(node.value, float):
- return str(node.value)
- elif isinstance(node.value, basestring):
- v = node.value
- if isinstance(node.value, unicode):
- v = v.encode('utf-8')
- return "String('%s')" % escapejs(v)
- elif node.value is None:
- return "null"
- else:
- raise TranslationError("unsupported type (in _const)", node)
-
- def _unaryadd(self, node, current_klass):
- return self.expr(node.expr, current_klass)
-
- def _unarysub(self, node, current_klass):
- return "-" + self.expr(node.expr, current_klass)
-
- def _add(self, node, current_klass):
- return self.expr(node.left, current_klass) + " + " + self.expr(node.right, current_klass)
-
- def _sub(self, node, current_klass):
- return self.expr(node.left, current_klass) + " - " + self.expr(node.right, current_klass)
-
- def _div(self, node, current_klass):
- return self.expr(node.left, current_klass) + " / " + self.expr(node.right, current_klass)
-
- def _mul(self, node, current_klass):
- return self.expr(node.left, current_klass) + " * " + self.expr(node.right, current_klass)
-
- def _mod(self, node, current_klass):
- if isinstance(node.left, ast.Const) and isinstance(node.left.value, StringType):
- self.imported_js.add("sprintf.js") # Include the sprintf functionality if it is used
- return "sprintf("+self.expr(node.left, current_klass) + ", " + self.expr(node.right, current_klass)+")"
- return self.expr(node.left, current_klass) + " % " + self.expr(node.right, current_klass)
-
- def _invert(self, node, current_klass):
- return "~" + self.expr(node.expr, current_klass)
-
- def _bitand(self, node, current_klass):
- return " & ".join([self.expr(child, current_klass) for child in node.nodes])
-
- def _bitshiftleft(self, node, current_klass):
- return self.expr(node.left, current_klass) + " << " + self.expr(node.right, current_klass)
-
- def _bitshiftright(self, node, current_klass):
- return self.expr(node.left, current_klass) + " >>> " + self.expr(node.right, current_klass)
-
- def _bitxor(self,node, current_klass):
- return " ^ ".join([self.expr(child, current_klass) for child in node.nodes])
-
- def _bitor(self, node, current_klass):
- return " | ".join([self.expr(child, current_klass) for child in node.nodes])
-
- def _subscript(self, node, current_klass):
- if node.flags == "OP_APPLY":
- if len(node.subs) == 1:
- return self.expr(node.expr, current_klass) + ".__getitem__(" + self.expr(node.subs[0], current_klass) + ")"
- else:
- raise TranslationError("must have one sub (in _subscript)", node)
- else:
- raise TranslationError("unsupported flag (in _subscript)", node)
-
- def _subscript_stmt(self, node, current_klass):
- if node.flags == "OP_DELETE":
- print >>self.output, " " + self.expr(node.expr, current_klass) + ".__delitem__(" + self.expr(node.subs[0], current_klass) + ");"
- else:
- raise TranslationError("unsupported flag (in _subscript)", node)
-
- def _list(self, node, current_klass):
- return "new pyjslib.List([" + ", ".join([self.expr(x, current_klass) for x in node.nodes]) + "])"
-
- def _dict(self, node, current_klass):
- items = []
- for x in node.items:
- key = self.expr(x[0], current_klass)
- value = self.expr(x[1], current_klass)
- items.append("[" + key + ", " + value + "]")
- return "new pyjslib.Dict([" + ", ".join(items) + "])"
-
- def _tuple(self, node, current_klass):
- return "new pyjslib.Tuple([" + ", ".join([self.expr(x, current_klass) for x in node.nodes]) + "])"
-
- def _lambda(self, node, current_klass):
- if node.varargs:
- raise TranslationError("varargs are not supported in Lambdas", node)
- if node.kwargs:
- raise TranslationError("kwargs are not supported in Lambdas", node)
- res = cStringIO.StringIO()
- arg_names = list(node.argnames)
- function_args = ", ".join(arg_names)
- for child in node.getChildNodes():
- expr = self.expr(child, None)
- print >> res, "function (%s){" % function_args
- self._default_args_handler(node, arg_names, None,
- output=res)
- print >> res, 'return %s;}' % expr
- return res.getvalue()
-
- def _slice(self, node, current_klass):
- if node.flags == "OP_APPLY":
- lower = "null"
- upper = "null"
- if node.lower != None:
- lower = self.expr(node.lower, current_klass)
- if node.upper != None:
- upper = self.expr(node.upper, current_klass)
- return "pyjslib.slice(" + self.expr(node.expr, current_klass) + ", " + lower + ", " + upper + ")"
- else:
- raise TranslationError("unsupported flag (in _slice)", node)
-
- def _global(self, node, current_klass):
- for name in node.names:
- self.method_imported_globals.add(name)
-
- def expr(self, node, current_klass):
- if isinstance(node, ast.Const):
- return self._const(node)
- # @@@ not sure if the parentheses should be here or in individual operator functions - JKT
- elif isinstance(node, ast.Mul):
- return " ( " + self._mul(node, current_klass) + " ) "
- elif isinstance(node, ast.Add):
- return " ( " + self._add(node, current_klass) + " ) "
- elif isinstance(node, ast.Sub):
- return " ( " + self._sub(node, current_klass) + " ) "
- elif isinstance(node, ast.Div):
- return " ( " + self._div(node, current_klass) + " ) "
- elif isinstance(node, ast.Mod):
- return self._mod(node, current_klass)
- elif isinstance(node, ast.UnaryAdd):
- return self._unaryadd(node, current_klass)
- elif isinstance(node, ast.UnarySub):
- return self._unarysub(node, current_klass)
- elif isinstance(node, ast.Not):
- return self._not(node, current_klass)
- elif isinstance(node, ast.Or):
- return self._or(node, current_klass)
- elif isinstance(node, ast.And):
- return self._and(node, current_klass)
- elif isinstance(node, ast.Invert):
- return self._invert(node, current_klass)
- elif isinstance(node, ast.Bitand):
- return "("+self._bitand(node, current_klass)+")"
- elif isinstance(node,ast.LeftShift):
- return self._bitshiftleft(node, current_klass)
- elif isinstance(node, ast.RightShift):
- return self._bitshiftright(node, current_klass)
- elif isinstance(node, ast.Bitxor):
- return "("+self._bitxor(node, current_klass)+")"
- elif isinstance(node, ast.Bitor):
- return "("+self._bitor(node, current_klass)+")"
- elif isinstance(node, ast.Compare):
- return self._compare(node, current_klass)
- elif isinstance(node, ast.CallFunc):
- return self._callfunc(node, current_klass)
- elif isinstance(node, ast.Name):
- return self._name(node, current_klass)
- elif isinstance(node, ast.Subscript):
- return self._subscript(node, current_klass)
- elif isinstance(node, ast.Getattr):
- return self._getattr(node, current_klass)
- elif isinstance(node, ast.List):
- return self._list(node, current_klass)
- elif isinstance(node, ast.Dict):
- return self._dict(node, current_klass)
- elif isinstance(node, ast.Tuple):
- return self._tuple(node, current_klass)
- elif isinstance(node, ast.Slice):
- return self._slice(node, current_klass)
- elif isinstance(node, ast.Lambda):
- return self._lambda(node, current_klass)
- else:
- raise TranslationError("unsupported type (in expr)", node)
-
-
-
-import cStringIO
-
-def translate(file_name, module_name, debug=False):
- f = file(file_name, "r")
- src = f.read()
- f.close()
- output = cStringIO.StringIO()
- mod = compiler.parseFile(file_name)
- t = Translator(module_name, module_name, module_name, src, debug, mod, output)
- return output.getvalue()
-
-
-class PlatformParser:
- def __init__(self, platform_dir = "", verbose=True):
- self.platform_dir = platform_dir
- self.parse_cache = {}
- self.platform = ""
- self.verbose = verbose
-
- def setPlatform(self, platform):
- self.platform = platform
-
- def parseModule(self, module_name, file_name):
-
- importing = False
- if not self.parse_cache.has_key(file_name):
- importing = True
- mod = compiler.parseFile(file_name)
- self.parse_cache[file_name] = mod
- else:
- mod = self.parse_cache[file_name]
-
- override = False
- platform_file_name = self.generatePlatformFilename(file_name)
- if self.platform and os.path.isfile(platform_file_name):
- mod = copy.deepcopy(mod)
- mod_override = compiler.parseFile(platform_file_name)
- self.merge(mod, mod_override)
- override = True
-
- if self.verbose:
- if override:
- print "Importing %s (Platform %s)" % (module_name, self.platform)
- elif importing:
- print "Importing %s" % (module_name)
-
- return mod, override
-
- def generatePlatformFilename(self, file_name):
- (module_name, extension) = os.path.splitext(os.path.basename(file_name))
- platform_file_name = module_name + self.platform + extension
-
- return os.path.join(os.path.dirname(file_name), self.platform_dir, platform_file_name)
-
- def merge(self, tree1, tree2):
- for child in tree2.node:
- if isinstance(child, ast.Function):
- self.replaceFunction(tree1, child.name, child)
- elif isinstance(child, ast.Class):
- self.replaceClassMethods(tree1, child.name, child)
-
- return tree1
-
- def replaceFunction(self, tree, function_name, function_node):
- # find function to replace
- for child in tree.node:
- if isinstance(child, ast.Function) and child.name == function_name:
- self.copyFunction(child, function_node)
- return
- raise TranslationError("function not found: " + function_name, function_node)
-
- def replaceClassMethods(self, tree, class_name, class_node):
- # find class to replace
- old_class_node = None
- for child in tree.node:
- if isinstance(child, ast.Class) and child.name == class_name:
- old_class_node = child
- break
-
- if not old_class_node:
- raise TranslationError("class not found: " + class_name, class_node)
-
- # replace methods
- for function_node in class_node.code:
- if isinstance(function_node, ast.Function):
- found = False
- for child in old_class_node.code:
- if isinstance(child, ast.Function) and child.name == function_node.name:
- found = True
- self.copyFunction(child, function_node)
- break
-
- if not found:
- raise TranslationError("class method not found: " + class_name + "." + function_node.name, function_node)
-
- def copyFunction(self, target, source):
- target.code = source.code
- target.argnames = source.argnames
- target.defaults = source.defaults
- target.doc = source.doc # @@@ not sure we need to do this any more
-
-def dotreplace(fname):
- path, ext = os.path.splitext(fname)
- return path.replace(".", "/") + ext
-
-class AppTranslator:
-
- def __init__(self, library_dirs=[], parser=None, dynamic=False,
- optimize=False, verbose=True):
- self.extension = ".py"
- self.optimize = optimize
- self.library_modules = []
- self.overrides = {}
- self.library_dirs = path + library_dirs
- self.dynamic = dynamic
- self.verbose = verbose
-
- if not parser:
- self.parser = PlatformParser()
- else:
- self.parser = parser
-
- self.parser.dynamic = dynamic
-
- def findFile(self, file_name):
- if os.path.isfile(file_name):
- return file_name
-
- for library_dir in self.library_dirs:
- file_name = dotreplace(file_name)
- full_file_name = os.path.join(
- os.path.abspath(os.path.dirname(__file__)), library_dir, file_name)
- if os.path.isfile(full_file_name):
- return full_file_name
-
- fnameinit, ext = os.path.splitext(file_name)
- fnameinit = fnameinit + "/__init__.py"
-
- full_file_name = os.path.join(
- os.path.abspath(os.path.dirname(__file__)), library_dir, fnameinit)
- if os.path.isfile(full_file_name):
- return full_file_name
-
- raise Exception("file not found: " + file_name)
-
- def _translate(self, module_name, is_app=True, debug=False,
- imported_js=set()):
- if module_name not in self.library_modules:
- self.library_modules.append(module_name)
-
- file_name = self.findFile(module_name + self.extension)
-
- output = cStringIO.StringIO()
-
- f = file(file_name, "r")
- src = f.read()
- f.close()
-
- mod, override = self.parser.parseModule(module_name, file_name)
- if override:
- override_name = "%s.%s" % (self.parser.platform.lower(),
- module_name)
- self.overrides[override_name] = override_name
- if is_app:
- mn = '__main__'
- else:
- mn = module_name
- t = Translator(mn, module_name, module_name,
- src, debug, mod, output, self.dynamic, self.optimize,
- self.findFile)
-
- module_str = output.getvalue()
- imported_js.update(set(t.imported_js))
- imported_modules_str = ""
- for module in t.imported_modules:
- if module not in self.library_modules:
- self.library_modules.append(module)
- #imported_js.update(set(t.imported_js))
- #imported_modules_str += self._translate(
- # module, False, debug=debug, imported_js=imported_js)
-
- return imported_modules_str + module_str
-
-
- def translate(self, module_name, is_app=True, debug=False,
- library_modules=[]):
- app_code = cStringIO.StringIO()
- lib_code = cStringIO.StringIO()
- imported_js = set()
- self.library_modules = []
- self.overrides = {}
- for library in library_modules:
- if library.endswith(".js"):
- imported_js.add(library)
- continue
- self.library_modules.append(library)
- if self.verbose:
- print 'Including LIB', library
- print >> lib_code, '\n//\n// BEGIN LIB '+library+'\n//\n'
- print >> lib_code, self._translate(
- library, False, debug=debug, imported_js=imported_js)
-
- print >> lib_code, "/* initialize static library */"
- print >> lib_code, "%s%s();\n" % (UU, library)
-
- print >> lib_code, '\n//\n// END LIB '+library+'\n//\n'
- if module_name:
- print >> app_code, self._translate(
- module_name, is_app, debug=debug, imported_js=imported_js)
- for js in imported_js:
- path = self.findFile(js)
- if os.path.isfile(path):
- if self.verbose:
- print 'Including JS', js
- print >> lib_code, '\n//\n// BEGIN JS '+js+'\n//\n'
- print >> lib_code, file(path).read()
- print >> lib_code, '\n//\n// END JS '+js+'\n//\n'
- else:
- print >>sys.stderr, 'Warning: Unable to find imported javascript:', js
- return lib_code.getvalue(), app_code.getvalue()
-
-usage = """
- usage: %s file_name [module_name]
-"""
-
-def main():
- import sys
- if len(sys.argv)<2:
- print >> sys.stderr, usage % sys.argv[0]
- sys.exit(1)
- file_name = os.path.abspath(sys.argv[1])
- if not os.path.isfile(file_name):
- print >> sys.stderr, "File not found %s" % file_name
- sys.exit(1)
- if len(sys.argv) > 2:
- module_name = sys.argv[2]
- else:
- module_name = None
- print translate(file_name, module_name),
-
-if __name__ == "__main__":
- main()
-
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/svgui/svgui.py
--- a/plugins/python/modules/svgui/svgui.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-import wx
-import os, sys, shutil
-
-from plugger import opjimg
-from plugins.python import PythonCodeTemplate
-
-from pyjs import translate
-
-from docutils import *
-
-class RootClass:
-
- PluginMethods = [
- {"bitmap" : os.path.join("images","ImportSVG"),
- "name" : _("Import SVG"),
- "tooltip" : _("Import SVG"),
- "method" : "_ImportSVG"},
- {"bitmap" : os.path.join("images","ImportSVG"),
- "name" : _("Inkscape"),
- "tooltip" : _("Create HMI"),
- "method" : "_StartInkscape"},
- ]
-
- def PluginPath(self):
- return os.path.join(self.PlugParent.PluginPath(), "modules", self.PlugType)
-
- def _getSVGpath(self):
- # define name for IEC raw code file
- return os.path.join(self.PlugPath(), "gui.svg")
-
- def _getSVGUIserverpath(self):
- return os.path.join(os.path.dirname(__file__), "svgui_server.py")
-
- def PlugGenerate_C(self, buildpath, locations):
- """
- Return C code generated by iec2c compiler
- when _generate_softPLC have been called
- @param locations: ignored
- @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
- """
-
- current_location = self.GetCurrentLocation()
- # define a unique name for the generated C file
- location_str = "_".join(map(lambda x:str(x), current_location))
-
- res = ([], "", False)
-
- svgfile=self._getSVGpath()
- if os.path.exists(svgfile):
- res += (("gui.svg", file(svgfile,"rb")),)
-
- svguiserverfile = open(self._getSVGUIserverpath(), 'r')
- svguiservercode = svguiserverfile.read()
- svguiserverfile.close()
-
- svguilibpath = os.path.join(self._getBuildPath(), "svguilib.js")
- svguilibfile = open(svguilibpath, 'w')
- svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "sys.py"), "sys"))
- svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "_pyjs.js"), 'r').read())
- svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "pyjslib.py"), "pyjslib"))
- svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "svguilib.py"), "svguilib"))
- svguilibfile.write("pyjslib();\nsvguilib();\n")
- svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "json.js"), 'r').read())
- svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "livesvg.js"), 'r').read())
- svguilibfile.close()
- jsmodules = {"LiveSVGPage": "svguilib.js"}
- res += (("svguilib.js", file(svguilibpath,"rb")),)
-
- runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
- runtimefile = open(runtimefile_path, 'w')
- runtimefile.write(svguiservercode % {"svgfile" : "gui.svg"})
- runtimefile.write("""
-def _runtime_%(location)s_begin():
- website.LoadHMI(%(svgui_class)s, %(jsmodules)s)
-
-def _runtime_%(location)s_cleanup():
- website.UnLoadHMI()
-
-""" % {"location": location_str,
- "svgui_class": "SVGUI_HMI",
- "jsmodules" : str(jsmodules),
- })
- runtimefile.close()
-
- res += (("runtime_%s.py"%location_str, file(runtimefile_path,"rb")),)
-
- return res
-
- def _ImportSVG(self):
- dialog = wx.FileDialog(self.GetPlugRoot().AppFrame, _("Choose a SVG file"), os.getcwd(), "", _("SVG files (*.svg)|*.svg|All files|*.*"), wx.OPEN)
- if dialog.ShowModal() == wx.ID_OK:
- svgpath = dialog.GetPath()
- if os.path.isfile(svgpath):
- shutil.copy(svgpath, self._getSVGpath())
- else:
- self.GetPlugRoot().logger.write_error(_("No such SVG file: %s\n")%svgpath)
- dialog.Destroy()
-
- def _StartInkscape(self):
- svgfile = self._getSVGpath()
- open_inkscape = True
- if not self.GetPlugRoot().CheckProjectPathPerm():
- dialog = wx.MessageDialog(self.GetPlugRoot().AppFrame,
- _("You don't have write permissions.\nOpen Inkscape anyway ?"),
- _("Open Inkscape"),
- wx.YES_NO|wx.ICON_QUESTION)
- open_inkscape = dialog.ShowModal() == wx.ID_YES
- dialog.Destroy()
- if open_inkscape:
- if not os.path.isfile(svgfile):
- svgfile = None
- open_svg(svgfile)
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/svgui/svgui_server.py
--- a/plugins/python/modules/svgui/svgui_server.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-import os
-
-from nevow import rend, appserver, inevow, tags, loaders, athena
-import simplejson as json
-
-svgfile = '%(svgfile)s'
-
-svguiWidgets = {}
-
-currentId = 0
-def getNewId():
- global currentId
- currentId += 1
- return currentId
-
-class SvguiWidget:
-
- def __init__(self, classname, id, **kwargs):
- self.classname = classname
- self.id = id
- self.attrs = kwargs.copy()
- self.inputs = {}
- self.outputs = {}
- self.inhibit = False
- self.changed = False
-
- def setinput(self, attrname, value):
- self.inputs[attrname] = value
-
- def getinput(self, attrname, default=None):
- if not self.inputs.has_key(attrname):
- self.inputs[attrname] = default
- return self.inputs[attrname]
-
- def setoutput(self, attrname, value):
- if self.outputs.get(attrname) != value:
- self.outputs[attrname] = value
- self.changed = True
- self.RefreshInterface()
-
- def updateoutputs(self, **kwargs):
- for attrname, value in kwargs.iteritems():
- if self.outputs.get(attrname) != value:
- self.outputs[attrname] = value
- self.changed = True
- self.RefreshInterface()
-
- def RefreshInterface(self):
- interface = website.getHMI()
- if isinstance(interface, SVGUI_HMI) and self.changed and not self.inhibit:
- self.changed = False
- d = interface.sendData(self)
- if d is not None:
- self.inhibit = True
- d.addCallback(self.InterfaceRefreshed)
-
- def InterfaceRefreshed(self, result):
- self.inhibit = False
- if self.changed:
- self.RefreshInterface()
-
-def get_object_init_state(obj):
- # Convert objects to a dictionary of their representation
- attrs = obj.attrs.copy()
- attrs.update(obj.inputs)
- d = { '__class__': obj.classname,
- 'id': obj.id,
- 'kwargs': json.dumps(attrs),
- }
- return d
-
-def get_object_current_state(obj):
- # Convert objects to a dictionary of their representation
- d = { '__class__': obj.classname,
- 'id': obj.id,
- 'kwargs': json.dumps(obj.outputs),
- }
- return d
-
-class SVGUI_HMI(website.PLCHMI):
- jsClass = u"LiveSVGPage.LiveSVGWidget"
-
- docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[
- tags.xml(loaders.xmlfile(os.path.join(WorkingDir, svgfile))),
- ])
-
- def HMIinitialisation(self):
- gadgets = []
- for gadget in svguiWidgets.values():
- gadgets.append(unicode(json.dumps(gadget, default=get_object_init_state, indent=2), 'ascii'))
- d = self.callRemote('init', gadgets)
- d.addCallback(self.HMIinitialised)
-
- def sendData(self,data):
- if self.initialised:
- return self.callRemote('receiveData',unicode(json.dumps(data, default=get_object_current_state, indent=2), 'ascii'))
- return None
-
- def setattr(self, id, attrname, value):
- svguiWidgets[id].setinput(attrname, value)
-
-def createSVGUIControl(*args, **kwargs):
- id = getNewId()
- gad = SvguiWidget(args[0], id, **kwargs)
- svguiWidgets[id] = gad
- gadget = [unicode(json.dumps(gad, default=get_object_init_state, indent=2), 'ascii')]
- interface = website.getHMI()
- if isinstance(interface, SVGUI_HMI) and interface.initialised:
- interface.callRemote('init', gadget)
- return id
-
-def setAttr(id, attrname, value):
- gad = svguiWidgets.get(id, None)
- if gad is not None:
- gad.setoutput(attrname, value)
-
-def updateAttr(id, **kwargs):
- gad = svguiWidgets.get(id, None)
- if gad is not None:
- gad.updateoutput(**kwargs)
-
-def getAttr(id, attrname, default=None):
- gad = svguiWidgets.get(id, None)
- if gad is not None:
- return gad.getinput(attrname, default)
- return default
-
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/svgui/svguilib.py
--- a/plugins/python/modules/svgui/svguilib.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-
-class button:
-
- def __init__(self, parent, id, args):
- self.parent = parent
- self.id = id
- self.back_elt = getSVGElementById(args.back_id)
- self.sele_elt = getSVGElementById(args.sele_id)
- self.toggle = args.toggle
- self.active = args.active
- if args.state != undefined:
- self.state = args.state
- else:
- self.state = False
- self.dragging = False
- if self.toggle:
- self.up = not self.state
- else:
- self.up = True
-
- # Add event on each element of the button
- if self.active:
- self.back_elt.addEventListener("mouseup", self, False)
- self.back_elt.addEventListener("mousedown", self, False)
- self.back_elt.addEventListener("mouseover", self, False)
- self.back_elt.addEventListener("mouseout", self, False)
-
- self.sele_elt.addEventListener("mouseup", self, False)
- self.sele_elt.addEventListener("mousedown", self, False)
- self.sele_elt.addEventListener("mouseover", self, False)
- self.sele_elt.addEventListener("mouseout", self, False)
-
- blockSVGElementDrag(self.back_elt)
- blockSVGElementDrag(self.sele_elt)
-
- self.updateElements()
-
- # method to display the current state of interface
- def updateElements(self):
- if self.up:
- self.sele_elt.setAttribute("display", "none")
- self.back_elt.removeAttribute("display")
- else:
- self.sele_elt.removeAttribute("display")
- self.back_elt.setAttribute("display", "none")
-
- def updateValues(self, values):
- if values.state != self.state:
- self.state = values.state
- self.up = not self.state
- updateAttr(self.id, 'state', self.state)
- self.updateElements()
-
- def handleEvent(self, evt):
- # Quand le bouton de la souris est presse
- if evt.type == "mousedown":
- evt.stopPropagation()
- setCurrentObject(self)
-
- self.dragging = True
-
- if self.toggle:
- self.up = self.state
- else:
- self.up = False
- self.state = True
- updateAttr(self.id, 'state', self.state)
- self.updateElements()
-
- if isCurrentObject(self) and self.dragging:
- # Quand le bouton est survole
- if evt.type == "mouseover" and self.toggle:
- self.up = self.state
- self.updateElements()
-
- # Quand le curseur quitte la zone du bouton
- elif evt.type == "mouseout" and self.toggle:
- self.up = not self.state
- self.updateElements()
-
- # Quand le bouton de la souris est relache
- elif evt.type == "mouseup":
- evt.stopPropagation()
- if self.toggle and self.up == self.state:
- self.state = not self.state
- updateAttr(self.id, 'state', self.state)
- elif not self.toggle:
- self.up = True
- self.state = False
- updateAttr(self.id, 'state', self.state)
- self.updateElements()
- self.dragging = False
-
-class textControl:
-
- def __init__(self, parent, id, args):
- self.parent = parent
- self.id = id
- self.back_elt = getSVGElementById(args.back_id)
- if args.text != undefined:
- self.text = args.text
- else:
- self.text = ""
- self.updateElements()
-
- def updateValues(self, values):
- if values.text != self.value:
- self.text = values.text
- updateAttr(self.id, 'text', self.text)
- self.updateElements()
-
- def updateElements(self):
- self.back_elt.firstChild.firstChild.textContent = self.text
-
- def handleEvent(self, evt):
- pass
-
\ No newline at end of file
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/wxglade_hmi/README
--- a/plugins/python/modules/wxglade_hmi/README Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-WxGlade HMI
\ No newline at end of file
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/wxglade_hmi/__init__.py
--- a/plugins/python/modules/wxglade_hmi/__init__.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-from wxglade_hmi import *
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/modules/wxglade_hmi/wxglade_hmi.py
--- a/plugins/python/modules/wxglade_hmi/wxglade_hmi.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-import wx
-import os, sys
-from xml.dom import minidom
-
-from plugger import opjimg
-from plugins.python import PythonCodeTemplate
-
-class RootClass(PythonCodeTemplate):
-
- PluginMethods = [
- {"bitmap" : opjimg("editWXGLADE"),
- "name" : _("WXGLADE GUI"),
- "tooltip" : _("Edit a WxWidgets GUI with WXGlade"),
- "method" : "_editWXGLADE"},
- ]
-
- def _getWXGLADEpath(self):
- # define name for IEC raw code file
- return os.path.join(self.PlugPath(), "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 PlugGenerate_C(self, buildpath, locations):
- """
- Return C code generated by iec2c compiler
- when _generate_softPLC have been called
- @param locations: ignored
- @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
- """
-
- current_location = self.GetCurrentLocation()
- # define a unique name for the generated C file
- location_str = "_".join(map(lambda x:str(x), current_location))
-
- runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
- runtimefile = open(runtimefile_path, 'w')
-
- 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[node._attrs["name"].value] = node._attrs["class"].value
-
- 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')
- runtimefile.write(hmipyfile.read())
- hmipyfile.close()
-
- runtimefile.write(self.GetPythonCode())
- runtimefile.write("""
-%(declare)s
-
-def _runtime_%(location)s_begin():
- global %(global)s
-
- def OnCloseFrame(evt):
- wx.MessageBox(_("Please stop PLC to close"))
-
- %(init)s
-
-def _runtime_%(location)s_cleanup():
- global %(global)s
-
- %(cleanup)s
-
-""" % {"location": location_str,
- "declare": "\n".join(map(lambda x:"%s = None" % x, hmi_frames.keys())),
- "global": ",".join(hmi_frames.keys()),
- "init": "\n".join(map(lambda x: """
- %(name)s = %(class)s(None)
- %(name)s.Bind(wx.EVT_CLOSE, OnCloseFrame)
- %(name)s.Show()
-""" % {"name": x[0], "class": x[1]},
- hmi_frames.items())),
- "cleanup": "\n ".join(map(lambda x:"%s.Destroy()" % x, hmi_frames.keys()))})
- runtimefile.close()
-
- return [], "", False, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb"))
-
- def _editWXGLADE(self):
- wxg_filename = self._getWXGLADEpath()
- open_wxglade = True
- if not self.GetPlugRoot().CheckProjectPathPerm():
- dialog = wx.MessageDialog(self.GetPlugRoot().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("""
-
-
-
- """ % {"name": hmi_name, "class": "Class_%s" % hmi_name})
- if wx.Platform == '__WXMSW__':
- wxg_filename = "\"%s\""%wxg_filename
- self.launch_wxglade([wxg_filename])
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/plc_python.c
--- a/plugins/python/plc_python.c Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,216 +0,0 @@
-/*
- * Python Asynchronous execution code
- *
- * PLC put python commands in a fifo, respecting execution order
- * with the help of C pragmas inserted in python_eval FB code
- *
- * Buffer content is read asynchronously, (from non real time part),
- * commands are executed and result stored for later use by PLC.
- *
- * In this implementation, fifo is a list of pointer to python_eval
- * function blocks structures. Some local variables have been added in
- * python_eval interface. We use those local variables as buffer and state
- * flags.
- *
- * */
-
-#include "iec_types_all.h"
-#include "POUS.h"
-#include
-
-/* The fifo (fixed size, as number of FB is fixed) */
-static PYTHON_EVAL* EvalFBs[%(python_eval_fb_count)d];
-/* Producer and consumer cursors */
-static int Current_PLC_EvalFB;
-static int Current_Python_EvalFB;
-
-/* A global IEC-Python gateway state, for use inside python_eval FBs*/
-static int PythonState;
-#define PYTHON_LOCKED_BY_PYTHON 0
-#define PYTHON_LOCKED_BY_PLC 1
-#define PYTHON_MUSTWAKEUP 2
-#define PYTHON_FINISHED 4
-
-/* Each python_eval FunctionBlock have it own state */
-#define PYTHON_FB_FREE 0
-#define PYTHON_FB_REQUESTED 1
-#define PYTHON_FB_PROCESSING 2
-#define PYTHON_FB_ANSWERED 3
-
-int WaitPythonCommands(void);
-void UnBlockPythonCommands(void);
-int TryLockPython(void);
-void UnLockPython(void);
-void LockPython(void);
-
-int __init_%(location)s()
-{
- int i;
- /* Initialize cursors */
- Current_Python_EvalFB = 0;
- Current_PLC_EvalFB = 0;
- PythonState = PYTHON_LOCKED_BY_PYTHON;
- for(i = 0; i < %(python_eval_fb_count)d; i++)
- EvalFBs[i] = NULL;
- return 0;
-}
-
-void __cleanup_%(location)s()
-{
- PythonState = PYTHON_FINISHED;
- UnBlockPythonCommands();
-}
-
-void __retrieve_%(location)s()
-{
- /* Check Python thread is not being
- * modifying internal python_eval data */
- PythonState = TryLockPython() ?
- PYTHON_LOCKED_BY_PLC :
- PYTHON_LOCKED_BY_PYTHON;
- /* If python thread _is_ in, then PythonState remains PYTHON_LOCKED_BY_PYTHON
- * and python_eval will no do anything */
-}
-
-void __publish_%(location)s()
-{
- if(PythonState & PYTHON_LOCKED_BY_PLC){
- /* If runnig PLC did push something in the fifo*/
- if(PythonState & PYTHON_MUSTWAKEUP){
- /* WakeUp python thread */
- UnBlockPythonCommands();
- }
- UnLockPython();
- }
-}
-/**
- * Called by the PLC, each time a python_eval
- * FB instance is executed
- */
-void __PythonEvalFB(int poll, PYTHON_EVAL* data__)
-{
- /* detect rising edge on TRIG to trigger evaluation */
- if(((__GET_VAR(data__->TRIG) && !__GET_VAR(data__->TRIGM1)) ||
- /* polling is equivalent to trig on value rather than on rising edge*/
- (poll && __GET_VAR(data__->TRIG) )) &&
- /* trig only if not already trigged */
- __GET_VAR(data__->TRIGGED) == 0){
- /* mark as trigged */
- __SET_VAR(data__->, TRIGGED, 1);
- /* make a safe copy of the code */
- __SET_VAR(data__->, PREBUFFER, __GET_VAR(data__->CODE));
- }
- /* retain value for next rising edge detection */
- __SET_VAR(data__->, TRIGM1, __GET_VAR(data__->TRIG));
-
- /* python thread is not in ? */
- if( PythonState & PYTHON_LOCKED_BY_PLC){
- /* if some answer are waiting, publish*/
- if(__GET_VAR(data__->STATE) == PYTHON_FB_ANSWERED){
- /* Copy buffer content into result*/
- __SET_VAR(data__->, RESULT, __GET_VAR(data__->BUFFER));
- /* signal result presece to PLC*/
- __SET_VAR(data__->, ACK, 1);
- /* Mark as free */
- __SET_VAR(data__->, STATE, PYTHON_FB_FREE);
- /* mark as not trigged */
- if(!poll)
- __SET_VAR(data__->, TRIGGED, 0);
- /*printf("__PythonEvalFB pop %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/
- }else if(poll){
- /* when in polling, no answer == ack down */
- __SET_VAR(data__->, ACK, 0);
- }
- /* got the order to act ?*/
- if(__GET_VAR(data__->TRIGGED) == 1 &&
- /* and not already being processed */
- __GET_VAR(data__->STATE) == PYTHON_FB_FREE)
- {
- /* Enter the block in the fifo
- * Don't have to check if fifo cell is free
- * as fifo size == FB count, and a FB cannot
- * be requested twice */
- EvalFBs[Current_PLC_EvalFB] = data__;
- /* copy into BUFFER local*/
- __SET_VAR(data__->, BUFFER, __GET_VAR(data__->PREBUFFER));
- /* Set ACK pin to low so that we can set a rising edge on result */
- if(!poll){
- /* when not polling, a new answer imply reseting ack*/
- __SET_VAR(data__->, ACK, 0);
- }else{
- /* when in polling, acting reset trigger */
- __SET_VAR(data__->, TRIGGED, 0);
- }
- /* Mark FB busy */
- __SET_VAR(data__->, STATE, PYTHON_FB_REQUESTED);
- /* Have to wakeup python thread in case he was asleep */
- PythonState |= PYTHON_MUSTWAKEUP;
- /*printf("__PythonEvalFB push %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/
- /* Get a new line */
- Current_PLC_EvalFB = (Current_PLC_EvalFB + 1) %% %(python_eval_fb_count)d;
- }
- }
-}
-
-char* PythonIterator(char* result)
-{
- char* next_command;
- PYTHON_EVAL* data__;
- //printf("PythonIterator result %%s\n", result);
- /*emergency exit*/
- if(PythonState & PYTHON_FINISHED) return NULL;
- /* take python mutex to prevent changing PLC data while PLC running */
- LockPython();
- /* Get current FB */
- data__ = EvalFBs[Current_Python_EvalFB];
- if(data__ && /* may be null at first run */
- __GET_VAR(data__->STATE) == PYTHON_FB_PROCESSING){ /* some answer awaited*/
- /* If result not None */
- if(result){
- /* Get results len */
- __SET_VAR(data__->, BUFFER, strlen(result), .len);
- /* prevent results overrun */
- if(__GET_VAR(data__->BUFFER, .len) > STR_MAX_LEN)
- {
- __SET_VAR(data__->, BUFFER, STR_MAX_LEN, .len );
- /* TODO : signal error */
- }
- /* Copy results to buffer */
- strncpy((char*)__GET_VAR(data__->BUFFER, .body), result, __GET_VAR(data__->BUFFER,.len));
- }else{
- __SET_VAR(data__->, BUFFER, 0, .len);
- }
- /* remove block from fifo*/
- EvalFBs[Current_Python_EvalFB] = NULL;
- /* Mark block as answered */
- __SET_VAR(data__->, STATE, PYTHON_FB_ANSWERED);
- /* Get a new line */
- Current_Python_EvalFB = (Current_Python_EvalFB + 1) %% %(python_eval_fb_count)d;
- //printf("PythonIterator ++ Current_Python_EvalFB %%d\n", Current_Python_EvalFB);
- }
- /* while next slot is empty */
- while(((data__ = EvalFBs[Current_Python_EvalFB]) == NULL) ||
- /* or doesn't contain command */
- __GET_VAR(data__->STATE) != PYTHON_FB_REQUESTED)
- {
- UnLockPython();
- /* wait next FB to eval */
- //printf("PythonIterator wait\n");
- if(WaitPythonCommands()) return NULL;
- /*emergency exit*/
- if(PythonState & PYTHON_FINISHED) return NULL;
- LockPython();
- }
- /* Mark block as processing */
- __SET_VAR(data__->, STATE, PYTHON_FB_PROCESSING);
- //printf("PythonIterator\n");
- /* make BUFFER a null terminated string */
- __SET_VAR(data__->, BUFFER, 0, .body[__GET_VAR(data__->BUFFER, .len)]);
- /* next command is BUFFER */
- next_command = (char*)__GET_VAR(data__->BUFFER, .body);
- /* free python mutex */
- UnLockPython();
- /* return the next command to eval */
- return next_command;
-}
-
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/pous.xml
--- a/plugins/python/pous.xml Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,457 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
-
- TRIG
-
-
-
-
-
-
- CODE
-
-
-
-
-
-
-
-
-
-
- ACK
-
-
-
-
-
-
-
-
-
-
- RESULT
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- COUNTER
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- USINT#1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- USINT#0
-
-
-
-
-
-
-
-
-
-
- COUNTER
-
-
-
-
-
-
-
-
-
-
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/python.py
--- a/plugins/python/python.py Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-import wx
-import os
-import modules
-from plugger import PlugTemplate, opjimg
-from PLCControler import UndoBuffer
-from PythonEditor import PythonEditor
-
-from xml.dom import minidom
-from xmlclass import *
-import cPickle
-
-PythonClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "python_xsd.xsd"))
-
-class PythonCodeTemplate:
-
- EditorType = PythonEditor
-
- def __init__(self):
-
- self.PluginMethods.insert(0,
- {"bitmap" : opjimg("editPYTHONcode"),
- "name" : _("Edit Python File"),
- "tooltip" : _("Edit Python File"),
- "method" : "_OpenView"},
- )
-
- filepath = self.PythonFileName()
-
- self.PythonCode = PythonClasses["Python"]()
- if os.path.isfile(filepath):
- xmlfile = open(filepath, 'r')
- tree = minidom.parse(xmlfile)
- xmlfile.close()
-
- for child in tree.childNodes:
- if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "Python":
- self.PythonCode.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"])
- self.CreatePythonBuffer(True)
- else:
- self.CreatePythonBuffer(False)
- self.OnPlugSave()
-
- def PluginPath(self):
- return os.path.join(self.PlugParent.PluginPath(), "modules", self.PlugType)
-
- def PythonFileName(self):
- return os.path.join(self.PlugPath(), "python.xml")
-
- def GetFilename(self):
- if self.PythonBuffer.IsCurrentSaved():
- return "python"
- else:
- return "~python~"
-
- def SetPythonCode(self, text):
- self.PythonCode.settext(text)
-
- def GetPythonCode(self):
- return self.PythonCode.gettext()
-
- def PlugTestModified(self):
- return self.ChangesToSave or not self.PythonIsSaved()
-
- def OnPlugSave(self):
- filepath = self.PythonFileName()
-
- text = "\n"
- extras = {"xmlns":"http://www.w3.org/2001/XMLSchema",
- "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
- "xsi:schemaLocation" : "python_xsd.xsd"}
- text += self.PythonCode.generateXMLText("Python", 0, extras)
-
- xmlfile = open(filepath,"w")
- xmlfile.write(text.encode("utf-8"))
- xmlfile.close()
-
- self.MarkPythonAsSaved()
- return True
-
-#-------------------------------------------------------------------------------
-# Current Buffering Management Functions
-#-------------------------------------------------------------------------------
-
- """
- Return a copy of the project
- """
- def Copy(self, model):
- return cPickle.loads(cPickle.dumps(model))
-
- def CreatePythonBuffer(self, saved):
- self.Buffering = False
- self.PythonBuffer = UndoBuffer(cPickle.dumps(self.PythonCode), saved)
-
- def BufferPython(self):
- self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode))
-
- def StartBuffering(self):
- self.Buffering = True
-
- def EndBuffering(self):
- if self.Buffering:
- self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode))
- self.Buffering = False
-
- def MarkPythonAsSaved(self):
- self.EndBuffering()
- self.PythonBuffer.CurrentSaved()
-
- def PythonIsSaved(self):
- return self.PythonBuffer.IsCurrentSaved() and not self.Buffering
-
- def LoadPrevious(self):
- self.EndBuffering()
- self.PythonCode = cPickle.loads(self.PythonBuffer.Previous())
-
- def LoadNext(self):
- self.PythonCode = cPickle.loads(self.PythonBuffer.Next())
-
- def GetBufferState(self):
- first = self.PythonBuffer.IsFirst() and not self.Buffering
- last = self.PythonBuffer.IsLast()
- return not first, not last
-
-def _GetClassFunction(name):
- def GetRootClass():
- __import__("plugins.python.modules." + name)
- return getattr(modules, name).RootClass
- return GetRootClass
-
-class RootClass(PythonCodeTemplate):
-
- # For root object, available Childs Types are modules of the modules packages.
- PlugChildsTypes = [(name, _GetClassFunction(name), help) for name, help in zip(modules.__all__,modules.helps)]
-
- def PluginPath(self):
- return os.path.join(self.PlugParent.PluginPath(), self.PlugType)
-
- def PlugGenerate_C(self, buildpath, locations):
- """
- Generate C code
- @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
- @param locations: List of complete variables locations \
- [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
- "NAME" : name of the variable (generally "__IW0_1_2" style)
- "DIR" : direction "Q","I" or "M"
- "SIZE" : size "X", "B", "W", "D", "L"
- "LOC" : tuple of interger for IEC location (0,1,2,...)
- }, ...]
- @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
- """
- current_location = self.GetCurrentLocation()
- # define a unique name for the generated C file
- location_str = "_".join(map(lambda x:str(x), current_location))
-
- plugin_root = self.GetPlugRoot()
- plugin_root.GetIECProgramsAndVariables()
-
- plc_python_filepath = os.path.join(os.path.split(__file__)[0], "plc_python.c")
- plc_python_file = open(plc_python_filepath, 'r')
- plc_python_code = plc_python_file.read()
- plc_python_file.close()
- python_eval_fb_list = []
- for v in plugin_root._VariablesList:
- if v["vartype"] == "FB" and v["type"] in ["PYTHON_EVAL","PYTHON_POLL"]:
- python_eval_fb_list.append(v)
- python_eval_fb_count = max(1, len(python_eval_fb_list))
-
- # prepare python code
- plc_python_code = plc_python_code % {
- "python_eval_fb_count": python_eval_fb_count,
- "location": location_str}
-
- Gen_Pythonfile_path = os.path.join(buildpath, "python_%s.c"%location_str)
- pythonfile = open(Gen_Pythonfile_path,'w')
- pythonfile.write(plc_python_code)
- pythonfile.close()
-
- runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
- runtimefile = open(runtimefile_path, 'w')
- runtimefile.write(self.GetPythonCode())
- runtimefile.close()
-
- matiec_flags = '"-I%s"'%os.path.abspath(self.GetPlugRoot().GetIECLibPath())
-
- return [(Gen_Pythonfile_path, matiec_flags)], "", True, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb"))
diff -r 180e4a7d945c -r 1c23952dbde1 plugins/python/python_xsd.xsd
--- a/plugins/python/python_xsd.xsd Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-
-
-
-
-
-
- Formatted text according to parts of XHTML 1.1
-
-
-
-
-
-
-
diff -r 180e4a7d945c -r 1c23952dbde1 runtime/PLCObject.py
--- a/runtime/PLCObject.py Thu May 03 19:02:34 2012 +0200
+++ b/runtime/PLCObject.py Mon May 07 18:47:29 2012 +0200
@@ -109,7 +109,7 @@
self._stopPLC = self._stopPLC_real
else:
- # If python plugin is not enabled, we reuse _PythonIterator
+ # If python confnode is not enabled, we reuse _PythonIterator
# as a call that block pythonthread until StopPLC
self.PythonIteratorLock = Lock()
self.PythonIteratorLock.acquire()
diff -r 180e4a7d945c -r 1c23952dbde1 targets/LPC/__init__.py
--- a/targets/LPC/__init__.py Thu May 03 19:02:34 2012 +0200
+++ b/targets/LPC/__init__.py Mon May 07 18:47:29 2012 +0200
@@ -6,9 +6,9 @@
class LPC_target(toolchain_makefile):
#extension = ".ld"
#DebugEnabled = False
- def __init__(self, PluginsRootInstance):
+ def __init__(self, ConfigTreeRootInstance):
self.binmd5key = None
- toolchain_makefile.__init__(self, PluginsRootInstance)
+ toolchain_makefile.__init__(self, ConfigTreeRootInstance)
def _GetBinMD5FileName(self):
return os.path.join(self.buildpath, "lastbuildPLCbin.md5")
@@ -64,7 +64,7 @@
f.write(self.binmd5key)
f.close()
try:
- self.PluginsRootInstance.logger.write(
+ self.ConfigTreeRootInstance.logger.write(
_("Binary is %s bytes long\n")%
str(os.path.getsize(
os.path.join(self.buildpath, "ArmPLC_rom.bin"))))
diff -r 180e4a7d945c -r 1c23952dbde1 targets/Xenomai/__init__.py
--- a/targets/Xenomai/__init__.py Thu May 03 19:02:34 2012 +0200
+++ b/targets/Xenomai/__init__.py Mon May 07 18:47:29 2012 +0200
@@ -4,14 +4,14 @@
extension = ".so"
def getXenoConfig(self, flagsname):
""" Get xeno-config from target parameters """
- xeno_config=self.PluginsRootInstance.GetTarget().getcontent()["value"].getXenoConfig()
+ xeno_config=self.ConfigTreeRootInstance.GetTarget().getcontent()["value"].getXenoConfig()
if xeno_config:
from wxPopen import ProcessLogger
- status, result, err_result = ProcessLogger(self.PluginsRootInstance.logger,
+ status, result, err_result = ProcessLogger(self.ConfigTreeRootInstance.logger,
xeno_config + " --skin=native --"+flagsname,
no_stdout=True).spin()
if status:
- self.PluginsRootInstance.logger.write_error(_("Unable to get Xenomai's %s \n")%flagsname)
+ self.ConfigTreeRootInstance.logger.write_error(_("Unable to get Xenomai's %s \n")%flagsname)
return [result.strip()]
return []
diff -r 180e4a7d945c -r 1c23952dbde1 targets/toolchain_gcc.py
--- a/targets/toolchain_gcc.py Thu May 03 19:02:34 2012 +0200
+++ b/targets/toolchain_gcc.py Mon May 07 18:47:29 2012 +0200
@@ -10,23 +10,23 @@
It cannot be used as this and should be inherited in a target specific
class such as target_linux or target_win32
"""
- def __init__(self, PluginsRootInstance):
- self.PluginsRootInstance = PluginsRootInstance
+ def __init__(self, ConfigTreeRootInstance):
+ self.ConfigTreeRootInstance = ConfigTreeRootInstance
self.buildpath = None
- self.SetBuildPath(self.PluginsRootInstance._getBuildPath())
+ self.SetBuildPath(self.ConfigTreeRootInstance._getBuildPath())
def getBuilderCFLAGS(self):
"""
Returns list of builder specific CFLAGS
"""
- return [self.PluginsRootInstance.GetTarget().getcontent()["value"].getCFLAGS()]
+ return [self.ConfigTreeRootInstance.GetTarget().getcontent()["value"].getCFLAGS()]
def getBuilderLDFLAGS(self):
"""
Returns list of builder specific LDFLAGS
"""
- return self.PluginsRootInstance.LDFLAGS + \
- [self.PluginsRootInstance.GetTarget().getcontent()["value"].getLDFLAGS()]
+ return self.ConfigTreeRootInstance.LDFLAGS + \
+ [self.ConfigTreeRootInstance.GetTarget().getcontent()["value"].getLDFLAGS()]
def GetBinaryCode(self):
try:
@@ -56,7 +56,7 @@
def SetBuildPath(self, buildpath):
if self.buildpath != buildpath:
self.buildpath = buildpath
- self.exe = self.PluginsRootInstance.GetProjectName() + self.extension
+ self.exe = self.ConfigTreeRootInstance.GetProjectName() + self.extension
self.exe_path = os.path.join(self.buildpath, self.exe)
self.md5key = None
self.srcmd5 = {}
@@ -89,7 +89,7 @@
def build(self):
# Retrieve toolchain user parameters
- toolchain_params = self.PluginsRootInstance.GetTarget().getcontent()["value"]
+ toolchain_params = self.ConfigTreeRootInstance.GetTarget().getcontent()["value"]
self.compiler = toolchain_params.getCompiler()
self.linker = toolchain_params.getLinker()
@@ -99,11 +99,11 @@
obns = []
objs = []
relink = False
- for Location, CFilesAndCFLAGS, DoCalls in self.PluginsRootInstance.LocationCFilesAndCFLAGS:
+ for Location, CFilesAndCFLAGS, DoCalls in self.ConfigTreeRootInstance.LocationCFilesAndCFLAGS:
if Location:
- self.PluginsRootInstance.logger.write(_("Plugin : ") + self.PluginsRootInstance.GetChildByIECLocation(Location).GetCurrentName() + " " + str(Location)+"\n")
+ self.ConfigTreeRootInstance.logger.write(_("ConfNode : ") + self.ConfigTreeRootInstance.GetChildByIECLocation(Location).GetCurrentName() + " " + str(Location)+"\n")
else:
- self.PluginsRootInstance.logger.write(_("PLC :\n"))
+ self.ConfigTreeRootInstance.logger.write(_("PLC :\n"))
for CFile, CFLAGS in CFilesAndCFLAGS:
if CFile.endswith(".c"):
@@ -114,21 +114,21 @@
match = self.check_and_update_hash_and_deps(bn)
if match:
- self.PluginsRootInstance.logger.write(" [pass] "+bn+" -> "+obn+"\n")
+ self.ConfigTreeRootInstance.logger.write(" [pass] "+bn+" -> "+obn+"\n")
else:
relink = True
- self.PluginsRootInstance.logger.write(" [CC] "+bn+" -> "+obn+"\n")
+ self.ConfigTreeRootInstance.logger.write(" [CC] "+bn+" -> "+obn+"\n")
status, result, err_result = ProcessLogger(
- self.PluginsRootInstance.logger,
+ self.ConfigTreeRootInstance.logger,
"\"%s\" -c \"%s\" -o \"%s\" %s %s"%
(self.compiler, CFile, objectfilename, Builder_CFLAGS, CFLAGS)
).spin()
if status :
self.srcmd5.pop(bn)
- self.PluginsRootInstance.logger.write_error(_("C compilation of %s failed.\n")%bn)
+ self.ConfigTreeRootInstance.logger.write_error(_("C compilation of %s failed.\n")%bn)
return False
obns.append(obn)
objs.append(objectfilename)
@@ -138,7 +138,7 @@
######### GENERATE library FILE ########################################
# Link all the object files into one binary file
- self.PluginsRootInstance.logger.write(_("Linking :\n"))
+ self.ConfigTreeRootInstance.logger.write(_("Linking :\n"))
if relink:
objstring = []
@@ -147,10 +147,10 @@
ALLldflags = ' '.join(self.getBuilderLDFLAGS())
- self.PluginsRootInstance.logger.write(" [CC] " + ' '.join(obns)+" -> " + self.exe + "\n")
+ self.ConfigTreeRootInstance.logger.write(" [CC] " + ' '.join(obns)+" -> " + self.exe + "\n")
status, result, err_result = ProcessLogger(
- self.PluginsRootInstance.logger,
+ self.ConfigTreeRootInstance.logger,
"\"%s\" %s -o \"%s\" %s"%
(self.linker,
listobjstring,
@@ -162,7 +162,7 @@
return False
else:
- self.PluginsRootInstance.logger.write(" [pass] " + ' '.join(obns)+" -> " + self.exe + "\n")
+ self.ConfigTreeRootInstance.logger.write(" [pass] " + ' '.join(obns)+" -> " + self.exe + "\n")
# Calculate md5 key and get data for the new created PLC
data=self.GetBinaryCode()
diff -r 180e4a7d945c -r 1c23952dbde1 targets/toolchain_makefile.py
--- a/targets/toolchain_makefile.py Thu May 03 19:02:34 2012 +0200
+++ b/targets/toolchain_makefile.py Mon May 07 18:47:29 2012 +0200
@@ -7,11 +7,11 @@
includes_re = re.compile('\s*#include\s*["<]([^">]*)[">].*')
class toolchain_makefile():
- def __init__(self, PluginsRootInstance):
- self.PluginsRootInstance = PluginsRootInstance
+ def __init__(self, ConfigTreeRootInstance):
+ self.ConfigTreeRootInstance = ConfigTreeRootInstance
self.md5key = None
self.buildpath = None
- self.SetBuildPath(self.PluginsRootInstance._getBuildPath())
+ self.SetBuildPath(self.ConfigTreeRootInstance._getBuildPath())
def SetBuildPath(self, buildpath):
if self.buildpath != buildpath:
@@ -60,7 +60,7 @@
srcfiles= []
cflags = []
wholesrcdata = ""
- for Location, CFilesAndCFLAGS, DoCalls in self.PluginsRootInstance.LocationCFilesAndCFLAGS:
+ for Location, CFilesAndCFLAGS, DoCalls in self.ConfigTreeRootInstance.LocationCFilesAndCFLAGS:
# Get CFiles list to give it to makefile
for CFile, CFLAGS in CFilesAndCFLAGS:
CFileName = os.path.basename(CFile)
@@ -72,7 +72,7 @@
oldmd5 = self.md5key
self.md5key = hashlib.md5(wholesrcdata).hexdigest()
- props = self.PluginsRootInstance.GetProjectProperties()
+ props = self.ConfigTreeRootInstance.GetProjectProperties()
self.md5key += '#'.join([props[key] for key in ['companyName',
'projectName',
'productName']])
@@ -88,21 +88,21 @@
"md5": '"'+self.md5key+'"'
}
- target = self.PluginsRootInstance.GetTarget().getcontent()["value"]
+ target = self.ConfigTreeRootInstance.GetTarget().getcontent()["value"]
command = target.getCommand().split(' ') +\
[target.getBuildPath()] +\
[arg % beremizcommand for arg in target.getArguments().split(' ')] +\
target.getRule().split(' ')
# Call Makefile to build PLC code and link it with target specific code
- status, result, err_result = ProcessLogger(self.PluginsRootInstance.logger,
+ status, result, err_result = ProcessLogger(self.ConfigTreeRootInstance.logger,
command).spin()
if status :
self.md5key = None
- self.PluginsRootInstance.logger.write_error(_("C compilation failed.\n"))
+ self.ConfigTreeRootInstance.logger.write_error(_("C compilation failed.\n"))
return False
return True
else :
- self.PluginsRootInstance.logger.write(_("Source didn't change, no build.\n"))
+ self.ConfigTreeRootInstance.logger.write(_("Source didn't change, no build.\n"))
return True
diff -r 180e4a7d945c -r 1c23952dbde1 tests/canopen_master/canopen@canfestival/baseconfnode.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/canopen_master/canopen@canfestival/baseconfnode.xml Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+
+
diff -r 180e4a7d945c -r 1c23952dbde1 tests/canopen_master/canopen@canfestival/baseplugin.xml
--- a/tests/canopen_master/canopen@canfestival/baseplugin.xml Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-
-
diff -r 180e4a7d945c -r 1c23952dbde1 tests/canopen_master/canopen@canfestival/confnode.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/canopen_master/canopen@canfestival/confnode.xml Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+
+
diff -r 180e4a7d945c -r 1c23952dbde1 tests/canopen_master/canopen@canfestival/master@CanOpenNode/baseconfnode.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/canopen_master/canopen@canfestival/master@CanOpenNode/baseconfnode.xml Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+
+
diff -r 180e4a7d945c -r 1c23952dbde1 tests/canopen_master/canopen@canfestival/master@CanOpenNode/baseplugin.xml
--- a/tests/canopen_master/canopen@canfestival/master@CanOpenNode/baseplugin.xml Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-
-
diff -r 180e4a7d945c -r 1c23952dbde1 tests/canopen_master/canopen@canfestival/master@CanOpenNode/confnode.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/canopen_master/canopen@canfestival/master@CanOpenNode/confnode.xml Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+
+
diff -r 180e4a7d945c -r 1c23952dbde1 tests/canopen_master/canopen@canfestival/master@CanOpenNode/plugin.xml
--- a/tests/canopen_master/canopen@canfestival/master@CanOpenNode/plugin.xml Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-
-
diff -r 180e4a7d945c -r 1c23952dbde1 tests/canopen_master/canopen@canfestival/plugin.xml
--- a/tests/canopen_master/canopen@canfestival/plugin.xml Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-
-
diff -r 180e4a7d945c -r 1c23952dbde1 tests/canopen_slave/canopen@canfestival/baseconfnode.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/canopen_slave/canopen@canfestival/baseconfnode.xml Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+
+
diff -r 180e4a7d945c -r 1c23952dbde1 tests/canopen_slave/canopen@canfestival/baseplugin.xml
--- a/tests/canopen_slave/canopen@canfestival/baseplugin.xml Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-
-
diff -r 180e4a7d945c -r 1c23952dbde1 tests/canopen_slave/canopen@canfestival/confnode.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/canopen_slave/canopen@canfestival/confnode.xml Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+
+
diff -r 180e4a7d945c -r 1c23952dbde1 tests/canopen_slave/canopen@canfestival/plugin.xml
--- a/tests/canopen_slave/canopen@canfestival/plugin.xml Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-
-
diff -r 180e4a7d945c -r 1c23952dbde1 tests/canopen_slave/canopen@canfestival/slave@CanOpenSlave/baseconfnode.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/canopen_slave/canopen@canfestival/slave@CanOpenSlave/baseconfnode.xml Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+
+
diff -r 180e4a7d945c -r 1c23952dbde1 tests/canopen_slave/canopen@canfestival/slave@CanOpenSlave/baseplugin.xml
--- a/tests/canopen_slave/canopen@canfestival/slave@CanOpenSlave/baseplugin.xml Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-
-
diff -r 180e4a7d945c -r 1c23952dbde1 tests/canopen_slave/canopen@canfestival/slave@CanOpenSlave/confnode.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/canopen_slave/canopen@canfestival/slave@CanOpenSlave/confnode.xml Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+
+
diff -r 180e4a7d945c -r 1c23952dbde1 tests/canopen_slave/canopen@canfestival/slave@CanOpenSlave/plugin.xml
--- a/tests/canopen_slave/canopen@canfestival/slave@CanOpenSlave/plugin.xml Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-
-
diff -r 180e4a7d945c -r 1c23952dbde1 tests/python/python@python/baseconfnode.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/python/python@python/baseconfnode.xml Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+
+
diff -r 180e4a7d945c -r 1c23952dbde1 tests/python/python@python/baseplugin.xml
--- a/tests/python/python@python/baseplugin.xml Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-
-
diff -r 180e4a7d945c -r 1c23952dbde1 tests/svgui/python@python/baseconfnode.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/svgui/python@python/baseconfnode.xml Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+
+
diff -r 180e4a7d945c -r 1c23952dbde1 tests/svgui/python@python/baseplugin.xml
--- a/tests/svgui/python@python/baseplugin.xml Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-
-
diff -r 180e4a7d945c -r 1c23952dbde1 tests/svgui/python@python/svgui@svgui/baseconfnode.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/svgui/python@python/svgui@svgui/baseconfnode.xml Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+
+
diff -r 180e4a7d945c -r 1c23952dbde1 tests/svgui/python@python/svgui@svgui/baseplugin.xml
--- a/tests/svgui/python@python/svgui@svgui/baseplugin.xml Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-
-
diff -r 180e4a7d945c -r 1c23952dbde1 tests/wxGlade/python@python/HMIFrame@wxglade_hmi/baseconfnode.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/wxGlade/python@python/HMIFrame@wxglade_hmi/baseconfnode.xml Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+
+
diff -r 180e4a7d945c -r 1c23952dbde1 tests/wxGlade/python@python/HMIFrame@wxglade_hmi/baseplugin.xml
--- a/tests/wxGlade/python@python/HMIFrame@wxglade_hmi/baseplugin.xml Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-
-
diff -r 180e4a7d945c -r 1c23952dbde1 tests/wxGlade/python@python/baseconfnode.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/wxGlade/python@python/baseconfnode.xml Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+
+
diff -r 180e4a7d945c -r 1c23952dbde1 tests/wxGlade/python@python/baseplugin.xml
--- a/tests/wxGlade/python@python/baseplugin.xml Thu May 03 19:02:34 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-
-