# HG changeset patch # User edouard # Date 1250156258 -7200 # Node ID 71c441104cac214097d83abe7c88b9cac06fbb4b # Parent b7cb57a2da08ec9a6933cad26bbb1eae1b4ffc61# Parent 75ae46b66315975b49ec48574befa094be583fdd Merge with 75ae46b66315975b49ec48574befa094be583fdd diff -r 75ae46b66315 -r 71c441104cac Beremiz.py --- a/Beremiz.py Wed Aug 12 16:23:59 2009 -0600 +++ b/Beremiz.py Thu Aug 13 11:37:38 2009 +0200 @@ -29,9 +29,10 @@ import shutil import random -_local_path = os.path.split(os.path.realpath(__file__))[0] +CWD = os.path.split(os.path.realpath(__file__))[0] + def Bpath(*args): - return os.path.join(_local_path,*args) + return os.path.join(CWD,*args) if __name__ == '__main__': def usage(): @@ -72,6 +73,33 @@ splash=wx.SplashScreen(bmp,wx.SPLASH_CENTRE_ON_SCREEN, 1000, None) wx.Yield() +# Import module for internationalization +import gettext +import __builtin__ + +# Get folder containing translation files +localedir = os.path.join(CWD,"locale") +# Get the default language +langid = wx.LANGUAGE_DEFAULT +# Define translation domain (name of translation files) +domain = "Beremiz" + +# Define locale for wx +loc = __builtin__.__dict__.get('loc', None) +if loc is None: + loc = wx.Locale(langid) + __builtin__.__dict__['loc'] = loc +# Define location for searching translation files +loc.AddCatalogLookupPathPrefix(localedir) +# Define locale domain +loc.AddCatalog(domain) + +def unicode_translation(message): + return wx.GetTranslation(message).encode("utf-8") + +if __name__ == '__main__': + __builtin__.__dict__['_'] = wx.GetTranslation#unicode_translation + import wx.lib.buttons, wx.lib.statbmp import TextCtrlAutoComplete, cPickle import types, time, re, platform, time, traceback, commands @@ -255,19 +283,19 @@ def _init_coll_FileMenu_Items(self, parent): parent.Append(help='', id=wx.ID_NEW, - kind=wx.ITEM_NORMAL, text=u'New\tCTRL+N') + kind=wx.ITEM_NORMAL, text=_(u'New\tCTRL+N')) parent.Append(help='', id=wx.ID_OPEN, - kind=wx.ITEM_NORMAL, text=u'Open\tCTRL+O') + kind=wx.ITEM_NORMAL, text=_(u'Open\tCTRL+O')) parent.Append(help='', id=wx.ID_SAVE, - kind=wx.ITEM_NORMAL, text=u'Save\tCTRL+S') + kind=wx.ITEM_NORMAL, text=_(u'Save\tCTRL+S')) parent.Append(help='', id=wx.ID_CLOSE_ALL, - kind=wx.ITEM_NORMAL, text=u'Close Project') + kind=wx.ITEM_NORMAL, text=_(u'Close Project')) parent.AppendSeparator() parent.Append(help='', id=wx.ID_PROPERTIES, - kind=wx.ITEM_NORMAL, text=u'Properties') + kind=wx.ITEM_NORMAL, text=_(u'Properties')) parent.AppendSeparator() parent.Append(help='', id=wx.ID_EXIT, - kind=wx.ITEM_NORMAL, text=u'Quit\tCTRL+Q') + kind=wx.ITEM_NORMAL, text=_(u'Quit\tCTRL+Q')) self.Bind(wx.EVT_MENU, self.OnNewProjectMenu, id=wx.ID_NEW) self.Bind(wx.EVT_MENU, self.OnOpenProjectMenu, id=wx.ID_OPEN) self.Bind(wx.EVT_MENU, self.OnSaveProjectMenu, id=wx.ID_SAVE) @@ -277,27 +305,27 @@ def _init_coll_EditMenu_Items(self, parent): parent.Append(help='', id=wx.ID_EDIT, - kind=wx.ITEM_NORMAL, text=u'Edit PLC\tCTRL+R') + kind=wx.ITEM_NORMAL, text=_(u'Edit PLC\tCTRL+R')) parent.AppendSeparator() parent.Append(help='', id=wx.ID_ADD, - kind=wx.ITEM_NORMAL, text=u'Add Plugin') + kind=wx.ITEM_NORMAL, text=_(u'Add Plugin')) parent.Append(help='', id=wx.ID_DELETE, - kind=wx.ITEM_NORMAL, text=u'Delete Plugin') + kind=wx.ITEM_NORMAL, text=_(u'Delete Plugin')) self.Bind(wx.EVT_MENU, self.OnEditPLCMenu, id=wx.ID_EDIT) self.Bind(wx.EVT_MENU, self.OnAddMenu, id=wx.ID_ADD) self.Bind(wx.EVT_MENU, self.OnDeleteMenu, id=wx.ID_DELETE) def _init_coll_RunMenu_Items(self, parent): parent.Append(help='', id=ID_BEREMIZRUNMENUBUILD, - kind=wx.ITEM_NORMAL, text=u'Build\tCTRL+R') + kind=wx.ITEM_NORMAL, text=_(u'Build\tCTRL+R')) parent.AppendSeparator() parent.Append(help='', id=ID_BEREMIZRUNMENUSIMULATE, - kind=wx.ITEM_NORMAL, text=u'Simulate') + kind=wx.ITEM_NORMAL, text=_(u'Simulate')) parent.Append(help='', id=ID_BEREMIZRUNMENURUN, - kind=wx.ITEM_NORMAL, text=u'Run') + kind=wx.ITEM_NORMAL, text=_(u'Run')) parent.AppendSeparator() parent.Append(help='', id=ID_BEREMIZRUNMENUSAVELOG, - kind=wx.ITEM_NORMAL, text=u'Save Log') + kind=wx.ITEM_NORMAL, text=_(u'Save Log')) self.Bind(wx.EVT_MENU, self.OnBuildMenu, id=ID_BEREMIZRUNMENUBUILD) self.Bind(wx.EVT_MENU, self.OnSimulateMenu, @@ -309,17 +337,17 @@ def _init_coll_HelpMenu_Items(self, parent): parent.Append(help='', id=wx.ID_HELP, - kind=wx.ITEM_NORMAL, text=u'Beremiz\tF1') + kind=wx.ITEM_NORMAL, text=_(u'Beremiz\tF1')) parent.Append(help='', id=wx.ID_ABOUT, - kind=wx.ITEM_NORMAL, text=u'About') + kind=wx.ITEM_NORMAL, text=_(u'About')) self.Bind(wx.EVT_MENU, self.OnBeremizMenu, id=wx.ID_HELP) self.Bind(wx.EVT_MENU, self.OnAboutMenu, id=wx.ID_ABOUT) def _init_coll_MenuBar_Menus(self, parent): - parent.Append(menu=self.FileMenu, title=u'File') + parent.Append(menu=self.FileMenu, title=_(u'File')) #parent.Append(menu=self.EditMenu, title=u'Edit') #parent.Append(menu=self.RunMenu, title=u'Run') - parent.Append(menu=self.HelpMenu, title=u'Help') + parent.Append(menu=self.HelpMenu, title=_(u'Help')) def _init_utils(self): self.MenuBar = wx.MenuBar() @@ -361,7 +389,7 @@ def _init_ctrls(self, prnt): wx.Frame.__init__(self, id=ID_BEREMIZ, name=u'Beremiz', parent=prnt, pos=wx.Point(0, 0), size=wx.Size(1000, 600), - style=wx.DEFAULT_FRAME_STYLE|wx.CLIP_CHILDREN, title=u'Beremiz') + style=wx.DEFAULT_FRAME_STYLE|wx.CLIP_CHILDREN, title=_(u'Beremiz')) self._init_utils() self.SetClientSize(wx.Size(1000, 600)) self.SetMenuBar(self.MenuBar) @@ -404,7 +432,7 @@ self.AUIManager.AddPane(self.PLCConfig, wx.aui.AuiPaneInfo().CenterPane()) self.AUIManager.AddPane(self.LogConsole, wx.aui.AuiPaneInfo(). - Caption("Log Console").Bottom().Layer(1). + Caption(_("Log Console")).Bottom().Layer(1). BestSize(wx.Size(800, 200)).CloseButton(False)) self.AUIManager.Update() @@ -492,8 +520,8 @@ if self.PluginRoot is not None: if self.PluginRoot.ProjectTestModified(): dialog = wx.MessageDialog(self, - "Save changes ?", - "Close Application", + _("Save changes ?"), + _("Close Application"), wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION) answer = dialog.ShowModal() dialog.Destroy() @@ -581,7 +609,7 @@ addbutton = wx.lib.buttons.GenBitmapButton(id=addbutton_id, bitmap=wx.Bitmap(Bpath( 'images', 'Add.png')), name='AddPluginButton', parent=plcwindow, pos=wx.Point(0, 0), size=wx.Size(16, 16), style=wx.NO_BORDER) - addbutton.SetToolTipString("Add a sub plugin") + addbutton.SetToolTipString(_("Add a sub plugin")) addbutton.Bind(wx.EVT_BUTTON, self.Gen_AddPluginMenu(self.PluginRoot), id=addbutton_id) plcwindowsizer.AddWindow(addbutton, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER) @@ -677,7 +705,7 @@ for plugin_method in plugin.PluginMethods: if "method" in plugin_method and plugin_method.get("shown",True): id = wx.NewId() - label=plugin_method["name"] + label = plugin_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, name=label, pos=wx.DefaultPosition, style=wx.NO_BORDER) @@ -784,7 +812,7 @@ enablebutton_id = wx.NewId() enablebutton = wx.lib.buttons.GenBitmapToggleButton(id=enablebutton_id, bitmap=wx.Bitmap(Bpath( 'images', 'Disabled.png')), name='EnableButton', parent=leftwindow, 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 plugin")) make_genbitmaptogglebutton_flat(enablebutton) enablebutton.SetBitmapSelected(wx.Bitmap(Bpath( 'images', 'Enabled.png'))) enablebutton.SetToggle(plugin.MandatoryParams[1].getEnabled()) @@ -834,7 +862,7 @@ deletebutton = wx.lib.buttons.GenBitmapButton(id=deletebutton_id, bitmap=wx.Bitmap(Bpath( 'images', 'Delete.png')), name='DeletePluginButton', parent=leftwindow, pos=wx.Point(0, 0), size=wx.Size(16, 16), style=wx.NO_BORDER) - deletebutton.SetToolTipString("Delete this plugin") + deletebutton.SetToolTipString(_("Delete this plugin")) deletebutton.Bind(wx.EVT_BUTTON, self.GetDeleteButtonFunction(plugin), id=deletebutton_id) adddeletesizer.AddWindow(deletebutton, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER) @@ -843,7 +871,7 @@ addbutton = wx.lib.buttons.GenBitmapButton(id=addbutton_id, bitmap=wx.Bitmap(Bpath( 'images', 'Add.png')), name='AddPluginButton', parent=leftwindow, pos=wx.Point(0, 0), size=wx.Size(16, 16), style=wx.NO_BORDER) - addbutton.SetToolTipString("Add a sub plugin") + addbutton.SetToolTipString(_("Add a sub plugin")) addbutton.Bind(wx.EVT_BUTTON, self.Gen_AddPluginMenu(plugin), id=addbutton_id) adddeletesizer.AddWindow(addbutton, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER) @@ -1025,7 +1053,7 @@ if len(plugin.PlugChildsTypes) > 0: for name, XSDClass, help in plugin.PlugChildsTypes: new_id = wx.NewId() - main_menu.Append(help=help, id=new_id, kind=wx.ITEM_NORMAL, text="Append "+help) + 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.PopupMenuXY(main_menu) event.Skip() @@ -1110,7 +1138,8 @@ else: element_path = element_infos["name"] if element_infos["type"] == "element": - staticbox = wx.StaticBox(id=-1, label=element_infos["name"], + label = element_infos["name"] + staticbox = wx.StaticBox(id=-1, label=_(label), name='%s_staticbox'%element_infos["name"], parent=parent, pos=wx.Point(0, 0), size=wx.Size(10, 0), style=0) staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL) @@ -1130,10 +1159,11 @@ name="%s_bitmap"%element_infos["name"], parent=parent, pos=wx.Point(0, 0), size=wx.Size(24, 24), style=0) boxsizer.AddWindow(staticbitmap, 0, border=5, flag=wx.RIGHT) - statictext = wx.StaticText(id=-1, label="%s:"%element_infos["name"], + label = element_infos["name"] + statictext = wx.StaticText(id=-1, label="%s:"%_(label), name="%s_label"%element_infos["name"], parent=parent, - pos=wx.Point(0, 0), size=wx.Size(100, 17), style=0) - boxsizer.AddWindow(statictext, 0, border=4, flag=wx.TOP) + pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) + boxsizer.AddWindow(statictext, 0, border=5, flag=wx.ALIGN_CENTER_VERTICAL|wx.RIGHT) id = wx.NewId() if isinstance(element_infos["type"], types.ListType): combobox = wx.ComboBox(id=id, name=element_infos["name"], parent=parent, @@ -1144,7 +1174,9 @@ if len(element_infos["type"]) > 0 and isinstance(element_infos["type"][0], types.TupleType): for choice, xsdclass in element_infos["type"]: combobox.Append(choice) - staticbox = wx.StaticBox(id=-1, label="%(name)s - %(value)s"%element_infos, + name = element_infos["name"] + value = element_infos["value"] + staticbox = wx.StaticBox(id=-1, label="%s - %s"%(_(name), _(value)), name='%s_staticbox'%element_infos["name"], parent=parent, pos=wx.Point(0, 0), size=wx.Size(10, 0), style=0) staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL) @@ -1214,7 +1246,7 @@ else: defaultpath = config.Read("lastopenedfolder") - dialog = wx.DirDialog(self , "Choose a project", defaultpath, wx.DD_NEW_DIR_BUTTON) + dialog = wx.DirDialog(self , _("Choose a project"), defaultpath, wx.DD_NEW_DIR_BUTTON) if dialog.ShowModal() == wx.ID_OK: projectpath = dialog.GetPath() dialog.Destroy() @@ -1226,7 +1258,7 @@ self.RefreshAll() self.RefreshMainMenu() else: - message = wx.MessageDialog(self, res, "ERROR", wx.OK|wx.ICON_ERROR) + message = wx.MessageDialog(self, res, _("ERROR"), wx.OK|wx.ICON_ERROR) message.ShowModal() message.Destroy() event.Skip() @@ -1237,7 +1269,7 @@ else: defaultpath = config.Read("lastopenedfolder") - dialog = wx.DirDialog(self , "Choose a project", defaultpath, wx.DD_NEW_DIR_BUTTON) + dialog = wx.DirDialog(self , _("Choose a project"), defaultpath, wx.DD_NEW_DIR_BUTTON) if dialog.ShowModal() == wx.ID_OK: projectpath = dialog.GetPath() if os.path.isdir(projectpath): @@ -1249,11 +1281,11 @@ self.RefreshAll() self.RefreshMainMenu() else: - message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR) + message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR) message.ShowModal() message.Destroy() else: - message = wx.MessageDialog(self, "\"%s\" folder is not a valid Beremiz project\n"%projectpath, "Error", wx.OK|wx.ICON_ERROR) + message = wx.MessageDialog(self, _("\"%s\" folder is not a valid Beremiz project\n")%projectpath, _("Error"), wx.OK|wx.ICON_ERROR) message.ShowModal() message.Destroy() dialog.Destroy() @@ -1263,8 +1295,8 @@ if self.PluginRoot is not None: if self.PluginRoot.ProjectTestModified(): dialog = wx.MessageDialog(self, - "Save changes ?", - "Close Application", + _("Save changes ?"), + _("Close Application"), wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION) answer = dialog.ShowModal() dialog.Destroy() @@ -1322,7 +1354,7 @@ event.Skip() def OnAboutMenu(self, event): - OpenHtmlFrame(self,"About Beremiz", Bpath("doc","about.html"), wx.Size(550, 500)) + OpenHtmlFrame(self,_("About Beremiz"), Bpath("doc","about.html"), wx.Size(550, 500)) event.Skip() def OnAddButton(self, event): @@ -1355,7 +1387,7 @@ return DeleteButtonFunction def AddPlugin(self, PluginType, plugin): - dialog = wx.TextEntryDialog(self, "Please enter a name for plugin:", "Add Plugin", "", wx.OK|wx.CANCEL) + dialog = wx.TextEntryDialog(self, _("Please enter a name for plugin:"), _("Add Plugin"), "", wx.OK|wx.CANCEL) if dialog.ShowModal() == wx.ID_OK: PluginName = dialog.GetValue() plugin.PlugAddChild(PluginName, PluginType) @@ -1363,7 +1395,7 @@ dialog.Destroy() def DeletePlugin(self, plugin): - dialog = wx.MessageDialog(self, "Really delete plugin ?", "Remove plugin", wx.YES_NO|wx.NO_DEFAULT) + dialog = wx.MessageDialog(self, _("Really delete plugin ?"), _("Remove plugin"), wx.YES_NO|wx.NO_DEFAULT) if dialog.ShowModal() == wx.ID_YES: self.PluginInfos.pop(plugin) plugin.PlugRemove() @@ -1380,12 +1412,12 @@ def Display_Exception_Dialog(e_type, e_value, e_tb, bug_report_path): trcbck_lst = [] for i,line in enumerate(traceback.extract_tb(e_tb)): - trcbck = " " + str(i+1) + ". " + trcbck = " " + str(i+1) + _(". ") if line[0].find(os.getcwd()) == -1: - trcbck += "file : " + str(line[0]) + ", " + trcbck += _("file : ") + str(line[0]) + _(", ") else: - trcbck += "file : " + str(line[0][len(os.getcwd()):]) + ", " - trcbck += "line : " + str(line[1]) + ", " + "function : " + str(line[2]) + trcbck += _("file : ") + str(line[0][len(os.getcwd()):]) + _(", ") + trcbck += _("line : ") + str(line[1]) + _(", ") + _("function : ") + str(line[2]) trcbck_lst.append(trcbck) # Allow clicking.... @@ -1394,7 +1426,7 @@ cap.ReleaseMouse() dlg = wx.SingleChoiceDialog(None, - """ + _(""" An unhandled exception (bug) occured. Bug report saved at : (%s) @@ -1406,9 +1438,9 @@ You should now restart Beremiz. Traceback: -""" % bug_report_path + +""") % bug_report_path + str(e_type) + " : " + str(e_value), - "Error", + _("Error"), trcbck_lst) try: res = (dlg.ShowModal() == wx.ID_OK) @@ -1418,7 +1450,7 @@ return res def Display_Error_Dialog(e_value): - message = wxMessageDialog(None, str(e_value), "Error", wxOK|wxICON_ERROR) + message = wxMessageDialog(None, str(e_value), _("Error"), wxOK|wxICON_ERROR) message.ShowModal() message.Destroy() diff -r 75ae46b66315 -r 71c441104cac Beremiz_service.py --- a/Beremiz_service.py Wed Aug 12 16:23:59 2009 -0600 +++ b/Beremiz_service.py Thu Aug 13 11:37:38 2009 +0200 @@ -34,12 +34,13 @@ -h - print this help text and quit -a - autostart PLC (0:disable 1:enable) -x - enable/disable wxTaskbarIcon (0:disable 1:enable) + -t - enable/disable Twisted web interface (0:disable 1:enable) working_dir - directory where are stored PLC files """%sys.argv[0] try: - opts, argv = getopt.getopt(sys.argv[1:], "i:p:n:x:a:h") + opts, argv = getopt.getopt(sys.argv[1:], "i:p:n:x:t:a:h") except getopt.GetoptError, err: # print help information and exit: print str(err) # will print something like "option -a not recognized" @@ -56,6 +57,8 @@ autostart = False enablewx = True havewx = False +enabletwisted = True +havetwisted = False for o, a in opts: if o == "-h": @@ -71,6 +74,8 @@ name = a elif o == "-x": enablewx = int(a) + elif o == "-t": + enabletwisted = int(a) elif o == "-a": autostart = int(a) else: @@ -86,6 +91,10 @@ WorkingDir = os.getcwd() argv=[WorkingDir] +import __builtin__ +if __name__ == '__main__': + __builtin__.__dict__['_'] = lambda x: x + if enablewx: try: import wx, re @@ -96,6 +105,36 @@ havewx = False if havewx: + app=wx.App(redirect=False) + + # Import module for internationalization + import gettext + + CWD = os.path.split(os.path.realpath(__file__))[0] + + # Get folder containing translation files + localedir = os.path.join(CWD,"locale") + # Get the default language + langid = wx.LANGUAGE_DEFAULT + # Define translation domain (name of translation files) + domain = "Beremiz" + + # Define locale for wx + loc = __builtin__.__dict__.get('loc', None) + if loc is None: + loc = wx.Locale(langid) + __builtin__.__dict__['loc'] = loc + # Define location for searching translation files + loc.AddCatalogLookupPathPrefix(localedir) + # Define locale domain + loc.AddCatalog(domain) + + def unicode_translation(message): + return wx.GetTranslation(message).encode("utf-8") + + if __name__ == '__main__': + __builtin__.__dict__['_'] = wx.GetTranslation#unicode_translation + try: from wx.lib.embeddedimage import PyEmbeddedImage except: @@ -226,7 +265,7 @@ texts = {"value" : value} for function, message in self.Tests: if not function(value): - message = wx.MessageDialog(self, message%texts, "Error", wx.OK|wx.ICON_ERROR) + message = wx.MessageDialog(self, message%texts, _("Error"), wx.OK|wx.ICON_ERROR) message.ShowModal() message.Destroy() return @@ -275,16 +314,16 @@ the base class takes care of the rest. """ menu = wx.Menu() - menu.Append(self.TBMENU_START, "Start PLC") - menu.Append(self.TBMENU_STOP, "Stop PLC") - menu.Append(self.TBMENU_CHANGE_NAME, "Change Name") - menu.Append(self.TBMENU_CHANGE_INTERFACE, "Change IP of interface to bind") - menu.Append(self.TBMENU_LIVE_SHELL, "Launch a live Python shell") - menu.Append(self.TBMENU_WXINSPECTOR, "Launch WX GUI inspector") - menu.Append(self.TBMENU_CHANGE_PORT, "Change Port Number") + menu.Append(self.TBMENU_START, _("Start PLC")) + menu.Append(self.TBMENU_STOP, _("Stop PLC")) + menu.Append(self.TBMENU_CHANGE_NAME, _("Change Name")) + menu.Append(self.TBMENU_CHANGE_INTERFACE, _("Change IP of interface to bind")) + menu.Append(self.TBMENU_LIVE_SHELL, _("Launch a live Python shell")) + menu.Append(self.TBMENU_WXINSPECTOR, _("Launch WX GUI inspector")) + menu.Append(self.TBMENU_CHANGE_PORT, _("Change Port Number")) menu.AppendSeparator() - menu.Append(self.TBMENU_CHANGE_WD, "Change working directory") - menu.Append(self.TBMENU_QUIT, "Quit") + menu.Append(self.TBMENU_CHANGE_WD, _("Change working directory")) + menu.Append(self.TBMENU_QUIT, _("Quit")) return menu def MakeIcon(self, img): @@ -311,9 +350,9 @@ evt.Skip() def OnTaskBarChangeInterface(self, evt): - dlg = ParamsEntryDialog(None, "Enter the ip of the interface to bind", defaultValue=self.pyroserver.ip) - dlg.SetTests([(re.compile('\d{1,3}(?:\.\d{1,3}){3}$').match, "Ip is not valid!"), - ( lambda ip :len([x for x in ip.split(".") if 0 <= int(x) <= 255]) == 4, "Ip is not valid!") + dlg = ParamsEntryDialog(None, _("Enter the ip of the interface to bind"), defaultValue=self.pyroserver.ip) + dlg.SetTests([(re.compile('\d{1,3}(?:\.\d{1,3}){3}$').match, _("Ip is not valid!")), + ( lambda ip :len([x for x in ip.split(".") if 0 <= int(x) <= 255]) == 4, _("Ip is not valid!")) ]) if dlg.ShowModal() == wx.ID_OK: self.pyroserver.ip = dlg.GetValue() @@ -321,23 +360,23 @@ evt.Skip() def OnTaskBarChangePort(self, evt): - dlg = ParamsEntryDialog(None, "Enter a port number ", defaultValue=str(self.pyroserver.port)) - dlg.SetTests([(UnicodeType.isdigit, "Port number must be an integer!"), (lambda port : 0 <= int(port) <= 65535 , "Port number must be 0 <= port <= 65535!")]) + dlg = ParamsEntryDialog(None, _("Enter a port number "), defaultValue=str(self.pyroserver.port)) + dlg.SetTests([(UnicodeType.isdigit, _("Port number must be an integer!")), (lambda port : 0 <= int(port) <= 65535 , _("Port number must be 0 <= port <= 65535!"))]) if dlg.ShowModal() == wx.ID_OK: self.pyroserver.port = int(dlg.GetValue()) self.pyroserver.Stop() evt.Skip() def OnTaskBarChangeWorkingDir(self, evt): - dlg = wx.DirDialog(None, "Choose a working directory ", self.pyroserver.workdir, wx.DD_NEW_DIR_BUTTON) + dlg = wx.DirDialog(None, _("Choose a working directory "), self.pyroserver.workdir, wx.DD_NEW_DIR_BUTTON) if dlg.ShowModal() == wx.ID_OK: self.pyroserver.workdir = dlg.GetPath() self.pyroserver.Stop() evt.Skip() def OnTaskBarChangeName(self, evt): - dlg = ParamsEntryDialog(None, "Enter a name ", defaultValue=self.pyroserver.name) - dlg.SetTests([(lambda name : len(name) is not 0 , "Name must not be null!")]) + dlg = ParamsEntryDialog(None, _("Enter a name "), defaultValue=self.pyroserver.name) + dlg.SetTests([(lambda name : len(name) is not 0 , _("Name must not be null!"))]) if dlg.ShowModal() == wx.ID_OK: self.pyroserver.name = dlg.GetValue() self.pyroserver.Restart() @@ -350,7 +389,7 @@ frame = py.crust.CrustFrame(locals=self.pyroserver.plcobj.python_threads_vars) frame.Show() else: - wx.MessageBox("No runnning PLC","Error") + wx.MessageBox(_("No runnning PLC"), _("Error")) evt.Skip() def OnTaskBarWXInspector(self, evt): @@ -392,7 +431,7 @@ return callable(*args,**kwargs) class Server(): - def __init__(self, name, ip, port, workdir, argv, autostart=False, statuschange=None, evaluator=default_evaluator): + def __init__(self, name, ip, port, workdir, argv, autostart=False, statuschange=None, evaluator=default_evaluator, website=None): self.continueloop = True self.daemon = None self.name = name @@ -405,6 +444,7 @@ self.autostart = autostart self.statuschange = statuschange self.evaluator = evaluator + self.website = website def Loop(self): while self.continueloop: @@ -420,7 +460,7 @@ def Start(self): pyro.initServer() self.daemon=pyro.Daemon(host=self.ip, port=self.port) - self.plcobj = PLCObject(self.workdir, self.daemon, self.argv, self.statuschange, self.evaluator) + self.plcobj = PLCObject(self.workdir, self.daemon, self.argv, self.statuschange, self.evaluator, self.website) uri = self.daemon.connect(self.plcobj,"PLCObject") print "The daemon runs on port :",self.port @@ -447,12 +487,165 @@ self.servicepublisher.UnRegisterService() del self.servicepublisher self.daemon.shutdown(True) - + +if enabletwisted: + try: + if havewx: + from twisted.internet import wxreactor + wxreactor.install() + from twisted.internet import reactor, task + from twisted.python import log, util + from nevow import rend, appserver, inevow, tags, loaders, athena + from nevow.page import renderer + + havetwisted = True + except: + havetwisted = False + +if havetwisted: + + xhtml_header = ''' + +''' + + + class DefaultPLCStartedHMI(athena.LiveElement): + docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[ + tags.h1["PLC IS NOW STARTED"], + ]) + class PLCStoppedHMI(athena.LiveElement): + docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[ + tags.h1["PLC IS STOPPED"] + ]) + + class MainPage(athena.LiveElement): + jsClass = u"WebInterface.PLC" + docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[ + tags.div(id='content')[ + tags.div(render = tags.directive('PLCElement')), + ]]) + + def __init__(self, *a, **kw): + athena.LiveElement.__init__(self, *a, **kw) + self.pcl_state = False + self.HMI = None + self.resetPLCStartedHMI() + + def setPLCState(self, state): + self.pcl_state = state + if self.HMI is not None: + self.callRemote('updateHMI') + + def setPLCStartedHMI(self, hmi): + self.PLCStartedHMIClass = hmi + + def resetPLCStartedHMI(self): + self.PLCStartedHMIClass = DefaultPLCStartedHMI + + def getHMI(self): + return self.HMI + + def HMIexec(self, function, *args, **kwargs): + if self.HMI is not None: + getattr(self.HMI, function, lambda:None)(*args, **kwargs) + athena.expose(HMIexec) + + def resetHMI(self): + self.HMI = None + + def PLCElement(self, ctx, data): + return self.getPLCElement() + renderer(PLCElement) + + def getPLCElement(self): + self.detachFragmentChildren() + if self.pcl_state: + f = self.PLCStartedHMIClass() + else: + f = PLCStoppedHMI() + f.setFragmentParent(self) + self.HMI = f + return f + athena.expose(getPLCElement) + + def detachFragmentChildren(self): + for child in self.liveFragmentChildren[:]: + child.detach() + + class WebInterface(athena.LivePage): + + docFactory = loaders.stan([tags.raw(xhtml_header), + tags.html(xmlns="http://www.w3.org/1999/xhtml")[ + tags.head(render=tags.directive('liveglue')), + tags.body[ + tags.div[ + tags.div( render = tags.directive( "MainPage" )) + ]]]]) + MainPage = MainPage() + + def __init__(self, plcState=False, *a, **kw): + super(WebInterface, self).__init__(*a, **kw) + self.jsModules.mapping[u'WebInterface'] = util.sibpath(__file__, 'webinterface.js') + self.plcState = plcState + self.MainPage.setPLCState(plcState) + + def getHMI(self): + return self.MainPage.getHMI() + + def LoadHMI(self, hmi, jsmodules): + for name, path in jsmodules.iteritems(): + self.jsModules.mapping[name] = os.path.join(WorkingDir, path) + self.MainPage.setPLCStartedHMI(hmi) + + def UnLoadHMI(self): + self.MainPage.resetPLCStartedHMI() + + def PLCStarted(self): + self.plcState = True + self.MainPage.setPLCState(True) + + def PLCStopped(self): + self.plcState = False + self.MainPage.setPLCState(False) + + def renderHTTP(self, ctx): + """ + Force content type to fit with SVG + """ + req = inevow.IRequest(ctx) + req.setHeader('Content-type', 'application/xhtml+xml') + return super(WebInterface, self).renderHTTP(ctx) + + def render_MainPage(self, ctx, data): + f = self.MainPage + f.setFragmentParent(self) + return ctx.tag[f] + + def child_(self, ctx): + self.MainPage.detachFragmentChildren() + return WebInterface(plcState=self.plcState) + + def beforeRender(self, ctx): + d = self.notifyOnDisconnect() + d.addErrback(self.disconnected) + + def disconnected(self, reason): + self.MainPage.resetHMI() + #print reason + #print "We will be called back when the client disconnects" + + if havewx: + reactor.registerWxApp(app) + res = WebInterface() + site = appserver.NevowSite(res) + reactor.listenTCP(8009, site) +else: + res = None if havewx: from threading import Semaphore wx_eval_lock = Semaphore(0) - app=wx.App(redirect=False) mythread = currentThread() def statuschange(status): @@ -477,12 +670,17 @@ wx_eval_lock.acquire() return eval_res - pyroserver = Server(name, ip, port, WorkingDir, argv, autostart, statuschange, evaluator) + pyroserver = Server(name, ip, port, WorkingDir, argv, autostart, statuschange, evaluator, res) taskbar_instance = BeremizTaskBarIcon(pyroserver) pyro_thread=Thread(target=pyroserver.Loop) pyro_thread.start() +else: + pyroserver = Server(name, ip, port, WorkingDir, argv, autostart, website=res) + +if havetwisted: + reactor.run() +elif havewx: app.MainLoop() else: - pyroserver = Server(name, ip, port, WorkingDir, argv, autostart) pyroserver.Loop() diff -r 75ae46b66315 -r 71c441104cac PythonSTC.py --- a/PythonSTC.py Wed Aug 12 16:23:59 2009 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,596 +0,0 @@ -import keyword -import os -import wx -import wx.stc as stc - -#---------------------------------------------------------------------- - -""" -This Python editor class comes from the wxPython demo, a bit tweaked -""" - -#---------------------------------------------------------------------- - - -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, - } - - -#---------------------------------------------------------------------- - -class PythonSTC(stc.StyledTextCtrl): - - fold_symbols = 2 - - def __init__(self, parent, ID, - pos=wx.DefaultPosition, size=wx.DefaultSize, - style=0): - stc.StyledTextCtrl.__init__(self, parent, ID, pos, size, style) - - 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_PYTHON) - self.SetKeyWords(0, " ".join(keyword.kwlist)) - - 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:%(helv)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:%(helv)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") - - # Python styles - # Default - self.StyleSetSpec(stc.STC_P_DEFAULT, "fore:#000000,face:%(helv)s,size:%(size)d" % faces) - # Comments - self.StyleSetSpec(stc.STC_P_COMMENTLINE, "fore:#007F00,face:%(other)s,size:%(size)d" % faces) - # Number - self.StyleSetSpec(stc.STC_P_NUMBER, "fore:#007F7F,size:%(size)d" % faces) - # String - self.StyleSetSpec(stc.STC_P_STRING, "fore:#7F007F,face:%(helv)s,size:%(size)d" % faces) - # Single quoted string - self.StyleSetSpec(stc.STC_P_CHARACTER, "fore:#7F007F,face:%(helv)s,size:%(size)d" % faces) - # Keyword - self.StyleSetSpec(stc.STC_P_WORD, "fore:#00007F,bold,size:%(size)d" % faces) - # Triple quotes - self.StyleSetSpec(stc.STC_P_TRIPLE, "fore:#7F0000,size:%(size)d" % faces) - # Triple double quotes - self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, "fore:#7F0000,size:%(size)d" % faces) - # Class name definition - self.StyleSetSpec(stc.STC_P_CLASSNAME, "fore:#0000FF,bold,underline,size:%(size)d" % faces) - # Function or method name definition - self.StyleSetSpec(stc.STC_P_DEFNAME, "fore:#007F7F,bold,size:%(size)d" % faces) - # Operators - self.StyleSetSpec(stc.STC_P_OPERATOR, "bold,size:%(size)d" % faces) - # Identifiers - self.StyleSetSpec(stc.STC_P_IDENTIFIER, "fore:#000000,face:%(helv)s,size:%(size)d" % faces) - # Comment-blocks - self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, "fore:#7F7F7F,size:%(size)d" % faces) - # End of line where string is not closed - self.StyleSetSpec(stc.STC_P_STRINGEOL, "fore:#000000,face:%(mono)s,back:#E0C0E0,eol,size:%(size)d" % faces) - - self.SetCaretForeground("BLUE") - - def OnKeyPressed(self, event): - if self.CallTipActive(): - self.CallTipCancel() - - event.Skip() -## For later use -# key = event.GetKeyCode() -# if key == 32 and event.ControlDown(): -# pos = self.GetCurrentPos() -# -# # Tips -# if event.ShiftDown(): -# 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: -# #lst = [] -# #for x in range(50000): -# # lst.append('%05d' % x) -# #st = " ".join(lst) -# #print len(st) -# #self.AutoCompShow(0, st) -# -# kw = keyword.kwlist[:] -# kw.append("zzzzzz?2") -# kw.append("aaaaa?2") -# kw.append("__init__?3") -# kw.append("zzaaaaa?2") -# kw.append("zzbaaaa?2") -# kw.append("this_is_a_longer_value") -# #kw.append("this_is_a_much_much_much_much_much_much_much_longer_value") -# -# kw.sort() # Python sorts are case sensitive -# self.AutoCompSetIgnoreCase(False) # so this needs to match -# -# # Images are specified with a appended "?type" -# for i in range(len(kw)): -# if kw[i] in keyword.kwlist: -# kw[i] = kw[i] + "?1" -# -# self.AutoCompShow(0, " ".join(kw)) -# else: -# 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 - - -#---------------------------------------------------------------------- -class PythonCodeEditor(PythonSTC): - def __init__(self, parent): - PythonSTC.__init__(self, parent, -1, style=wx.BORDER_NONE) - self.SetUpEditor() - - # Some methods to make it compatible with how the wxTextCtrl is used - def SetValue(self, value): - if wx.USE_UNICODE: - value = value.decode('utf-8') - self.SetText(value) - self.EmptyUndoBuffer() - self.SetSavePoint() - - def IsModified(self): - return self.GetModify() - - def Clear(self): - self.ClearAll() - - def SetInsertionPoint(self, pos): - self.SetCurrentPos(pos) - self.SetAnchor(pos) - - def ShowPosition(self, pos): - line = self.LineFromPosition(pos) - #self.EnsureVisible(line) - self.GotoLine(line) - - def GetLastPosition(self): - return self.GetLength() - - def GetPositionFromLine(self, line): - return self.PositionFromLine(line) - - def GetRange(self, start, end): - return self.GetTextRange(start, end) - - def GetSelection(self): - return self.GetAnchor(), self.GetCurrentPos() - - def SetSelection(self, start, end): - self.SetSelectionStart(start) - self.SetSelectionEnd(end) - - def SelectLine(self, line): - start = self.PositionFromLine(line) - end = self.GetLineEndPosition(line) - self.SetSelection(start, end) - - def SetUpEditor(self): - """ - This method carries out the work of setting up the demo editor. - It's seperate so as not to clutter up the init code. - """ - import keyword - - self.SetLexer(stc.STC_LEX_PYTHON) - self.SetKeyWords(0, " ".join(keyword.kwlist)) - - # Enable folding - self.SetProperty("fold", "1" ) - - # Highlight tab/space mixing (shouldn't be any) - self.SetProperty("tab.timmy.whinge.level", "1") - - # Set left and right margins - self.SetMargins(2,2) - - # Set up the numbers in the margin for margin #1 - self.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER) - # Reasonable value for, say, 4-5 digits using a mono font (40 pix) - self.SetMarginWidth(1, 40) - - # Indentation and tab stuff - self.SetIndent(4) # Proscribed indent size for wx - self.SetIndentationGuides(True) # Show indent guides - self.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space - self.SetTabIndents(True) # Tab key indents - self.SetTabWidth(4) # Proscribed tab size for wx - self.SetUseTabs(False) # Use spaces rather than tabs, or - # TabTimmy will complain! - # White space - self.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.SetEOLMode(wx.stc.STC_EOL_LF) - self.SetViewEOL(False) - - # No right-edge mode indicator - self.SetEdgeMode(stc.STC_EDGE_NONE) - - # Setup a margin to hold fold markers - self.SetMarginType(2, stc.STC_MARGIN_SYMBOL) - self.SetMarginMask(2, stc.STC_MASK_FOLDERS) - self.SetMarginSensitive(2, True) - self.SetMarginWidth(2, 12) - - # and now set up the fold markers - self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "black") - self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "black") - self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "black") - self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "black") - self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "black") - self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "black") - self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "black") - - # Global default style - if wx.Platform == '__WXMSW__': - self.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.StyleSetSpec(stc.STC_STYLE_DEFAULT, - 'fore:#000000,back:#FFFFFF,face:Monaco') - else: - defsize = wx.SystemSettings.GetFont(wx.SYS_ANSI_FIXED_FONT).GetPointSize() - self.StyleSetSpec(stc.STC_STYLE_DEFAULT, - 'fore:#000000,back:#FFFFFF,face:Courier,size:%d'%defsize) - - # Clear styles and revert to default. - self.StyleClearAll() - - # Following style specs only indicate differences from default. - # The rest remains unchanged. - - # Line numbers in margin - self.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2') - # Highlighted brace - self.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00') - # Unmatched brace - self.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000') - # Indentation guide - self.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD") - - # Python styles - self.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000') - # Comments - self.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, 'fore:#008000,back:#F0FFF0') - self.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0') - # Numbers - self.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080') - # Strings and characters - self.StyleSetSpec(wx.stc.STC_P_STRING, 'fore:#800080') - self.StyleSetSpec(wx.stc.STC_P_CHARACTER, 'fore:#800080') - # Keywords - self.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold') - # Triple quotes - self.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA') - self.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA') - # Class names - self.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold') - # Function names - self.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold') - # Operators - self.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.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, 'fore:#000000') - - # Caret color - self.SetCaretForeground("BLUE") - # Selection background - self.SetSelBackground(1, '#66CCFF') - - self.SetSelBackground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)) - self.SetSelForeground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)) - - def RegisterModifiedEvent(self, eventHandler): - self.Bind(wx.stc.EVT_STC_CHANGE, eventHandler) - - -class PythonCodePanel(wx.Panel): - """Panel for the 'Demo Code' tab""" - def __init__(self, parent, mainFrame): - wx.Panel.__init__(self, parent, size=(1,1)) - self.mainFrame = mainFrame - self.editor = PythonCodeEditor(self) - self.editor.RegisterModifiedEvent(self.OnCodeModified) - - self.btnSave = wx.Button(self, -1, "Save") - self.btnRestore = wx.Button(self, -1, "Restore") - self.btnSave.Enable(False) - self.btnSave.Bind(wx.EVT_BUTTON, self.OnSave) - self.btnRestore.Bind(wx.EVT_BUTTON, self.OnRestore) - - self.controlBox = wx.BoxSizer(wx.HORIZONTAL) - self.controlBox.Add(self.btnSave, 0, wx.RIGHT, 5) - self.controlBox.Add(self.btnRestore, 0) - - self.box = wx.BoxSizer(wx.VERTICAL) - self.box.Add(self.controlBox, 0, wx.EXPAND) - self.box.Add(wx.StaticLine(self), 0, wx.EXPAND) - self.box.Add(self.editor, 1, wx.EXPAND) - - self.box.Fit(self) - self.SetSizer(self.box) - - self.sourceFile = None - - self.Bind(wx.EVT_MENU, self.OnSave, id=wx.ID_SAVE) - accel = wx.AcceleratorTable([wx.AcceleratorEntry(wx.ACCEL_CTRL, 83, wx.ID_SAVE)]) - self.SetAcceleratorTable(accel) - - # Loads from a file object - def LoadSourceFile(self, filename): - self.sourceFile = filename - if os.path.exists(filename): - self.LoadSource(file(filename).read()) - - def LoadSource(self, source): - self.editor.Clear() - self.editor.SetValue(source) - self.JumpToLine(0) - self.btnSave.Enable(False) - - def JumpToLine(self, line, highlight=False): - self.editor.GotoLine(line) - self.editor.SetFocus() - if highlight: - self.editor.SelectLine(line) - - def OnCodeModified(self, event): - self.btnSave.Enable(self.editor.IsModified()) - # TODO : add callback - - def OnSave(self, event): - overwriteMsg = "You are about to overwrite that file\n" + \ - "Do you want to continue?" - dlg = wx.MessageDialog(self, overwriteMsg, "wxPython Demo", - wx.YES_NO | wx.NO_DEFAULT| wx.ICON_EXCLAMATION) - result = dlg.ShowModal() - if result == wx.ID_NO: - return - dlg.Destroy() - - source = self.editor.GetText().encode("utf-8") - - f = file(self.sourceFile, "w") - f.write(source) - f.close() - - # TODO - #self.mainFrame.SetTreeModified(True) - - - def OnRestore(self, event): - self.LoadSourceFile(self.sourceFile) - self.btnSave.Enable(self.editor.IsModified()) diff -r 75ae46b66315 -r 71c441104cac Zeroconf.py --- a/Zeroconf.py Wed Aug 12 16:23:59 2009 -0600 +++ b/Zeroconf.py Thu Aug 13 11:37:38 2009 +0200 @@ -596,10 +596,10 @@ next = off + 1 off = ((len & 0x3F) << 8) | ord(self.data[off]) if off >= first: - raise "Bad domain name (circular) at " + str(off) + raise _("Bad domain name (circular) at ") + str(off) first = off else: - raise "Bad domain name at " + str(off) + raise _("Bad domain name at ") + str(off) if next >= 0: self.offset = next diff -r 75ae46b66315 -r 71c441104cac connectors/PYRO/__init__.py --- a/connectors/PYRO/__init__.py Wed Aug 12 16:23:59 2009 -0600 +++ b/connectors/PYRO/__init__.py Thu Aug 13 11:37:38 2009 +0200 @@ -28,7 +28,7 @@ """ This returns the connector to Pyro style PLCobject """ - pluginsroot.logger.write("Connecting to URI : %s\n"%uri) + pluginsroot.logger.write(_("Connecting to URI : %s\n")%uri) servicetype, location = uri.split("://") @@ -36,7 +36,7 @@ try : RemotePLCObjectProxy = pyro.getAttrProxyForURI("PYROLOC://"+location+"/PLCObject") except Exception, msg: - pluginsroot.logger.write_error("Wrong URI, please check it !\n") + pluginsroot.logger.write_error(_("Wrong URI, please check it !\n")) pluginsroot.logger.write_error(traceback.format_exc()) return None @@ -58,7 +58,7 @@ # 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") + pluginsroot.logger.write_error(_("Cannot get PLC status - connection failed.\n")) return None @@ -90,7 +90,7 @@ 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.logger.write(_("Force runtime reload\n")) pluginsroot._connector.GetPyroProxy().ForceReload() pluginsroot._Disconnect() # let remote PLC time to resurect.(freeze app) diff -r 75ae46b66315 -r 71c441104cac discovery.py --- a/discovery.py Wed Aug 12 16:23:59 2009 -0600 +++ b/discovery.py Thu Aug 13 11:37:38 2009 +0200 @@ -33,7 +33,7 @@ listmix.ListCtrlAutoWidthMixin.__init__(self) class DiscoveryDialog(wx.Dialog, listmix.ColumnSorterMixin): - def __init__(self, parent, id=-1, title='Service Discovery'): + def __init__(self, parent, id=-1, title=_('Service Discovery')): self.my_result=None wx.Dialog.__init__(self, parent, id, title, size=(600,600), style=wx.DEFAULT_DIALOG_STYLE) @@ -67,7 +67,7 @@ # set up buttons local_id = wx.NewId() - b = wx.Button(self, local_id, "Refresh") + b = wx.Button(self, local_id, _("Refresh")) self.Bind(wx.EVT_BUTTON, self.OnRefreshButton, b) btsizer.Add(b) @@ -75,18 +75,18 @@ btsizer.AddGrowableCol(1) local_id = wx.NewId() - b = wx.Button(self, local_id, "Local") + b = wx.Button(self, local_id, _("Local")) self.Bind(wx.EVT_BUTTON, self.ChooseLocalID, b) btsizer.Add(b) btsizer.AddSpacer(0) btsizer.AddGrowableCol(3) - b = wx.Button(self, wx.ID_CANCEL, "Cancel") + b = wx.Button(self, wx.ID_CANCEL, _("Cancel")) self.Bind(wx.EVT_BUTTON, self.OnCancel, b) btsizer.Add(b) - b = wx.Button(self, wx.ID_OK, "OK") + b = wx.Button(self, wx.ID_OK, _("OK")) self.Bind(wx.EVT_BUTTON, self.OnOk, b) b.SetDefault() btsizer.Add(b) diff -r 75ae46b66315 -r 71c441104cac i18n/Beremiz_fr_FR.po --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/i18n/Beremiz_fr_FR.po Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,954 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-06-24 18:44+0200\n" +"PO-Revision-Date: 2009-07-02 18:53+0100\n" +"Last-Translator: \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: Beremiz.py:1429 +#, python-format +msgid "" +"\n" +"An unhandled exception (bug) occured. Bug report saved at :\n" +"(%s)\n" +"\n" +"Please contact LOLITech at:\n" +"+33 (0)3 29 57 60 42\n" +"or please be kind enough to send this file to:\n" +"bugs_beremiz@lolitech.fr\n" +"\n" +"You should now restart Beremiz.\n" +"\n" +"Traceback:\n" +msgstr "" +"\n" +"Une erreur inconnue (bug) est apparu. Le rapport d'erreur a été sauvé dans :\n" +"(%s)\n" +"\n" +"Veuillez contacter LOLITech au :\n" +"+33 (0)3 29 57 60 42\n" +"ou envoyez ce fichier à l'adresse :\n" +"bugs_beremiz@lolitech.fr\n" +"\n" +"Vous devriez redémarrer Beremiz.\n" +"\n" +"Origine :\n" + +#: plugger.py:1332 +msgid " generation failed !\n" +msgstr ": la construction a échouée !\n" + +#: Beremiz.py:1288 +#, python-format +msgid "\"%s\" folder is not a valid Beremiz project\n" +msgstr "Le dossier \"%s\" ne contient pas de projet Beremiz valide\n" + +#: Beremiz_service.py:467 +#: runtime/PLCObject.py:269 +msgid "#EXCEPTION : " +msgstr "#EXCEPTION : " + +#: Beremiz.py:1417 +#: Beremiz.py:1419 +#: Beremiz.py:1420 +msgid ", " +msgstr ", " + +#: Beremiz.py:1415 +msgid ". " +msgstr ". " + +#: plugger.py:395 +#, python-format +msgid "A child names \"%s\" already exist -> \"%s\"\n" +msgstr "" + +#: plugger.py:427 +#, python-format +msgid "A child with IEC channel %d already exist -> %d\n" +msgstr "" + +#: Beremiz.py:342 +msgid "About" +msgstr "A propos" + +#: Beremiz.py:1357 +msgid "About Beremiz" +msgstr "A propos de Beremiz" + +#: Beremiz.py:311 +#: Beremiz.py:1390 +msgid "Add Plugin" +msgstr "Ajouter un plugin" + +#: Beremiz.py:612 +#: Beremiz.py:874 +msgid "Add a sub plugin" +msgstr "Ajouter un sous plugin" + +#: plugger.py:1680 +msgid "Already connected. Please disconnect\n" +msgstr "Déjà connecté. Veuillez déconnecter\n" + +#: Beremiz.py:1056 +msgid "Append " +msgstr "Ajouter " + +#: plugins/canfestival/config_utils.py:341 +#: plugins/canfestival/config_utils.py:623 +#, python-format +msgid "Bad location size : %s" +msgstr "Mauvaise taille d'adresse : %s" + +#: Beremiz.py:392 +msgid "Beremiz" +msgstr "Beremiz" + +#: Beremiz.py:340 +msgid "Beremiz\tF1" +msgstr "Beremiz\tF1" + +#: plugger.py:1464 +msgid "Broken" +msgstr "Cassé" + +#: plugger.py:1800 +msgid "Build" +msgstr "Compiler" + +#: Beremiz.py:320 +msgid "Build\tCTRL+R" +msgstr "Compiler\tCTRL+R" + +#: plugger.py:1434 +msgid "Build directory already clean\n" +msgstr "Le répertoire de compilation est déjà nettoyé\n" + +#: plugger.py:1801 +msgid "Build project into build folder" +msgstr "Compiler le projet dans le répertoire ce compilation" + +#: plugger.py:1350 +msgid "C Build crashed !\n" +msgstr "La compilation du C a mal fonctionné !\n" + +#: plugger.py:1347 +msgid "C Build failed.\n" +msgstr "La compilation du C a échouée !\n" + +#: plugger.py:1336 +msgid "C code generated successfully.\n" +msgstr "Code C généré avec succès.\n" + +#: targets/toolchain_gcc.py:119 +#, python-format +msgid "C compilation of %s failed.\n" +msgstr "La compilation C de %s a échouée.\n" + +#: plugger.py:1037 +#, python-format +msgid "Can't find module for target %s!\n" +msgstr "Impossible de trouver le module correspondant à la cible %s !\n" + +#: discovery.py:79 +msgid "Cancel" +msgstr "Annuler" + +#: plugger.py:1746 +msgid "Cannot compare latest build to target. Please build.\n" +msgstr "Impossible de comparer la cible avec la dernière compilation. Veuillez compiler le projet.\n" + +#: plugger.py:465 +#, python-format +msgid "Cannot create child %s of type %s " +msgstr "Impossible d'ajouter un élément \"%s\" de type \"%s\"" + +#: plugger.py:420 +#, python-format +msgid "Cannot find lower free IEC channel than %d\n" +msgstr "Impossible de trouver un numéro IEC inférieur à %d libre\n" + +#: connectors/PYRO/__init__.py:61 +msgid "Cannot get PLC status - connection failed.\n" +msgstr "Impossible d'obtenir le statut de l'automate - la connecxion a échoué.\n" + +#: plugger.py:1161 +msgid "Cannot open/parse VARIABLES.csv!\n" +msgstr "Impossible d'ouvrir ou d'analyser le fichier VARIABLES.csv !\n" + +#: plugins/canfestival/config_utils.py:371 +#, python-format +msgid "Cannot set bit offset for non bool '%s' variable (ID:%d,Idx:%x,sIdx:%x))" +msgstr "" + +#: Beremiz_service.py:281 +msgid "Change IP of interface to bind" +msgstr "Changer l'adresse IP de l'interface à lier" + +#: Beremiz_service.py:280 +msgid "Change Name" +msgstr "Changer le nom" + +#: Beremiz_service.py:284 +msgid "Change Port Number" +msgstr "Changer le numéro de port" + +#: Beremiz_service.py:286 +msgid "Change working directory" +msgstr "Changer le dossier de travail" + +#: Beremiz.py:1249 +#: Beremiz.py:1272 +msgid "Choose a project" +msgstr "Choisissez un projet" + +#: Beremiz_service.py:332 +msgid "Choose a working directory " +msgstr "Choisissez un dossier de travail" + +#: plugger.py:1804 +msgid "Clean" +msgstr "Nettoyer" + +#: plugger.py:1806 +msgid "Clean project build folder" +msgstr "Nettoyer le répertoire de compilation" + +#: plugger.py:1431 +msgid "Cleaning the build directory\n" +msgstr "Répertoire de compilation en cours de nettoyage\n" + +#: Beremiz.py:524 +#: Beremiz.py:1299 +msgid "Close Application" +msgstr "Fermer l'application" + +#: Beremiz.py:292 +msgid "Close Project" +msgstr "Fermer le projet" + +#: plugger.py:963 +msgid "Compiling IEC Program in to C code...\n" +msgstr "Compilation du program en IEC vers du code C en cours...\n" + +#: plugins/canfestival/config_utils.py:335 +#: plugins/canfestival/config_utils.py:617 +#, python-format +msgid "Conflict type for location \"%s\"" +msgstr "Conflit entre types pour l'adresse \"%s\"" + +#: plugger.py:1828 +msgid "Connect" +msgstr "Connecter" + +#: plugger.py:1829 +msgid "Connect to the target PLC" +msgstr "Connecter à l'automate cible" + +#: connectors/PYRO/__init__.py:31 +#, python-format +msgid "Connecting to URI : %s\n" +msgstr "Connection à l'URI %s en cours...\n" + +#: plugger.py:1713 +#, python-format +msgid "Connection failed to %s!\n" +msgstr "La connection à \"%s\" a échouée !\n" + +#: plugger.py:581 +#, python-format +msgid "" +"Could not add child \"%s\", type %s :\n" +"%s\n" +msgstr "" + +#: plugger.py:558 +#, python-format +msgid "" +"Couldn't load plugin base parameters %s :\n" +" %s" +msgstr "" +"Impossible de charger les paramètres de base du plugin %s :\n" +" %s" + +#: plugger.py:569 +#, python-format +msgid "" +"Couldn't load plugin parameters %s :\n" +" %s" +msgstr "" +"Impossible de charger les paramètres du plugin %s :\n" +" %s" + +#: plugger.py:1644 +msgid "Couldn't start PLC debug !\n" +msgstr "Impossible d'arrêter le débogage de l'automate !\n" + +#: plugger.py:1674 +msgid "Couldn't stop PLC !\n" +msgstr "Impossible d'arrêter l'automate !\n" + +#: plugger.py:1814 +msgid "Debug" +msgstr "Déboguer" + +#: plugger.py:1514 +#, python-format +msgid "Debug : Unknown variable %s\n" +msgstr "Débogage : variable \"%s\" inconnue\n" + +#: plugger.py:1622 +msgid "Debug Thread couldn't be killed" +msgstr "Le thread de débogage n'a pu être détruit" + +#: plugger.py:1609 +#, python-format +msgid "Debug data not coherent %d != %d\n" +msgstr "Les données de débogage ne sont pas cohérentes %d != %d\n" + +#: runtime/PLCObject.py:424 +#, python-format +msgid "Debug error idx : %d, expected_idx %d, type : %s" +msgstr "" + +#: plugger.py:1614 +msgid "Debugger disabled\n" +msgstr "Débogueur désactivé\n" + +#: Beremiz.py:313 +msgid "Delete Plugin" +msgstr "Supprimer un plugin" + +#: Beremiz.py:865 +msgid "Delete this plugin" +msgstr "Supprimer ce plugin" + +#: plugger.py:1461 +msgid "Dirty" +msgstr "Corrompu" + +#: plugger.py:1837 +msgid "Disconnect" +msgstr "Déconnecter" + +#: plugger.py:1839 +msgid "Disconnect from PLC" +msgstr "Déconnecter l'automate" + +#: plugger.py:1467 +msgid "Disconnected" +msgstr "Déconnecté" + +#: PythonSTC.py:576 +msgid "Do you want to continue?" +msgstr "Voulez-vous continuer ?" + +#: Beremiz.py:1261 +msgid "ERROR" +msgstr "ERREUR" + +#: plugins/c_ext/c_ext.py:204 +#: plugins/c_ext/c_ext.py:205 +msgid "Edit C File" +msgstr "Editer le fichier C" + +#: plugins/canfestival/canfestival.py:200 +msgid "Edit CanOpen Network with NetworkEdit" +msgstr "Editer le réseau CANOpen à l'aide de NetworkEdit" + +#: plugger.py:1796 +msgid "Edit PLC" +msgstr "Editer l'automate" + +#: Beremiz.py:308 +msgid "Edit PLC\tCTRL+R" +msgstr "Editer l'automate\tCTRL+R" + +#: plugger.py:1797 +msgid "Edit PLC program with PLCOpenEditor" +msgstr "Editer le programme à l'aide de PLCOpenEditor" + +#: plugger.py:1856 +msgid "Edit a WxWidgets GUI with WXGlade" +msgstr "Editer une IHM WxWidgets à l'aide de WXGlade" + +#: plugins/canfestival/canfestival.py:199 +msgid "Edit network" +msgstr "Editer le réseau" + +#: plugger.py:1848 +msgid "Edit raw IEC code added to code generated by PLCGenerator" +msgstr "Editer le code IEC ajouté au code généré par PLCGenerator" + +#: plugger.py:1458 +msgid "Empty" +msgstr "Vide" + +#: Beremiz.py:815 +msgid "Enable/Disable this plugin" +msgstr "Activer/Désactiver le plugin" + +#: Beremiz_service.py:339 +msgid "Enter a name " +msgstr "Saisissez un nom" + +#: Beremiz_service.py:324 +msgid "Enter a port number " +msgstr "Saisissez un numéro de port" + +#: Beremiz_service.py:314 +msgid "Enter the ip of the interface to bind" +msgstr "Saisissez l'adresse IP de l'interface à lier" + +#: Beremiz.py:1284 +#: Beremiz.py:1288 +#: Beremiz.py:1443 +#: Beremiz.py:1453 +#: Beremiz_service.py:229 +#: Beremiz_service.py:353 +msgid "Error" +msgstr "Erreur" + +#: plugger.py:1010 +msgid "Error : At least one configuration and one ressource must be declared in PLC !\n" +msgstr "Erreur : Au moins une configuration ou une resource doit être déclaré dans l'automate !\n" + +#: plugger.py:1002 +#, python-format +msgid "Error : IEC to C compiler returned %d\n" +msgstr "Erreur : Le compilateur d'IEC en C a retourné %d\n" + +#: plugger.py:941 +#, python-format +msgid "" +"Error in ST/IL/SFC code generator :\n" +"%s\n" +msgstr "" +"Erreur dans le générateur de code ST/IL/SFC :\n" +"%s\n" + +#: plugger.py:202 +#, python-format +msgid "Error while saving \"%s\"\n" +msgstr "Erreur lors de l'enregistrement de \"%s\"\n" + +#: plugins/canfestival/canfestival.py:191 +msgid "Error: No Master generated\n" +msgstr "Erreur : Aucun maître généré\n" + +#: plugins/canfestival/canfestival.py:186 +msgid "Error: No PLC built\n" +msgstr "Erreur : Aucun automate compilé\n" + +#: plugger.py:1707 +#, python-format +msgid "Exception while connecting %s!\n" +msgstr "Une exception est apparu au cours de la connexion %s !\n" + +#: plugger.py:1014 +msgid "Extracting Located Variables...\n" +msgstr "Extraction des variables adressées en cours...\n" + +#: plugger.py:1761 +msgid "Failed : Must build before transfer.\n" +msgstr "Echec : Le projet doit être compilé avant d'être transféré.\n" + +#: plugger.py:1341 +msgid "Fatal : cannot get builder.\n" +msgstr "Erreur fatale : impossible de trouver un compilateur.\n" + +#: Beremiz.py:347 +msgid "File" +msgstr "Fichier" + +#: plugger.py:815 +msgid "Folder choosen doesn't contain a program. It's not a valid project!" +msgstr "Le répertoire ne contient pas de programme. Ce n'est pas un projet valide !" + +#: plugger.py:780 +msgid "Folder choosen isn't empty. You can't use it for a new project!" +msgstr "Le répertoire n'est pas vide. Vous ne pouvez pas l'utiliser pour créer un nouveau projet !" + +#: connectors/PYRO/__init__.py:93 +msgid "Force runtime reload\n" +msgstr "Redémarrage du runtime forcé\n" + +#: plugger.py:931 +msgid "Generating SoftPLC IEC-61131 ST/IL/SFC code...\n" +msgstr "Création du code ST/IL/SFC de l'automate IEC-61131 en cours...\n" + +#: plugger.py:1289 +msgid "Generating plugins C code\n" +msgstr "Création du code C des plugins en cours\n" + +#: Beremiz.py:350 +msgid "Help" +msgstr "Aide" + +#: plugger.py:1281 +msgid "IEC-61131-3 code generation failed !\n" +msgstr "La création du code IEC-61131-3 a échouée !\n" + +#: plugins/canfestival/config_utils.py:376 +#: plugins/canfestival/config_utils.py:637 +#, python-format +msgid "Invalid type \"%s\"-> %d != %d for location\"%s\"" +msgstr "Type invalide \"%s\"-> %d != %d pour cette adresse \"%s\"" + +#: Beremiz_service.py:315 +#: Beremiz_service.py:316 +msgid "Ip is not valid!" +msgstr "l'IP est invalide !" + +#: plugger.py:1767 +msgid "Latest build already match current target. Transfering anyway...\n" +msgstr "La dernière compilation correspond à la cible actuelle...\n" + +#: plugger.py:1737 +msgid "Latest build do not match with target, please transfer.\n" +msgstr "La dernière compilation ne correspond pas a la cible actuelle, veuillez transférer le programme.\n" + +#: plugger.py:1741 +msgid "Latest build match target, no transfer needed.\n" +msgstr "La dernière compilation correspond à la cible actuelle. il n'est pas nécessaire de transférer le programme.\n" + +#: Beremiz_service.py:283 +msgid "Launch WX GUI inspector" +msgstr "Lancer un inspecteur d'IHM WX" + +#: Beremiz_service.py:282 +msgid "Launch a live Python shell" +msgstr "Lancer une console Python" + +#: targets/toolchain_gcc.py:127 +msgid "Linking :\n" +msgstr "Linkage :\n" + +#: discovery.py:72 +msgid "Local" +msgstr "Local" + +#: Beremiz.py:435 +msgid "Log Console" +msgstr "Console de log" + +#: plugger.py:475 +#, python-format +msgid "Max count (%d) reached for this plugin of type %s " +msgstr "Nombre limite(%d) atteint pour les plugin de type %s" + +#: runtime/ServicePublisher.py:50 +msgid "My IP is :" +msgstr "Mon IP est :" + +#: Beremiz_service.py:340 +msgid "Name must not be null!" +msgstr "Le nom ne doit pas être vide !" + +#: Beremiz.py:286 +msgid "New\tCTRL+N" +msgstr "Nouveau\tCTRL+N" + +#: runtime/PLCObject.py:313 +#, python-format +msgid "NewPLC (%s)" +msgstr "Nouvel automate (%s)" + +#: plugger.py:1791 +msgid "No PLC to transfer (did build success ?)\n" +msgstr "Aucun automate à transférer (la compilation a-t-elle réussi ?)\n" + +#: Beremiz_service.py:353 +msgid "No runnning PLC" +msgstr "Aucun automate en cours d'exécution" + +#: plugins/canfestival/config_utils.py:632 +#, python-format +msgid "No such index/subindex (%x,%x) (variable %s)" +msgstr "indice et sous-indice inconnu (%x,%x) (variable %s)" + +#: plugins/canfestival/config_utils.py:361 +#, python-format +msgid "No such index/subindex (%x,%x) in ID : %d (variable %s)" +msgstr "indice et sous-indice inconnu (%x,%x) pour l'ID : %d (variable %s)" + +#: plugins/canfestival/config_utils.py:354 +#, python-format +msgid "Non existing node ID : %d (variable %s)" +msgstr "Le node ID n'existe pas : %d (variable %s)" + +#: plugins/canfestival/config_utils.py:383 +#, python-format +msgid "Not PDO mappable variable : '%s' (ID:%d,Idx:%x,sIdx:%x))" +msgstr "Variable non mappable dans un PDO : '%s' (ID:%d,Idx:%x,sIdx:%x))" + +#: discovery.py:83 +msgid "OK" +msgstr "Valider" + +#: Beremiz.py:288 +msgid "Open\tCTRL+O" +msgstr "Ouvrir\tCTRL+O" + +#: targets/toolchain_gcc.py:95 +msgid "PLC :\n" +msgstr "Automate :\n" + +#: plugger.py:1447 +#: plugger.py:1483 +#: plugger.py:1723 +#, python-format +msgid "PLC is %s\n" +msgstr "L'automate est dans l'état %s\n" + +#: Beremiz.py:1390 +msgid "Please enter a name for plugin:" +msgstr "Saisissez un nom pour le plugin :" + +#: runtime/PLCObject.py:219 +msgid "Please stop PLC to close" +msgstr "Veuillez arrêter l'automate pour quitter" + +#: targets/toolchain_gcc.py:93 +msgid "Plugin : " +msgstr "Plugin :" + +#: plugger.py:1295 +msgid "Plugins code generation failed !\n" +msgstr "La création du code des plugins a échoué !\n" + +#: Beremiz_service.py:325 +msgid "Port number must be 0 <= port <= 65535!" +msgstr "Le numéro de port doit être compris entre 0 et 65535 !" + +#: Beremiz_service.py:325 +msgid "Port number must be an integer!" +msgstr "Le numéro de port doit être un entier !" + +#: runtime/PLCObject.py:279 +#, python-format +msgid "Problem %s PLC" +msgstr "Problème lors du %s de l'automate" + +#: plugger.py:789 +msgid "Project not created" +msgstr "Le projet n'a pu être créé" + +#: plugger.py:503 +#, python-format +msgid "Project tree layout do not match plugin.xml %s!=%s " +msgstr "L'organisation du projet ne correspond pas à plugin.xml %s!=%s" + +#: Beremiz.py:295 +msgid "Properties" +msgstr "Propriétés" + +#: Beremiz_service.py:433 +msgid "Publish service on local network" +msgstr "Le service est publié sur le réseau local" + +#: plugger.py:1851 +msgid "Python code" +msgstr "Code Python" + +#: runtime/PLCObject.py:282 +msgid "PythonThreadProc interrupted" +msgstr "PythonThreadProc a été interrompu" + +#: PythonSTC.py:577 +msgid "Question" +msgstr "Question" + +#: Beremiz_service.py:287 +msgid "Quit" +msgstr "Quitter" + +#: Beremiz.py:298 +msgid "Quit\tCTRL+Q" +msgstr "Quitter\tCTRL+Q" + +#: plugger.py:1847 +msgid "Raw IEC code" +msgstr "Ajout code IEC" + +#: Beremiz.py:1398 +msgid "Really delete plugin ?" +msgstr "Voulez-vous réellement supprimer le plugin ?" + +#: discovery.py:64 +msgid "Refresh" +msgstr "Actualiser" + +#: Beremiz.py:1398 +msgid "Remove plugin" +msgstr "Enlever le plugin" + +#: Beremiz.py:325 +#: plugger.py:1809 +msgid "Run" +msgstr "Exécuter" + +#: Beremiz.py:290 +msgid "Save\tCTRL+S" +msgstr "Enregistrer\tCTRL+S" + +#: Beremiz.py:328 +msgid "Save Log" +msgstr "Enregistrer le log" + +#: Beremiz.py:523 +#: Beremiz.py:1298 +msgid "Save changes ?" +msgstr "Enregistrer les changements ?" + +#: discovery.py:37 +msgid "Service Discovery" +msgstr "Découverte de service" + +#: plugger.py:1844 +msgid "Show IEC code generated by PLCGenerator" +msgstr "Afficher le code IEC généré par PLCGenerator" + +#: plugins/canfestival/canfestival.py:202 +msgid "Show Master" +msgstr "Afficher le maître" + +#: plugins/canfestival/canfestival.py:203 +msgid "Show Master generated by config_utils" +msgstr "Afficher le maître généré par config_utils" + +#: plugger.py:1842 +msgid "Show code" +msgstr "Afficher le code" + +#: Beremiz.py:323 +msgid "Simulate" +msgstr "Simuler" + +#: plugger.py:1811 +#: Beremiz_service.py:278 +#: runtime/PLCObject.py:285 +msgid "Start PLC" +msgstr "Démarrer l'automate" + +#: plugger.py:1816 +msgid "Start PLC (debug mode)" +msgstr "Démarrer l'automate (en mode debug)" + +#: plugger.py:1273 +#, python-format +msgid "Start build in %s\n" +msgstr "Début de la compilation dans %s\n" + +#: plugger.py:1452 +msgid "Started" +msgstr "Démarré" + +#: plugger.py:1631 +msgid "Starting PLC (debug mode)\n" +msgstr "Démarrage de l'automate (en mode debug) en cours\n" + +#: plugger.py:1823 +msgid "Stop" +msgstr "Arrêter" + +#: Beremiz_service.py:279 +#: runtime/PLCObject.py:291 +msgid "Stop PLC" +msgstr "Arrêter l'automate" + +#: plugger.py:1825 +msgid "Stop Running PLC" +msgstr "Arrêter l'automate en cours d'exécution" + +#: plugger.py:1455 +msgid "Stopped" +msgstr "Arrêté" + +#: plugger.py:1670 +msgid "Stopping debug\n" +msgstr "Arrêt du débogage en cours\n" + +#: Beremiz_service.py:426 +msgid "The daemon runs on port :" +msgstr "Le service est disponible sur le port :" + +#: Beremiz_service.py:427 +msgid "The object's uri is :" +msgstr "L' URI de l'objet est :" + +#: Beremiz_service.py:428 +msgid "The working directory :" +msgstr "Le répertoire de travail :" + +#: plugger.py:1832 +msgid "Transfer" +msgstr "Transférer" + +#: plugger.py:1834 +msgid "Transfer PLC" +msgstr "Transférer l'automate" + +#: plugger.py:1787 +msgid "Transfer completed successfully.\n" +msgstr "Transfert effectué avec succès.\n" + +#: plugger.py:1789 +msgid "Transfer failed\n" +msgstr "Le transfert a échoué\n" + +#: targets/Xenomai/__init__.py:27 +msgid "Unable to get Xenomai's CFLAGS\n" +msgstr "Impossible d'obtenir les CFLAGS de Xenomai\n" + +#: targets/Xenomai/__init__.py:16 +msgid "Unable to get Xenomai's LDFLAGS\n" +msgstr "Impossible d'obtenir les LDFLAGS de Xenomai\n" + +#: plugger.py:1855 +msgid "WXGLADE GUI" +msgstr "IHM WXGlade" + +#: plugger.py:936 +msgid "Warnings in ST/IL/SFC code generator :\n" +msgstr "Mises en garde du generateur de code ST/IL/SFC :\n" + +#: plugger.py:1852 +msgid "Write Python runtime code, for use with python_eval FBs" +msgstr "Ecrivez le code Python du runtime, à utiliser avec les blocs python_eval" + +#: connectors/PYRO/__init__.py:39 +msgid "Wrong URI, please check it !\n" +msgstr "URI inconnue, veuillez vérifier l'adresse !\n" + +#: PythonSTC.py:575 +msgid "You are about to overwrite that file\n" +msgstr "Vous allez écraser ce fichier\n" + +#: wxPopen.py:134 +#, python-format +msgid "exited with status %s (pid %s)\n" +msgstr "a quitté avec le status %s (pid %s)\n" + +#: Beremiz.py:1417 +#: Beremiz.py:1419 +msgid "file : " +msgstr "fichier :" + +#: Beremiz.py:1420 +msgid "function : " +msgstr "fonction :" + +#: Beremiz.py:1420 +msgid "line : " +msgstr "ligne :" + +#: runtime/PLCObject.py:277 +msgid "loading" +msgstr "chargement" + +#: runtime/PLCObject.py:275 +msgid "starting" +msgstr "démarrage" + +#: Extra XSD strings +msgid "BaseParams" +msgstr "Paramètres de base" + +msgid "Name" +msgstr "Nom" + +msgid "IEC_Channel" +msgstr "Numéro IEC" + +msgid "Enabled" +msgstr "Actif" + +msgid "BeremizRoot" +msgstr "Racine de Beremiz" + +msgid "TargetType" +msgstr "Type de cible" + +msgid "URI_location" +msgstr "Adresse URI" + +msgid "Enable_Plugins" +msgstr "Plugins actifs" + +msgid "CExtension" +msgstr "Extension C" + +msgid "CFLAGS" +msgstr "CFLAGS" + +msgid "LDFLAGS" +msgstr "LDFLAGS" + +msgid "CanFestivalSlaveNode" +msgstr "Noeud esclave CanFestival" + +msgid "CAN_Device" +msgstr "Port CAN" + +msgid "CAN_Baudrate" +msgstr "Vitesse CAN" + +msgid "NodeId" +msgstr "NodeId" + +msgid "Sync_Align" +msgstr "Aligner sur synchro" + +msgid "Sync_Align_Ratio" +msgstr "Rapport d'alignement" + +msgid "CanFestivalNode" +msgstr "Noeud CanFestival" + +msgid "Sync_TPDOs" +msgstr "TPDOs sur synchro" + +msgid "CanFestivalInstance" +msgstr "Instance CanFestival" + +msgid "CAN_Driver" +msgstr "Driver CAN" + +msgid "Debug_mode" +msgstr "Mode de débogage" + +msgid "Compiler" +msgstr "Compileur" + +msgid "Linker" +msgstr "Linkeur" + +msgid "Linux" +msgstr "Linux" + +msgid "Rtai" +msgstr "Rtai" + +msgid "rtai_config" +msgstr "Config Rtai" + +msgid "Win32" +msgstr "Win32" + +msgid "Xenomai" +msgstr "Xenomai" + +msgid "XenoConfig" +msgstr "Config Xenomai" + diff -r 75ae46b66315 -r 71c441104cac i18n/Beremiz_zh_CN.po --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/i18n/Beremiz_zh_CN.po Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,989 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-06-24 18:44+0200\n" +"PO-Revision-Date: 2009-07-02 18:27+0100\n" +"Last-Translator: \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: Beremiz.py:1429 +#, python-format +msgid "" +"\n" +"An unhandled exception (bug) occured. Bug report saved at :\n" +"(%s)\n" +"\n" +"Please contact LOLITech at:\n" +"+33 (0)3 29 57 60 42\n" +"or please be kind enough to send this file to:\n" +"bugs_beremiz@lolitech.fr\n" +"\n" +"You should now restart Beremiz.\n" +"\n" +"Traceback:\n" +msgstr "" +"\n" +"一个未处理的异常(漏洞)出现。漏洞报告存为:\n" +"(%s)\n" +"\n" +"请用以下方式联系LOLITech:\n" +"+33 (0)3 29 57 60 42\n" +"或者请将文件发送至下列邮箱:\n" +"bugs_beremiz@lolitech.fr\n" +"\n" +"你现在必须重新启动Beremiz。\n" +"\n" +"回溯:\n" + +#: plugger.py:1332 +msgid " generation failed !\n" +msgstr "生成失败!\n" + +#: Beremiz.py:1288 +#, python-format +msgid "\"%s\" folder is not a valid Beremiz project\n" +msgstr "\"%s\" 文件夹不是有效的Beremiz项目\n" + +#: Beremiz_service.py:467 +#: runtime/PLCObject.py:269 +msgid "#EXCEPTION : " +msgstr "#异常:" + +#: Beremiz.py:1417 +#: Beremiz.py:1419 +#: Beremiz.py:1420 +msgid ", " +msgstr "," + +#: Beremiz.py:1415 +msgid ". " +msgstr "。" + +#: plugger.py:395 +#, python-format +msgid "A child names \"%s\" already exist -> \"%s\"\n" +msgstr "分支名字 \"%s\" 已经存在 -> \"%s\"\n" + +#: plugger.py:427 +#, python-format +msgid "A child with IEC channel %d already exist -> %d\n" +msgstr "一个IEC通道的分支 %d 已经存在 -> %d\n" + +#: Beremiz.py:342 +msgid "About" +msgstr "关于" + +#: Beremiz.py:1357 +msgid "About Beremiz" +msgstr "关于Beremiz" + +#: Beremiz.py:311 +#: Beremiz.py:1390 +msgid "Add Plugin" +msgstr "添加插件" + +#: Beremiz.py:612 +#: Beremiz.py:874 +msgid "Add a sub plugin" +msgstr "添加一个子插件" + +#: plugger.py:1680 +msgid "Already connected. Please disconnect\n" +msgstr "已经连接。请断开连接\n" + +#: Beremiz.py:1056 +msgid "Append " +msgstr "追加" + +#: plugins/canfestival/config_utils.py:341 +#: plugins/canfestival/config_utils.py:623 +#, python-format +msgid "Bad location size : %s" +msgstr "不好的位置大小:%s" + +#: Beremiz.py:392 +msgid "Beremiz" +msgstr "Beremiz" + +#: Beremiz.py:340 +msgid "Beremiz\tF1" +msgstr "Beremiz\tF1" + +#: plugger.py:1464 +msgid "Broken" +msgstr "损坏" + +#: plugger.py:1800 +msgid "Build" +msgstr "构建" + +#: Beremiz.py:320 +msgid "Build\tCTRL+R" +msgstr "建立\tCTRL+R" + +#: plugger.py:1434 +msgid "Build directory already clean\n" +msgstr "构建目录已经清除\n" + +#: plugger.py:1801 +msgid "Build project into build folder" +msgstr "在构建文件夹中构建项目" + +#: plugger.py:1350 +msgid "C Build crashed !\n" +msgstr "C构建损坏!\n" + +#: plugger.py:1347 +msgid "C Build failed.\n" +msgstr "C构建失败。\n" + +#: plugger.py:1336 +msgid "C code generated successfully.\n" +msgstr "C代码生成成功。\n" + +#: targets/toolchain_gcc.py:119 +#, python-format +msgid "C compilation of %s failed.\n" +msgstr " %s 的C编译失败。\n" + +#: plugger.py:1037 +#, python-format +msgid "Can't find module for target %s!\n" +msgstr "无法为目标找到模型 %s!\n" + +#: discovery.py:79 +msgid "Cancel" +msgstr "取消" + +#: plugger.py:1746 +msgid "Cannot compare latest build to target. Please build.\n" +msgstr "无法与目标比较最新的建立。\n" + +#: plugger.py:465 +#, python-format +msgid "Cannot create child %s of type %s " +msgstr "无法新建分支 %s 类型 %s " + +#: plugger.py:420 +#, python-format +msgid "Cannot find lower free IEC channel than %d\n" +msgstr "无法找到比 %d 更低的自由的IEC通道\n" + +#: connectors/PYRO/__init__.py:61 +msgid "Cannot get PLC status - connection failed.\n" +msgstr "无法获取PLC的状态 - 连接失败。\n" + +#: plugger.py:1161 +msgid "Cannot open/parse VARIABLES.csv!\n" +msgstr "无法打开/解析 VARIABLES.csv!\n" + +#: plugins/canfestival/config_utils.py:371 +#, python-format +msgid "Cannot set bit offset for non bool '%s' variable (ID:%d,Idx:%x,sIdx:%x))" +msgstr "无法设定位抵消非布尔 '%s' variable (ID:%d,Idx:%x,sIdx:%x)) " + +#: Beremiz_service.py:281 +msgid "Change IP of interface to bind" +msgstr "更改界面的ip用以绑定" + +#: Beremiz_service.py:280 +msgid "Change Name" +msgstr "更改名字" + +#: Beremiz_service.py:284 +msgid "Change Port Number" +msgstr "更改端口号" + +#: Beremiz_service.py:286 +msgid "Change working directory" +msgstr "更改工作目录" + +#: Beremiz.py:1249 +#: Beremiz.py:1272 +msgid "Choose a project" +msgstr "选择一个项目" + +#: Beremiz_service.py:332 +msgid "Choose a working directory " +msgstr "选择一个工作目录" + +#: plugger.py:1804 +msgid "Clean" +msgstr "清除" + +#: plugger.py:1806 +msgid "Clean project build folder" +msgstr "清除项目构建目录" + +#: plugger.py:1431 +msgid "Cleaning the build directory\n" +msgstr "清除构建目录\n" + +#: Beremiz.py:524 +#: Beremiz.py:1299 +msgid "Close Application" +msgstr "关闭应用" + +#: Beremiz.py:292 +msgid "Close Project" +msgstr "关闭项目" + +#: plugger.py:963 +msgid "Compiling IEC Program in to C code...\n" +msgstr "正在将IEC程序编译成C代码...\n" + +#: plugins/canfestival/config_utils.py:335 +#: plugins/canfestival/config_utils.py:617 +#, python-format +msgid "Conflict type for location \"%s\"" +msgstr "位置的冲突类型 \"%s\"" + +#: plugger.py:1828 +msgid "Connect" +msgstr "连接" + +#: plugger.py:1829 +msgid "Connect to the target PLC" +msgstr "连接到PLC目标" + +#: connectors/PYRO/__init__.py:31 +#, python-format +msgid "Connecting to URI : %s\n" +msgstr "连接到URI: %s!\n" + +#: plugger.py:1713 +#, python-format +msgid "Connection failed to %s!\n" +msgstr "连接失败 %s!\n" + +#: plugger.py:581 +#, python-format +msgid "" +"Could not add child \"%s\", type %s :\n" +"%s\n" +msgstr "" +"无法添加分支 \"%s\", type %s :\n" +"%s\n" + +#: plugger.py:558 +#, python-format +msgid "" +"Couldn't load plugin base parameters %s :\n" +" %s" +msgstr "" +"无法下载插件基本参数 %s :\n" +" %s" + +#: plugger.py:569 +#, python-format +msgid "" +"Couldn't load plugin parameters %s :\n" +" %s" +msgstr "" +"无法下载插件参数 %s :\n" +" %s" + +#: plugger.py:1644 +msgid "Couldn't start PLC debug !\n" +msgstr "无法开始PLC调试!\n" + +#: plugger.py:1674 +msgid "Couldn't stop PLC !\n" +msgstr "无法停止PLC!\n" + +#: plugger.py:1814 +msgid "Debug" +msgstr "调试" + +#: plugger.py:1514 +#, python-format +msgid "Debug : Unknown variable %s\n" +msgstr "调试 :未知变量 %s\n" + +#: plugger.py:1622 +msgid "Debug Thread couldn't be killed" +msgstr "调试线程不能结束" + +#: plugger.py:1609 +#, python-format +msgid "Debug data not coherent %d != %d\n" +msgstr "调试不和谐的数据 %d != %d\n" + +#: runtime/PLCObject.py:424 +#, python-format +msgid "Debug error idx : %d, expected_idx %d, type : %s" +msgstr "调试错误 idx : %d, expected_idx %d, 类型 : %s" + +#: plugger.py:1614 +msgid "Debugger disabled\n" +msgstr "调试器禁用\n" + +#: Beremiz.py:313 +msgid "Delete Plugin" +msgstr "删除插件" + +#: Beremiz.py:865 +msgid "Delete this plugin" +msgstr "删除这个插件" + +#: plugger.py:1461 +msgid "Dirty" +msgstr "变质" + +#: plugger.py:1837 +msgid "Disconnect" +msgstr "断开" + +#: plugger.py:1839 +msgid "Disconnect from PLC" +msgstr "从PLC断开" + +#: plugger.py:1467 +msgid "Disconnected" +msgstr "已断开" + +#: PythonSTC.py:576 +msgid "Do you want to continue?" +msgstr "你希望继续吗?" + +#: Beremiz.py:1261 +msgid "ERROR" +msgstr "错误" + +#: plugins/c_ext/c_ext.py:204 +#: plugins/c_ext/c_ext.py:205 +msgid "Edit C File" +msgstr "编辑C文件" + +#: plugins/canfestival/canfestival.py:200 +msgid "Edit CanOpen Network with NetworkEdit" +msgstr "用网络编辑器编辑CanOpen网络" + +#: plugger.py:1796 +msgid "Edit PLC" +msgstr "编辑PLC" + +#: Beremiz.py:308 +msgid "Edit PLC\tCTRL+R" +msgstr "编辑PLC\tCTRL+R" + +#: plugger.py:1797 +msgid "Edit PLC program with PLCOpenEditor" +msgstr "使用PLCOpen编辑器编辑PLC程序" + +#: plugger.py:1856 +msgid "Edit a WxWidgets GUI with WXGlade" +msgstr "用 WXGlade 编辑一个 WxWidgets 用户图形界面" + +#: plugins/canfestival/canfestival.py:199 +msgid "Edit network" +msgstr "编辑网络" + +#: plugger.py:1848 +msgid "Edit raw IEC code added to code generated by PLCGenerator" +msgstr "编辑原始的IEC代码添加至PLCGenerator生成的代码" + +#: plugger.py:1458 +msgid "Empty" +msgstr "空的" + +#: Beremiz.py:815 +msgid "Enable/Disable this plugin" +msgstr "激活/禁用这个插件" + +#: Beremiz_service.py:339 +msgid "Enter a name " +msgstr "输入一个名字" + +#: Beremiz_service.py:324 +msgid "Enter a port number " +msgstr "输入一个端口号" + +#: Beremiz_service.py:314 +msgid "Enter the ip of the interface to bind" +msgstr "输入界面的ip用以绑定" + +#: Beremiz.py:1284 +#: Beremiz.py:1288 +#: Beremiz.py:1443 +#: Beremiz.py:1453 +#: Beremiz_service.py:229 +#: Beremiz_service.py:353 +msgid "Error" +msgstr "错误" + +#: plugger.py:1010 +msgid "Error : At least one configuration and one ressource must be declared in PLC !\n" +msgstr "错误:在PLC中,必须申明至少一个配置和一个资源!\n" + +#: plugger.py:1002 +#, python-format +msgid "Error : IEC to C compiler returned %d\n" +msgstr "错误:IEC到C编译器返回 %d\n" + +#: plugger.py:941 +#, python-format +msgid "" +"Error in ST/IL/SFC code generator :\n" +"%s\n" +msgstr "" +"错误在ST/IL/SFC代码生成器中:\n" +"%s\n" + +#: plugger.py:202 +#, python-format +msgid "Error while saving \"%s\"\n" +msgstr "存储时有错误 \"%s\"\n" + +#: plugins/canfestival/canfestival.py:191 +msgid "Error: No Master generated\n" +msgstr "错误:没有主控生成\n" + +#: plugins/canfestival/canfestival.py:186 +msgid "Error: No PLC built\n" +msgstr "错误:没有PLC构建\n" + +#: plugger.py:1707 +#, python-format +msgid "Exception while connecting %s!\n" +msgstr "连接时存在异常 %s!\n" + +#: plugger.py:1014 +msgid "Extracting Located Variables...\n" +msgstr "正在提取位置变量......\n" + +#: plugger.py:1761 +msgid "Failed : Must build before transfer.\n" +msgstr "失败:传输之前必须构建。\n" + +#: plugger.py:1341 +msgid "Fatal : cannot get builder.\n" +msgstr "致命错误:无法获取构建者。\n" + +#: Beremiz.py:347 +msgid "File" +msgstr "文件" + +#: plugger.py:815 +msgid "Folder choosen doesn't contain a program. It's not a valid project!" +msgstr "被选中的文件夹未包含一个程序。它不是一个有效项目!" + +#: plugger.py:780 +msgid "Folder choosen isn't empty. You can't use it for a new project!" +msgstr "被选中的文件夹非空。你不能用它创建一个新项目!" + +#: connectors/PYRO/__init__.py:93 +msgid "Force runtime reload\n" +msgstr "强制重新运行\n" + +#: plugger.py:931 +msgid "Generating SoftPLC IEC-61131 ST/IL/SFC code...\n" +msgstr "生成软PLC IEC-61131 ST/IL/SFC 代码......\n" + +#: plugger.py:1289 +msgid "Generating plugins C code\n" +msgstr "生成C代码插件\n" + +#: Beremiz.py:350 +msgid "Help" +msgstr "帮助" + +#: plugger.py:1281 +msgid "IEC-61131-3 code generation failed !\n" +msgstr "IEC-61131-3代码生成失败!\n" + +#: plugins/canfestival/config_utils.py:376 +#: plugins/canfestival/config_utils.py:637 +#, python-format +msgid "Invalid type \"%s\"-> %d != %d for location\"%s\"" +msgstr "无效类型 \"%s\"-> %d != %d 用于位置 \"%s\"" + +#: Beremiz_service.py:315 +#: Beremiz_service.py:316 +msgid "Ip is not valid!" +msgstr "Ip无效!" + +#: plugger.py:1767 +msgid "Latest build already match current target. Transfering anyway...\n" +msgstr "最新构建已经与当前目标匹配。正在传输中......\n" + +#: plugger.py:1737 +msgid "Latest build do not match with target, please transfer.\n" +msgstr "最新构建与目标不匹配,请传输。\n" + +#: plugger.py:1741 +msgid "Latest build match target, no transfer needed.\n" +msgstr "最新构建与目标匹配,不需要传输。\n" + +#: Beremiz_service.py:283 +msgid "Launch WX GUI inspector" +msgstr "启动 WX GUI 检查员" + +#: Beremiz_service.py:282 +msgid "Launch a live Python shell" +msgstr "启动一个活的Python Shell" + +#: targets/toolchain_gcc.py:127 +msgid "Linking :\n" +msgstr "链接:\n" + +#: discovery.py:72 +msgid "Local" +msgstr "本地" + +#: Beremiz.py:435 +msgid "Log Console" +msgstr "控制台日志" + +#: plugger.py:475 +#, python-format +msgid "Max count (%d) reached for this plugin of type %s " +msgstr "最大计数 (%d) 到达" + +#: runtime/ServicePublisher.py:50 +msgid "My IP is :" +msgstr "我的IP是:" + +#: Beremiz_service.py:340 +msgid "Name must not be null!" +msgstr "名称不能为空!" + +#: Beremiz.py:286 +msgid "New\tCTRL+N" +msgstr "新建\tCTRL+N" + +#: runtime/PLCObject.py:313 +#, python-format +msgid "NewPLC (%s)" +msgstr "新的PLC(%s)" + +#: plugger.py:1791 +msgid "No PLC to transfer (did build success ?)\n" +msgstr "没有PLC可传输(构建是否成功?)\n" + +#: Beremiz_service.py:353 +msgid "No runnning PLC" +msgstr "没有正在运行的PLC" + +#: plugins/canfestival/config_utils.py:632 +#, python-format +msgid "No such index/subindex (%x,%x) (variable %s)" +msgstr "没有这样的索引/子索引 (%x,%x) (variable %s)" + +#: plugins/canfestival/config_utils.py:361 +#, python-format +msgid "No such index/subindex (%x,%x) in ID : %d (variable %s)" +msgstr "没有这样的索引/子索引 (%x,%x) in ID : %d (variable %s)" + +#: plugins/canfestival/config_utils.py:354 +#, python-format +msgid "Non existing node ID : %d (variable %s)" +msgstr "不存在节点ID:%d (variable %s)" + +#: plugins/canfestival/config_utils.py:383 +#, python-format +msgid "Not PDO mappable variable : '%s' (ID:%d,Idx:%x,sIdx:%x))" +msgstr "不是PDO填图变量: '%s' (ID:%d,Idx:%x,sIdx:%x))" + +#: discovery.py:83 +msgid "OK" +msgstr "确定" + +#: Beremiz.py:288 +msgid "Open\tCTRL+O" +msgstr "打开\tCTRL+O" + +#: targets/toolchain_gcc.py:95 +msgid "PLC :\n" +msgstr "PLC:\n" + +#: plugger.py:1447 +#: plugger.py:1483 +#: plugger.py:1723 +#, python-format +msgid "PLC is %s\n" +msgstr "PLC 是 %s\n" + +#: Beremiz.py:1390 +msgid "Please enter a name for plugin:" +msgstr "请为插件输入一个名字:" + +#: runtime/PLCObject.py:219 +msgid "Please stop PLC to close" +msgstr "请停止PLC以便关闭" + +#: targets/toolchain_gcc.py:93 +msgid "Plugin : " +msgstr "插件:" + +#: plugger.py:1295 +msgid "Plugins code generation failed !\n" +msgstr "插件代码生成失败!\n" + +#: Beremiz_service.py:325 +msgid "Port number must be 0 <= port <= 65535!" +msgstr "端口号必须为 0 <= 端口号 <= 65535!" + +#: Beremiz_service.py:325 +msgid "Port number must be an integer!" +msgstr "端口号必须是整数!" + +#: runtime/PLCObject.py:279 +#, python-format +msgid "Problem %s PLC" +msgstr "问题 %s PLC" + +#: plugger.py:789 +msgid "Project not created" +msgstr "项目未创建" + +#: plugger.py:503 +#, python-format +msgid "Project tree layout do not match plugin.xml %s!=%s " +msgstr "项目树型布局与 plugin.xml 不匹配 %s!=%s " + +#: Beremiz.py:295 +msgid "Properties" +msgstr "属性" + +#: Beremiz_service.py:433 +msgid "Publish service on local network" +msgstr "在本地网络发布服务" + +#: plugger.py:1851 +msgid "Python code" +msgstr "Python代码" + +#: runtime/PLCObject.py:282 +msgid "PythonThreadProc interrupted" +msgstr "Python线程处理被中断" + +#: PythonSTC.py:577 +msgid "Question" +msgstr "问题" + +#: Beremiz_service.py:287 +msgid "Quit" +msgstr "退出" + +#: Beremiz.py:298 +msgid "Quit\tCTRL+Q" +msgstr "退出\tCTRL+Q" + +#: plugger.py:1847 +msgid "Raw IEC code" +msgstr "原始的IEC代码" + +#: Beremiz.py:1398 +msgid "Really delete plugin ?" +msgstr "确定删除插件?" + +#: discovery.py:64 +msgid "Refresh" +msgstr "刷新" + +#: Beremiz.py:1398 +msgid "Remove plugin" +msgstr "移除这个插件" + +#: Beremiz.py:325 +#: plugger.py:1809 +msgid "Run" +msgstr "运行" + +#: Beremiz.py:290 +msgid "Save\tCTRL+S" +msgstr "保存\tCTRL+S" + +#: Beremiz.py:328 +msgid "Save Log" +msgstr "保存日志" + +#: Beremiz.py:523 +#: Beremiz.py:1298 +msgid "Save changes ?" +msgstr "保存修改?" + +#: discovery.py:37 +msgid "Service Discovery" +msgstr "服务探索" + +#: plugger.py:1844 +msgid "Show IEC code generated by PLCGenerator" +msgstr "显示由PLCGenerator生成的IEC代码" + +#: plugins/canfestival/canfestival.py:202 +msgid "Show Master" +msgstr "显示主控" + +#: plugins/canfestival/canfestival.py:203 +msgid "Show Master generated by config_utils" +msgstr "显示由config_utils生成的主控" + +#: plugger.py:1842 +msgid "Show code" +msgstr "显示代码" + +#: Beremiz.py:323 +msgid "Simulate" +msgstr "模拟" + +#: plugger.py:1811 +#: Beremiz_service.py:278 +#: runtime/PLCObject.py:285 +msgid "Start PLC" +msgstr "开始PLC" + +#: plugger.py:1816 +msgid "Start PLC (debug mode)" +msgstr "开始PLC(调试模式)" + +#: plugger.py:1273 +#, python-format +msgid "Start build in %s\n" +msgstr "开始建立 %s\n" + +#: plugger.py:1452 +msgid "Started" +msgstr "已开始" + +#: plugger.py:1631 +msgid "Starting PLC (debug mode)\n" +msgstr "正在开始PLC(调试模式)\n" + +#: plugger.py:1823 +msgid "Stop" +msgstr "停止" + +#: Beremiz_service.py:279 +#: runtime/PLCObject.py:291 +msgid "Stop PLC" +msgstr "停止PLC" + +#: plugger.py:1825 +msgid "Stop Running PLC" +msgstr "停止运行PLC" + +#: plugger.py:1455 +msgid "Stopped" +msgstr "已停止" + +#: plugger.py:1670 +msgid "Stopping debug\n" +msgstr "正在停止调试\n" + +#: Beremiz_service.py:426 +msgid "The daemon runs on port :" +msgstr "守护进程在端口运行:" + +#: Beremiz_service.py:427 +msgid "The object's uri is :" +msgstr "对象的uri是:" + +#: Beremiz_service.py:428 +msgid "The working directory :" +msgstr "工作目录:" + +#: plugger.py:1832 +msgid "Transfer" +msgstr "传输" + +#: plugger.py:1834 +msgid "Transfer PLC" +msgstr "传输PLC" + +#: plugger.py:1787 +msgid "Transfer completed successfully.\n" +msgstr "传输成功\n" + +#: plugger.py:1789 +msgid "Transfer failed\n" +msgstr "传输失败\n" + +#: targets/Xenomai/__init__.py:27 +msgid "Unable to get Xenomai's CFLAGS\n" +msgstr "无法获取Xenomai的CFLAGS\n" + +#: targets/Xenomai/__init__.py:16 +msgid "Unable to get Xenomai's LDFLAGS\n" +msgstr "无法获取Xenomai的LDFLAGS\n" + +#: plugger.py:1855 +msgid "WXGLADE GUI" +msgstr "WXGLADE 用户图形界面" + +#: plugger.py:936 +msgid "Warnings in ST/IL/SFC code generator :\n" +msgstr "警告在ST/IL/SFC代码生成器中:\n" + +#: plugger.py:1852 +msgid "Write Python runtime code, for use with python_eval FBs" +msgstr "编辑Python运行时间代码,与python_eval FBs一起使用" + +#: connectors/PYRO/__init__.py:39 +msgid "Wrong URI, please check it !\n" +msgstr "错误的URI,请检查!\n" + +#: PythonSTC.py:575 +msgid "You are about to overwrite that file\n" +msgstr "你即将要覆盖该文件\n" + +#: wxPopen.py:134 +#, python-format +msgid "exited with status %s (pid %s)\n" +msgstr "退出并保持现状 %s (pid %s)\n" + +#: Beremiz.py:1417 +#: Beremiz.py:1419 +msgid "file : " +msgstr "文件:" + +#: Beremiz.py:1420 +msgid "function : " +msgstr "功能:" + +#: Beremiz.py:1420 +msgid "line : " +msgstr "在线:" + +#: runtime/PLCObject.py:277 +msgid "loading" +msgstr "载入" + +#: runtime/PLCObject.py:275 +msgid "starting" +msgstr "正在开始" + +#: Extra XSD strings +msgid "BaseParams" +msgstr "基本参照 " + +msgid "Name" +msgstr "名字" + +msgid "IEC_Channel" +msgstr "IEC_频道" + +msgid "Enabled" +msgstr "启用" + +msgid "BeremizRoot" +msgstr "Beremiz根" + +msgid "TargetType" +msgstr "目标类型" + +msgid "URI_location" +msgstr "URI_位置" + +msgid "Enable_Plugins" +msgstr "启用_插件" + +msgid "CExtension" +msgstr "C扩展" + +msgid "CFLAGS" +msgstr "CFLAGS" + +msgid "LDFLAGS" +msgstr "LDFLAGS" + +msgid "CanFestivalSlaveNode" +msgstr "CanFestival从节点" + +msgid "CAN_Device" +msgstr "CAN_设备" + +msgid "CAN_Baudrate" +msgstr "CAN_波特率" + +msgid "NodeId" +msgstr "节点Id" + +msgid "Sync_Align" +msgstr "同步_对齐" + +msgid "Sync_Align_Ratio" +msgstr "同步_对齐_比率" + +msgid "CanFestivalNode" +msgstr "CanFestival节点" + +msgid "Sync_TPDOs" +msgstr "Sync_TPDOs" + +msgid "CanFestivalInstance" +msgstr "CanFestival实例" + +msgid "CAN_Driver" +msgstr "CAN_驱动" + +msgid "Debug_mode" +msgstr "调试_模式" + +msgid "Compiler" +msgstr "编译" + +msgid "Linker" +msgstr "链接 " + +msgid "Linux" +msgstr "Linux" + +msgid "Rtai" +msgstr "Rtai" + +msgid "rtai_config" +msgstr "rtai_config" + +msgid "Win32" +msgstr "Win32" + +msgid "Xenomai" +msgstr "Xenomai" + +msgid "XenoConfig" +msgstr "XenoConfig" + +#~ msgid "#define %s beremiz%s\n" +#~ msgstr "#定义 %s beremiz%s\n" +#~ msgid "/* Beremiz c_ext plugin user variables definition */\n" +#~ msgstr "/* Beremiz c_ext 插件的用户变量定义 */\n" +#~ msgid "/* Beremiz plugin functions */\n" +#~ msgstr "/* Beremiz插件功能 */\n" +#~ msgid "" +#~ "/* Code generated by Beremiz c_ext plugin */\n" +#~ "\n" +#~ msgstr "" +#~ "/* 代码由Beremiz c_ext插件生成 */\n" +#~ "\n" +#~ msgid "/* User includes */\n" +#~ msgstr "/* 用户包含 */\n" +#~ msgid "/* User internal user variables and routines */\n" +#~ msgstr "/* 用户内部用户变量和例程 */\n" +#~ msgid "/* User variables reference */\n" +#~ msgstr "/* 用户变量参照 */\n" +#~ msgid "Choose a SVG file" +#~ msgstr "选择一个SVG文件" +#~ msgid "Choose a XML file" +#~ msgstr "选择一个XML文件" +#~ msgid "Couldn't start PLC !\n" +#~ msgstr "无法开始PLC!\n" +#~ msgid "No corresponding output variable found on SVGUI Block \"%s\"" +#~ msgstr "没有相应的输出变量" +#~ msgid "No such SVG file: %s\n" +#~ msgstr "没有这样的SVG文件:%s\n" +#~ msgid "No such XML file: %s\n" +#~ msgstr "没有这样的XML文件:%s\n" +#~ msgid "Shortcuts created." +#~ msgstr "快捷方式已被建立。" + diff -r 75ae46b66315 -r 71c441104cac i18n/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/i18n/README Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,8 @@ +To generate message.pot file: + + python mki18n.py -p --domain=Beremiz + +To generate .mo files for all languages: + + python mki18n.py -m --moTarget=../locale --domain=Beremiz + \ No newline at end of file diff -r 75ae46b66315 -r 71c441104cac i18n/app.fil --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/i18n/app.fil Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,21 @@ +../Beremiz.py +../plugger.py +../beremiz_postinst.py +../Beremiz_service.py +../discovery.py +../PythonSTC.py +../wxPopen.py +../connectors/PYRO/__init__.py +../plugins/c_ext/c_ext.py +../plugins/canfestival/canfestival.py +../plugins/canfestival/config_utils.py +../plugins/svgui/svgui.py +../runtime/PLCObject.py +../runtime/ServicePublisher.py +../targets/toolchain_gcc.py +../targets/XSD_toolchain_gcc +../targets/Linux/XSD +../targets/Rtai/XSD +../targets/Win32/XSD +../targets/Xenomai/__init__.py +../targets/Xenomai/XSD \ No newline at end of file diff -r 75ae46b66315 -r 71c441104cac i18n/messages.pot --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/i18n/messages.pot Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,843 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-07-27 18:06+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../Beremiz.py:1429 +#, python-format +msgid "" +"\n" +"An unhandled exception (bug) occured. Bug report saved at :\n" +"(%s)\n" +"\n" +"Please contact LOLITech at:\n" +"+33 (0)3 29 57 60 42\n" +"or please be kind enough to send this file to:\n" +"bugs_beremiz@lolitech.fr\n" +"\n" +"You should now restart Beremiz.\n" +"\n" +"Traceback:\n" +msgstr "" + +#: ../plugger.py:1332 +msgid " generation failed !\n" +msgstr "" + +#: ../Beremiz.py:1288 +#, python-format +msgid "\"%s\" folder is not a valid Beremiz project\n" +msgstr "" + +#: ../Beremiz.py:1417 ../Beremiz.py:1419 ../Beremiz.py:1420 +msgid ", " +msgstr "" + +#: ../Beremiz.py:1415 +msgid ". " +msgstr "" + +#: ../plugger.py:395 +#, python-format +msgid "A child names \"%s\" already exist -> \"%s\"\n" +msgstr "" + +#: ../plugger.py:427 +#, python-format +msgid "A child with IEC channel %d already exist -> %d\n" +msgstr "" + +#: ../Beremiz.py:342 +msgid "About" +msgstr "" + +#: ../Beremiz.py:1357 +msgid "About Beremiz" +msgstr "" + +#: ../Beremiz.py:311 ../Beremiz.py:1390 +msgid "Add Plugin" +msgstr "" + +#: ../Beremiz.py:612 ../Beremiz.py:874 +msgid "Add a sub plugin" +msgstr "" + +#: ../plugger.py:1683 +msgid "Already connected. Please disconnect\n" +msgstr "" + +#: ../Beremiz.py:1056 +msgid "Append " +msgstr "" + +#: ../plugins/canfestival/config_utils.py:341 +#: ../plugins/canfestival/config_utils.py:623 +#, python-format +msgid "Bad location size : %s" +msgstr "" + +#: ../Beremiz.py:392 +msgid "Beremiz" +msgstr "" + +#: ../Beremiz.py:340 +msgid "Beremiz\tF1" +msgstr "" + +#: ../plugger.py:1463 +msgid "Broken" +msgstr "" + +#: ../plugger.py:1807 +msgid "Build" +msgstr "" + +#: ../Beremiz.py:320 +msgid "Build\tCTRL+R" +msgstr "" + +#: ../plugger.py:1434 +msgid "Build directory already clean\n" +msgstr "" + +#: ../plugger.py:1808 +msgid "Build project into build folder" +msgstr "" + +#: ../plugger.py:1350 +msgid "C Build crashed !\n" +msgstr "" + +#: ../plugger.py:1347 +msgid "C Build failed.\n" +msgstr "" + +#: ../plugger.py:1336 +msgid "C code generated successfully.\n" +msgstr "" + +#: ../targets/toolchain_gcc.py:119 +#, python-format +msgid "C compilation of %s failed.\n" +msgstr "" + +#: ../plugger.py:1037 +#, python-format +msgid "Can't find module for target %s!\n" +msgstr "" + +#: ../discovery.py:79 +msgid "Cancel" +msgstr "" + +#: ../plugger.py:1753 +msgid "Cannot compare latest build to target. Please build.\n" +msgstr "" + +#: ../plugger.py:465 +#, python-format +msgid "Cannot create child %s of type %s " +msgstr "" + +#: ../plugger.py:420 +#, python-format +msgid "Cannot find lower free IEC channel than %d\n" +msgstr "" + +#: ../connectors/PYRO/__init__.py:61 +msgid "Cannot get PLC status - connection failed.\n" +msgstr "" + +#: ../plugger.py:1161 +msgid "Cannot open/parse VARIABLES.csv!\n" +msgstr "" + +#: ../plugins/canfestival/config_utils.py:371 +#, python-format +msgid "Cannot set bit offset for non bool '%s' variable (ID:%d,Idx:%x,sIdx:%x))" +msgstr "" + +#: ../Beremiz_service.py:315 +msgid "Change IP of interface to bind" +msgstr "" + +#: ../Beremiz_service.py:314 +msgid "Change Name" +msgstr "" + +#: ../Beremiz_service.py:318 +msgid "Change Port Number" +msgstr "" + +#: ../Beremiz_service.py:320 +msgid "Change working directory" +msgstr "" + +#: ../Beremiz.py:1249 ../Beremiz.py:1272 +msgid "Choose a project" +msgstr "" + +#: ../Beremiz_service.py:366 +msgid "Choose a working directory " +msgstr "" + +#: ../plugger.py:1811 +msgid "Clean" +msgstr "" + +#: ../plugger.py:1813 +msgid "Clean project build folder" +msgstr "" + +#: ../plugger.py:1431 +msgid "Cleaning the build directory\n" +msgstr "" + +#: ../Beremiz.py:524 ../Beremiz.py:1299 +msgid "Close Application" +msgstr "" + +#: ../Beremiz.py:292 +msgid "Close Project" +msgstr "" + +#: ../plugger.py:963 +msgid "Compiling IEC Program in to C code...\n" +msgstr "" + +#: ../plugins/canfestival/config_utils.py:335 +#: ../plugins/canfestival/config_utils.py:617 +#, python-format +msgid "Conflict type for location \"%s\"" +msgstr "" + +#: ../plugger.py:1835 +msgid "Connect" +msgstr "" + +#: ../plugger.py:1836 +msgid "Connect to the target PLC" +msgstr "" + +#: ../connectors/PYRO/__init__.py:31 +#, python-format +msgid "Connecting to URI : %s\n" +msgstr "" + +#: ../plugger.py:1716 +#, python-format +msgid "Connection failed to %s!\n" +msgstr "" + +#: ../plugger.py:581 +#, python-format +msgid "" +"Could not add child \"%s\", type %s :\n" +"%s\n" +msgstr "" + +#: ../plugger.py:558 +#, python-format +msgid "" +"Couldn't load plugin base parameters %s :\n" +" %s" +msgstr "" + +#: ../plugger.py:569 +#, python-format +msgid "" +"Couldn't load plugin parameters %s :\n" +" %s" +msgstr "" + +#: ../plugger.py:1647 +msgid "Couldn't start PLC debug !\n" +msgstr "" + +#: ../plugger.py:1677 +msgid "Couldn't stop PLC !\n" +msgstr "" + +#: ../plugger.py:1821 +msgid "Debug" +msgstr "" + +#: ../plugger.py:1517 +#, python-format +msgid "Debug : Unknown variable %s\n" +msgstr "" + +#: ../plugger.py:1625 +msgid "Debug Thread couldn't be killed" +msgstr "" + +#: ../plugger.py:1612 +#, python-format +msgid "Debug data not coherent %d != %d\n" +msgstr "" + +#: ../plugger.py:1617 +msgid "Debugger disabled\n" +msgstr "" + +#: ../Beremiz.py:313 +msgid "Delete Plugin" +msgstr "" + +#: ../Beremiz.py:865 +msgid "Delete this plugin" +msgstr "" + +#: ../plugger.py:1460 +msgid "Dirty" +msgstr "" + +#: ../plugger.py:1844 +msgid "Disconnect" +msgstr "" + +#: ../plugger.py:1846 +msgid "Disconnect from PLC" +msgstr "" + +#: ../plugger.py:1466 +msgid "Disconnected" +msgstr "" + +#: ../Beremiz.py:1261 +msgid "ERROR" +msgstr "" + +#: ../plugins/c_ext/c_ext.py:204 ../plugins/c_ext/c_ext.py:205 +msgid "Edit C File" +msgstr "" + +#: ../plugins/canfestival/canfestival.py:200 +msgid "Edit CanOpen Network with NetworkEdit" +msgstr "" + +#: ../plugger.py:1803 +msgid "Edit PLC" +msgstr "" + +#: ../Beremiz.py:308 +msgid "Edit PLC\tCTRL+R" +msgstr "" + +#: ../plugger.py:1804 +msgid "Edit PLC program with PLCOpenEditor" +msgstr "" + +#: ../plugins/canfestival/canfestival.py:199 +msgid "Edit network" +msgstr "" + +#: ../plugger.py:1855 +msgid "Edit raw IEC code added to code generated by PLCGenerator" +msgstr "" + +#: ../plugger.py:1457 +msgid "Empty" +msgstr "" + +#: ../Beremiz.py:815 +msgid "Enable/Disable this plugin" +msgstr "" + +#: ../Beremiz_service.py:373 +msgid "Enter a name " +msgstr "" + +#: ../Beremiz_service.py:358 +msgid "Enter a port number " +msgstr "" + +#: ../Beremiz_service.py:348 +msgid "Enter the ip of the interface to bind" +msgstr "" + +#: ../Beremiz.py:1284 ../Beremiz.py:1288 ../Beremiz.py:1443 ../Beremiz.py:1453 +#: ../Beremiz_service.py:263 ../Beremiz_service.py:387 +msgid "Error" +msgstr "" + +#: ../plugger.py:1010 +msgid "Error : At least one configuration and one ressource must be declared in PLC !\n" +msgstr "" + +#: ../plugger.py:1002 +#, python-format +msgid "Error : IEC to C compiler returned %d\n" +msgstr "" + +#: ../plugger.py:941 +#, python-format +msgid "" +"Error in ST/IL/SFC code generator :\n" +"%s\n" +msgstr "" + +#: ../plugger.py:202 +#, python-format +msgid "Error while saving \"%s\"\n" +msgstr "" + +#: ../plugins/canfestival/canfestival.py:191 +msgid "Error: No Master generated\n" +msgstr "" + +#: ../plugins/canfestival/canfestival.py:186 +msgid "Error: No PLC built\n" +msgstr "" + +#: ../plugger.py:1710 +#, python-format +msgid "Exception while connecting %s!\n" +msgstr "" + +#: ../plugger.py:1014 +msgid "Extracting Located Variables...\n" +msgstr "" + +#: ../plugger.py:1768 +msgid "Failed : Must build before transfer.\n" +msgstr "" + +#: ../plugger.py:1341 +msgid "Fatal : cannot get builder.\n" +msgstr "" + +#: ../Beremiz.py:347 +msgid "File" +msgstr "" + +#: ../plugger.py:815 +msgid "Folder choosen doesn't contain a program. It's not a valid project!" +msgstr "" + +#: ../plugger.py:780 +msgid "Folder choosen isn't empty. You can't use it for a new project!" +msgstr "" + +#: ../connectors/PYRO/__init__.py:93 +msgid "Force runtime reload\n" +msgstr "" + +#: ../plugger.py:931 +msgid "Generating SoftPLC IEC-61131 ST/IL/SFC code...\n" +msgstr "" + +#: ../plugger.py:1289 +msgid "Generating plugins C code\n" +msgstr "" + +#: ../Beremiz.py:350 +msgid "Help" +msgstr "" + +#: ../plugger.py:1281 +msgid "IEC-61131-3 code generation failed !\n" +msgstr "" + +#: ../plugins/canfestival/config_utils.py:455 +#: ../plugins/canfestival/config_utils.py:469 +#, python-format +msgid "Impossible to define PDO mapping for node %02x" +msgstr "" + +#: ../plugins/canfestival/config_utils.py:376 +#: ../plugins/canfestival/config_utils.py:637 +#, python-format +msgid "Invalid type \"%s\"-> %d != %d for location\"%s\"" +msgstr "" + +#: ../Beremiz_service.py:349 ../Beremiz_service.py:350 +msgid "Ip is not valid!" +msgstr "" + +#: ../plugger.py:1774 +msgid "Latest build already match current target. Transfering anyway...\n" +msgstr "" + +#: ../plugger.py:1744 +msgid "Latest build do not match with target, please transfer.\n" +msgstr "" + +#: ../plugger.py:1748 +msgid "Latest build match target, no transfer needed.\n" +msgstr "" + +#: ../Beremiz_service.py:317 +msgid "Launch WX GUI inspector" +msgstr "" + +#: ../Beremiz_service.py:316 +msgid "Launch a live Python shell" +msgstr "" + +#: ../targets/toolchain_gcc.py:127 +msgid "Linking :\n" +msgstr "" + +#: ../discovery.py:72 +msgid "Local" +msgstr "" + +#: ../Beremiz.py:435 +msgid "Log Console" +msgstr "" + +#: ../plugger.py:475 +#, python-format +msgid "Max count (%d) reached for this plugin of type %s " +msgstr "" + +#: ../Beremiz_service.py:374 +msgid "Name must not be null!" +msgstr "" + +#: ../Beremiz.py:286 +msgid "New\tCTRL+N" +msgstr "" + +#: ../plugger.py:1798 +msgid "No PLC to transfer (did build success ?)\n" +msgstr "" + +#: ../Beremiz_service.py:387 +msgid "No runnning PLC" +msgstr "" + +#: ../plugins/canfestival/config_utils.py:632 +#, python-format +msgid "No such index/subindex (%x,%x) (variable %s)" +msgstr "" + +#: ../plugins/canfestival/config_utils.py:361 +#, python-format +msgid "No such index/subindex (%x,%x) in ID : %d (variable %s)" +msgstr "" + +#: ../plugins/canfestival/config_utils.py:354 +#, python-format +msgid "Non existing node ID : %d (variable %s)" +msgstr "" + +#: ../plugins/canfestival/config_utils.py:383 +#, python-format +msgid "Not PDO mappable variable : '%s' (ID:%d,Idx:%x,sIdx:%x))" +msgstr "" + +#: ../discovery.py:83 +msgid "OK" +msgstr "" + +#: ../Beremiz.py:288 +msgid "Open\tCTRL+O" +msgstr "" + +#: ../targets/toolchain_gcc.py:95 +msgid "PLC :\n" +msgstr "" + +#: ../plugger.py:1486 ../plugger.py:1730 +#, python-format +msgid "PLC is %s\n" +msgstr "" + +#: ../Beremiz.py:1390 +msgid "Please enter a name for plugin:" +msgstr "" + +#: ../runtime/PLCObject.py:219 +msgid "Please stop PLC to close" +msgstr "" + +#: ../targets/toolchain_gcc.py:93 +msgid "Plugin : " +msgstr "" + +#: ../plugger.py:1295 +msgid "Plugins code generation failed !\n" +msgstr "" + +#: ../Beremiz_service.py:359 +msgid "Port number must be 0 <= port <= 65535!" +msgstr "" + +#: ../Beremiz_service.py:359 +msgid "Port number must be an integer!" +msgstr "" + +#: ../plugger.py:789 +msgid "Project not created" +msgstr "" + +#: ../plugger.py:503 +#, python-format +msgid "Project tree layout do not match plugin.xml %s!=%s " +msgstr "" + +#: ../Beremiz.py:295 +msgid "Properties" +msgstr "" + +#: ../Beremiz_service.py:321 +msgid "Quit" +msgstr "" + +#: ../Beremiz.py:298 +msgid "Quit\tCTRL+Q" +msgstr "" + +#: ../plugger.py:1854 +msgid "Raw IEC code" +msgstr "" + +#: ../Beremiz.py:1398 +msgid "Really delete plugin ?" +msgstr "" + +#: ../discovery.py:64 +msgid "Refresh" +msgstr "" + +#: ../Beremiz.py:1398 +msgid "Remove plugin" +msgstr "" + +#: ../Beremiz.py:325 ../plugger.py:1816 +msgid "Run" +msgstr "" + +#: ../Beremiz.py:290 +msgid "Save\tCTRL+S" +msgstr "" + +#: ../Beremiz.py:328 +msgid "Save Log" +msgstr "" + +#: ../Beremiz.py:523 ../Beremiz.py:1298 +msgid "Save changes ?" +msgstr "" + +#: ../discovery.py:37 +msgid "Service Discovery" +msgstr "" + +#: ../plugger.py:1851 +msgid "Show IEC code generated by PLCGenerator" +msgstr "" + +#: ../plugins/canfestival/canfestival.py:202 +msgid "Show Master" +msgstr "" + +#: ../plugins/canfestival/canfestival.py:203 +msgid "Show Master generated by config_utils" +msgstr "" + +#: ../plugger.py:1849 +msgid "Show code" +msgstr "" + +#: ../Beremiz.py:323 +msgid "Simulate" +msgstr "" + +#: ../plugger.py:1818 ../Beremiz_service.py:312 +msgid "Start PLC" +msgstr "" + +#: ../plugger.py:1823 +msgid "Start PLC (debug mode)" +msgstr "" + +#: ../plugger.py:1273 +#, python-format +msgid "Start build in %s\n" +msgstr "" + +#: ../plugger.py:1451 +msgid "Started" +msgstr "" + +#: ../plugger.py:1634 +msgid "Starting PLC (debug mode)\n" +msgstr "" + +#: ../plugger.py:1830 +msgid "Stop" +msgstr "" + +#: ../Beremiz_service.py:313 +msgid "Stop PLC" +msgstr "" + +#: ../plugger.py:1832 +msgid "Stop Running PLC" +msgstr "" + +#: ../plugger.py:1454 +msgid "Stopped" +msgstr "" + +#: ../plugger.py:1673 +msgid "Stopping debug\n" +msgstr "" + +#: ../plugger.py:1839 +msgid "Transfer" +msgstr "" + +#: ../plugger.py:1841 +msgid "Transfer PLC" +msgstr "" + +#: ../plugger.py:1794 +msgid "Transfer completed successfully.\n" +msgstr "" + +#: ../plugger.py:1796 +msgid "Transfer failed\n" +msgstr "" + +#: ../targets/Xenomai/__init__.py:27 +msgid "Unable to get Xenomai's CFLAGS\n" +msgstr "" + +#: ../targets/Xenomai/__init__.py:16 +msgid "Unable to get Xenomai's LDFLAGS\n" +msgstr "" + +#: ../plugger.py:936 +msgid "Warnings in ST/IL/SFC code generator :\n" +msgstr "" + +#: ../connectors/PYRO/__init__.py:39 +msgid "Wrong URI, please check it !\n" +msgstr "" + +#: ../wxPopen.py:134 +#, python-format +msgid "exited with status %s (pid %s)\n" +msgstr "" + +#: ../Beremiz.py:1417 ../Beremiz.py:1419 +msgid "file : " +msgstr "" + +#: ../Beremiz.py:1420 +msgid "function : " +msgstr "" + +#: ../Beremiz.py:1420 +msgid "line : " +msgstr "" + +#: Extra XSD strings + +msgid "BaseParams" +msgstr "" + +msgid "Name" +msgstr "" + +msgid "IEC_Channel" +msgstr "" + +msgid "Enabled" +msgstr "" + +msgid "BeremizRoot" +msgstr "" + +msgid "TargetType" +msgstr "" + +msgid "URI_location" +msgstr "" + +msgid "Enable_Plugins" +msgstr "" + +msgid "CExtension" +msgstr "" + +msgid "CFLAGS" +msgstr "" + +msgid "LDFLAGS" +msgstr "" + +msgid "CanFestivalSlaveNode" +msgstr "" + +msgid "CAN_Device" +msgstr "" + +msgid "CAN_Baudrate" +msgstr "" + +msgid "NodeId" +msgstr "" + +msgid "Sync_Align" +msgstr "" + +msgid "Sync_Align_Ratio" +msgstr "" + +msgid "CanFestivalNode" +msgstr "" + +msgid "Sync_TPDOs" +msgstr "" + +msgid "CanFestivalInstance" +msgstr "" + +msgid "CAN_Driver" +msgstr "" + +msgid "Debug_mode" +msgstr "" + +msgid "Compiler" +msgstr "" + +msgid "Linker" +msgstr "" + +msgid "Linux" +msgstr "" + +msgid "Rtai" +msgstr "" + +msgid "rtai_config" +msgstr "" + +msgid "Win32" +msgstr "" + +msgid "Xenomai" +msgstr "" + +msgid "XenoConfig" +msgstr "" diff -r 75ae46b66315 -r 71c441104cac i18n/mki18n.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/i18n/mki18n.py Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,479 @@ +#! /usr/bin/env python +# -*- coding: iso-8859-1 -*- +# +# PYTHON MODULE: MKI18N.PY +# ========= +# +# Abstract: Make Internationalization (i18n) files for an application. +# +# Copyright Pierre Rouleau. 2003. Released to public domain. +# +# Last update: Saturday, November 8, 2003. @ 15:55:18. +# +# File: ROUP2003N01::C:/dev/python/mki18n.py +# +# RCS $Header: //software/official/MKS/MKS_SI/TV_NT/dev/Python/rcs/mki18n.py 1.5 2003/11/05 19:40:04 PRouleau Exp $ +# +# Update history: +# +# - File created: Saturday, June 7, 2003. by Pierre Rouleau +# - 10/06/03 rcs : RCS Revision 1.1 2003/06/10 10:06:12 PRouleau +# - 10/06/03 rcs : RCS Initial revision +# - 23/08/03 rcs : RCS Revision 1.2 2003/06/10 10:54:27 PRouleau +# - 23/08/03 P.R.: [code:fix] : The strings encoded in this file are encode in iso-8859-1 format. Added the encoding +# notification to Python to comply with Python's 2.3 PEP 263. +# - 23/08/03 P.R.: [feature:new] : Added the '-e' switch which is used to force the creation of the empty English .mo file. +# - 22/10/03 P.R.: [code] : incorporated utility functions in here to make script self sufficient. +# - 05/11/03 rcs : RCS Revision 1.4 2003/10/22 06:39:31 PRouleau +# - 05/11/03 P.R.: [code:fix] : included the unixpath() in this file. +# - 08/11/03 rcs : RCS Revision 1.5 2003/11/05 19:40:04 PRouleau +# +# RCS $Log: $ +# +# +# ----------------------------------------------------------------------------- +""" +mki18n allows you to internationalize your software. You can use it to +create the GNU .po files (Portable Object) and the compiled .mo files +(Machine Object). + +mki18n module can be used from the command line or from within a script (see +the Usage at the end of this page). + + Table of Contents + ----------------- + + makePO() -- Build the Portable Object file for the application -- + catPO() -- Concatenate one or several PO files with the application domain files. -- + makeMO() -- Compile the Portable Object files into the Machine Object stored in the right location. -- + printUsage -- Displays how to use this script from the command line -- + + Scriptexecution -- Runs when invoked from the command line -- + + +NOTE: this module uses GNU gettext utilities. + +You can get the gettext tools from the following sites: + + - `GNU FTP site for gettetx`_ where several versions (0.10.40, 0.11.2, 0.11.5 and 0.12.1) are available. + Note that you need to use `GNU libiconv`_ to use this. Get it from the `GNU + libiconv ftp site`_ and get version 1.9.1 or later. Get the Windows .ZIP + files and install the packages inside c:/gnu. All binaries will be stored + inside c:/gnu/bin. Just put c:/gnu/bin inside your PATH. You will need + the following files: + + - `gettext-runtime-0.12.1.bin.woe32.zip`_ + - `gettext-tools-0.12.1.bin.woe32.zip`_ + - `libiconv-1.9.1.bin.woe32.zip`_ + + +.. _GNU libiconv: http://www.gnu.org/software/libiconv/ +.. _GNU libiconv ftp site: http://www.ibiblio.org/pub/gnu/libiconv/ +.. _gettext-runtime-0.12.1.bin.woe32.zip: ftp://ftp.gnu.org/gnu/gettext/gettext-runtime-0.12.1.bin.woe32.zip +.. _gettext-tools-0.12.1.bin.woe32.zip: ftp://ftp.gnu.org/gnu/gettext/gettext-tools-0.12.1.bin.woe32.zip +.. _libiconv-1.9.1.bin.woe32.zip: http://www.ibiblio.org/pub/gnu/libiconv/libiconv-1.9.1.bin.woe32.zip + +""" +# ----------------------------------------------------------------------------- +# Module Import +# ------------- +# +import os +import sys +import wx +import re + +# ----------------------------------------------------------------------------- +# Global variables +# ---------------- +# + +__author__ = "Pierre Rouleau" +__version__= "$Revision: 1.5 $" + +# ----------------------------------------------------------------------------- + +def getlanguageDict(): + languageDict = {} + + for lang in [x for x in dir(wx) if x.startswith("LANGUAGE")]: + i = wx.Locale(wx.LANGUAGE_DEFAULT).GetLanguageInfo(getattr(wx, lang)) + if i: + languageDict[i.CanonicalName] = i.Description + + return languageDict + +XSD_STRING_MODEL = re.compile("]*\>") + +# ----------------------------------------------------------------------------- +# m a k e P O ( ) -- Build the Portable Object file for the application -- +# ^^^^^^^^^^^^^^^ +# +def makePO(applicationDirectoryPath, applicationDomain=None, verbose=0) : + """Build the Portable Object Template file for the application. + + makePO builds the .pot file for the application stored inside + a specified directory by running xgettext for all application source + files. It finds the name of all files by looking for a file called 'app.fil'. + If this file does not exists, makePo raises an IOError exception. + By default the application domain (the application + name) is the same as the directory name but it can be overridden by the + 'applicationDomain' argument. + + makePO always creates a new file called messages.pot. If it finds files + of the form app_xx.po where 'app' is the application name and 'xx' is one + of the ISO 639 two-letter language codes, makePO resynchronizes those + files with the latest extracted strings (now contained in messages.pot). + This process updates all line location number in the language-specific + .po files and may also create new entries for translation (or comment out + some). The .po file is not changed, instead a new file is created with + the .new extension appended to the name of the .po file. + + By default the function does not display what it is doing. Set the + verbose argument to 1 to force it to print its commands. + """ + + if applicationDomain is None: + applicationName = fileBaseOf(applicationDirectoryPath,withPath=0) + else: + applicationName = applicationDomain + currentDir = os.getcwd() + os.chdir(applicationDirectoryPath) + if not os.path.exists('app.fil'): + raise IOError(2,'No module file: app.fil') + + # Steps: + # Use xgettext to parse all application modules + # The following switches are used: + # + # -s : sort output by string content (easier to use when we need to merge several .po files) + # --files-from=app.fil : The list of files is taken from the file: app.fil + # --output= : specifies the name of the output file (using a .pot extension) + cmd = 'xgettext -s --no-wrap --language=Python --files-from=app.fil --output=messages.pot' + if verbose: print cmd + os.system(cmd) + + appfil_file = open("app.fil", 'r') + messages_file = open("messages.pot", 'a') + messages_file.write(""" +#: Extra XSD strings +""") + words_found = {} + for filepath in appfil_file.xreadlines(): + code_file = open(filepath.strip(), 'r') + for match in XSD_STRING_MODEL.finditer(code_file.read()): + word = match.group(1) + if not words_found.get(word, False): + words_found[word] = True + messages_file.write(""" +msgid "%s" +msgstr "" +"""%word) + code_file.close() + messages_file.close() + appfil_file.close() + + languageDict = getlanguageDict() + + for langCode in languageDict.keys(): + if langCode == 'en': + pass + else: + langPOfileName = "%s_%s.po" % (applicationName , langCode) + if os.path.exists(langPOfileName): + cmd = 'msgmerge -s --no-wrap "%s" messages.pot > "%s.new"' % (langPOfileName, langPOfileName) + if verbose: print cmd + os.system(cmd) + os.chdir(currentDir) + +# ----------------------------------------------------------------------------- +# c a t P O ( ) -- Concatenate one or several PO files with the application domain files. -- +# ^^^^^^^^^^^^^ +# +def catPO(applicationDirectoryPath, listOf_extraPo, applicationDomain=None, targetDir=None, verbose=0) : + """Concatenate one or several PO files with the application domain files. + """ + + if applicationDomain is None: + applicationName = fileBaseOf(applicationDirectoryPath,withPath=0) + else: + applicationName = applicationDomain + currentDir = os.getcwd() + os.chdir(applicationDirectoryPath) + + languageDict = getlanguageDict() + + for langCode in languageDict.keys(): + if langCode == 'en': + pass + else: + langPOfileName = "%s_%s.po" % (applicationName , langCode) + if os.path.exists(langPOfileName): + fileList = '' + for fileName in listOf_extraPo: + fileList += ("%s_%s.po " % (fileName,langCode)) + cmd = "msgcat -s --no-wrap %s %s > %s.cat" % (langPOfileName, fileList, langPOfileName) + if verbose: print cmd + os.system(cmd) + if targetDir is None: + pass + else: + mo_targetDir = "%s/%s/LC_MESSAGES" % (targetDir,langCode) + cmd = "msgfmt --output-file=%s/%s.mo %s_%s.po.cat" % (mo_targetDir,applicationName,applicationName,langCode) + if verbose: print cmd + os.system(cmd) + os.chdir(currentDir) + +# ----------------------------------------------------------------------------- +# m a k e M O ( ) -- Compile the Portable Object files into the Machine Object stored in the right location. -- +# ^^^^^^^^^^^^^^^ +# +def makeMO(applicationDirectoryPath,targetDir='./locale',applicationDomain=None, verbose=0, forceEnglish=0) : + """Compile the Portable Object files into the Machine Object stored in the right location. + + makeMO converts all translated language-specific PO files located inside + the application directory into the binary .MO files stored inside the + LC_MESSAGES sub-directory for the found locale files. + + makeMO searches for all files that have a name of the form 'app_xx.po' + inside the application directory specified by the first argument. The + 'app' is the application domain name (that can be specified by the + applicationDomain argument or is taken from the directory name). The 'xx' + corresponds to one of the ISO 639 two-letter language codes. + + makeMo stores the resulting files inside a sub-directory of `targetDir` + called xx/LC_MESSAGES where 'xx' corresponds to the 2-letter language + code. + """ + if targetDir is None: + targetDir = './locale' + if verbose: + print "Target directory for .mo files is: %s" % targetDir + + if applicationDomain is None: + applicationName = fileBaseOf(applicationDirectoryPath,withPath=0) + else: + applicationName = applicationDomain + currentDir = os.getcwd() + os.chdir(applicationDirectoryPath) + + languageDict = getlanguageDict() + + for langCode in languageDict.keys(): + if (langCode == 'en') and (forceEnglish==0): + pass + else: + langPOfileName = "%s_%s.po" % (applicationName , langCode) + if os.path.exists(langPOfileName): + mo_targetDir = "%s/%s/LC_MESSAGES" % (targetDir,langCode) + if not os.path.exists(mo_targetDir): + mkdir(mo_targetDir) + cmd = 'msgfmt --output-file="%s/%s.mo" "%s_%s.po"' % (mo_targetDir,applicationName,applicationName,langCode) + if verbose: print cmd + os.system(cmd) + os.chdir(currentDir) + +# ----------------------------------------------------------------------------- +# p r i n t U s a g e -- Displays how to use this script from the command line -- +# ^^^^^^^^^^^^^^^^^^^ +# +def printUsage(errorMsg=None) : + """Displays how to use this script from the command line.""" + print """ + ################################################################################## + # mki18n : Make internationalization files. # + # Uses the GNU gettext system to create PO (Portable Object) files # + # from source code, coimpile PO into MO (Machine Object) files. # + # Supports C,C++,Python source files. # + # # + # Usage: mki18n {OPTION} [appDirPath] # + # # + # Options: # + # -e : When -m is used, forces English .mo file creation # + # -h : prints this help # + # -m : make MO from existing PO files # + # -p : make PO, update PO files: Creates a new messages.pot # + # file. Creates a dom_xx.po.new for every existing # + # language specific .po file. ('xx' stands for the ISO639 # + # two-letter language code and 'dom' stands for the # + # application domain name). mki18n requires that you # + # write a 'app.fil' file which contains the list of all # + # source code to parse. # + # -v : verbose (prints comments while running) # + # --domain=appName : specifies the application domain name. By default # + # the directory name is used. # + # --moTarget=dir : specifies the directory where .mo files are stored. # + # If not specified, the target is './locale' # + # # + # You must specify one of the -p or -m option to perform the work. You can # + # specify the path of the target application. If you leave it out mki18n # + # will use the current directory as the application main directory. # + # # + ##################################################################################""" + if errorMsg: + print "\n ERROR: %s" % errorMsg + +# ----------------------------------------------------------------------------- +# f i l e B a s e O f ( ) -- Return base name of filename -- +# ^^^^^^^^^^^^^^^^^^^^^^^ +# +def fileBaseOf(filename,withPath=0) : + """fileBaseOf(filename,withPath) ---> string + + Return base name of filename. The returned string never includes the extension. + Use os.path.basename() to return the basename with the extension. The + second argument is optional. If specified and if set to 'true' (non zero) + the string returned contains the full path of the file name. Otherwise the + path is excluded. + + [Example] + >>> fn = 'd:/dev/telepath/tvapp/code/test.html' + >>> fileBaseOf(fn) + 'test' + >>> fileBaseOf(fn) + 'test' + >>> fileBaseOf(fn,1) + 'd:/dev/telepath/tvapp/code/test' + >>> fileBaseOf(fn,0) + 'test' + >>> fn = 'abcdef' + >>> fileBaseOf(fn) + 'abcdef' + >>> fileBaseOf(fn,1) + 'abcdef' + >>> fn = "abcdef." + >>> fileBaseOf(fn) + 'abcdef' + >>> fileBaseOf(fn,1) + 'abcdef' + """ + pos = filename.rfind('.') + if pos > 0: + filename = filename[:pos] + if withPath: + return filename + else: + return os.path.basename(filename) +# ----------------------------------------------------------------------------- +# m k d i r ( ) -- Create a directory (and possibly the entire tree) -- +# ^^^^^^^^^^^^^ +# +def mkdir(directory) : + """Create a directory (and possibly the entire tree). + + The os.mkdir() will fail to create a directory if one of the + directory in the specified path does not exist. mkdir() + solves this problem. It creates every intermediate directory + required to create the final path. Under Unix, the function + only supports forward slash separator, but under Windows and MacOS + the function supports the forward slash and the OS separator (backslash + under windows). + """ + + # translate the path separators + directory = unixpath(directory) + # build a list of all directory elements + aList = filter(lambda x: len(x)>0, directory.split('/')) + theLen = len(aList) + # if the first element is a Windows-style disk drive + # concatenate it with the first directory + if aList[0].endswith(':'): + if theLen > 1: + aList[1] = aList[0] + '/' + aList[1] + del aList[0] + theLen -= 1 + # if the original directory starts at root, + # make sure the first element of the list + # starts at root too + if directory[0] == '/': + aList[0] = '/' + aList[0] + # Now iterate through the list, check if the + # directory exists and if not create it + theDir = '' + for i in range(theLen): + theDir += aList[i] + if not os.path.exists(theDir): + os.mkdir(theDir) + theDir += '/' + +# ----------------------------------------------------------------------------- +# u n i x p a t h ( ) -- Return a path name that contains Unix separator. -- +# ^^^^^^^^^^^^^^^^^^^ +# +def unixpath(thePath) : + r"""Return a path name that contains Unix separator. + + [Example] + >>> unixpath(r"d:\test") + 'd:/test' + >>> unixpath("d:/test/file.txt") + 'd:/test/file.txt' + >>> + """ + thePath = os.path.normpath(thePath) + if os.sep == '/': + return thePath + else: + return thePath.replace(os.sep,'/') + +# ----------------------------------------------------------------------------- + +# S c r i p t e x e c u t i o n -- Runs when invoked from the command line -- +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# +if __name__ == "__main__": + import getopt # command line parsing + argc = len(sys.argv) + if argc == 1: + printUsage('Missing argument: specify at least one of -m or -p (or both).') + sys.exit(1) + # If there is some arguments, parse the command line + validOptions = "ehmpv" + validLongOptions = ['domain=', 'moTarget='] + option = {} + option['forceEnglish'] = 0 + option['mo'] = 0 + option['po'] = 0 + option['verbose'] = 0 + option['domain'] = None + option['moTarget'] = None + try: + optionList,pargs = getopt.getopt(sys.argv[1:],validOptions,validLongOptions) + except getopt.GetoptError, e: + printUsage(e[0]) + sys.exit(1) + for (opt,val) in optionList: + if (opt == '-h'): + printUsage() + sys.exit(0) + elif (opt == '-e'): option['forceEnglish'] = 1 + elif (opt == '-m'): option['mo'] = 1 + elif (opt == '-p'): option['po'] = 1 + elif (opt == '-v'): option['verbose'] = 1 + elif (opt == '--domain'): option['domain'] = val + elif (opt == '--moTarget'): option['moTarget'] = val + if len(pargs) == 0: + appDirPath = os.getcwd() + if option['verbose']: + print "No project directory given. Using current one: %s" % appDirPath + elif len(pargs) == 1: + appDirPath = pargs[0] + else: + printUsage('Too many arguments (%u). Use double quotes if you have space in directory name' % len(pargs)) + sys.exit(1) + if option['domain'] is None: + # If no domain specified, use the name of the target directory + option['domain'] = fileBaseOf(appDirPath) + if option['verbose']: + print "Application domain used is: '%s'" % option['domain'] + if option['po']: + try: + makePO(appDirPath,option['domain'],option['verbose']) + except IOError, e: + printUsage(e[1] + '\n You must write a file app.fil that contains the list of all files to parse.') + if option['mo']: + makeMO(appDirPath,option['moTarget'],option['domain'],option['verbose'],option['forceEnglish']) + sys.exit(1) + + +# ----------------------------------------------------------------------------- diff -r 75ae46b66315 -r 71c441104cac locale/fr_FR/LC_MESSAGES/Beremiz.mo Binary file locale/fr_FR/LC_MESSAGES/Beremiz.mo has changed diff -r 75ae46b66315 -r 71c441104cac locale/zh_CN/LC_MESSAGES/Beremiz.mo Binary file locale/zh_CN/LC_MESSAGES/Beremiz.mo has changed diff -r 75ae46b66315 -r 71c441104cac plugger.py --- a/plugger.py Wed Aug 12 16:23:59 2009 -0600 +++ b/plugger.py Thu Aug 13 11:37:38 2009 +0200 @@ -115,7 +115,10 @@ return os.path.join(self.PlugPath(PlugName), "plugin.xml") def PluginLibraryFilePath(self): - return os.path.join(os.path.join(os.path.split(__file__)[0], "plugins", self.PlugType, "pous.xml")) + 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: @@ -199,7 +202,7 @@ # Call the plugin specific OnPlugSave method result = self.OnPlugSave() if not result: - return "Error while saving \"%s\"\n"%self.PlugPath() + return _("Error while saving \"%s\"\n")%self.PlugPath() # mark plugin as saved self.ChangesToSave = False @@ -235,7 +238,7 @@ gen_result = self.PlugGenerate_C(buildpath, locations) PlugCFilesAndCFLAGS, PlugLDFLAGS, DoCalls = gen_result[:3] extra_files = gen_result[3:] - # if some files heve been generated put them in the list with their location + # if some files have been generated put them in the list with their location if PlugCFilesAndCFLAGS: LocationCFilesAndCFLAGS = [(self.GetCurrentLocation(), PlugCFilesAndCFLAGS, DoCalls)] else: @@ -275,12 +278,27 @@ return [{"name" : "%s POUs" % self.PlugType, "list": self.LibraryControler.Project.GetCustomBlockTypes()}] return [] + def ParentsBlockTypesFactory(self): + return self.PlugParent.ParentsBlockTypesFactory() + self.BlockTypesFactory() + + def PluginsBlockTypesFactory(self): + list = self.BlockTypesFactory() + for PlugChild in self.IterChilds(): + list += PlugChild.PluginsBlockTypesFactory() + return list + def STLibraryFactory(self): if self.LibraryControler is not None: program, errors, warnings = self.LibraryControler.GenerateProgram() - return program + 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: @@ -392,7 +410,7 @@ shutil.move(oldname, self.PlugPath()) # warn user he has two left hands if DesiredName != res: - self.logger.write_warning("A child names \"%s\" already exist -> \"%s\"\n"%(DesiredName,res)) + self.logger.write_warning(_("A child names \"%s\" already exist -> \"%s\"\n")%(DesiredName,res)) return res def FindNewIEC_Channel(self, DesiredChannel): @@ -417,14 +435,14 @@ if res < CurrentChannel: # Want to go down ? res -= 1 # Test for n-1 if res < 0 : - self.logger.write_warning("Cannot find lower free IEC channel than %d\n"%CurrentChannel) + self.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) if DesiredChannel != res: - self.logger.write_warning("A child with IEC channel %d already exist -> %d\n"%(DesiredChannel,res)) + self.logger.write_warning(_("A child with IEC channel %d already exist -> %d\n")%(DesiredChannel,res)) return res def OnPlugClose(self): @@ -462,7 +480,7 @@ try: PlugClass, PlugHelp = PlugChildsTypes[PlugType] except KeyError: - raise Exception, "Cannot create child %s of type %s "%(PlugName, PlugType) + 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: @@ -472,7 +490,7 @@ 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) + 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): @@ -500,7 +518,7 @@ _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()) + raise Exception, _("Project tree layout do not match plugin.xml %s!=%s ")%(NewPlugName, _self.BaseParams.getName()) # Now, self.PlugPath() should be OK @@ -541,6 +559,8 @@ if os.path.isfile(library_path): self.LibraryControler = PLCControler() self.LibraryControler.OpenXMLFile(library_path) + self.LibraryControler.ClearPluginTypes() + self.LibraryControler.AddPluginBlockList(self.ParentsBlockTypesFactory()) def LoadXMLParams(self, PlugName = None): methode_name = os.path.join(self.PlugPath(PlugName), "methods.py") @@ -555,7 +575,7 @@ self.MandatoryParams[1].loadXMLTree(basetree.childNodes[0]) basexmlfile.close() except Exception, exc: - self.logger.write_error("Couldn't load plugin base parameters %s :\n %s" % (PlugName, str(exc))) + self.logger.write_error(_("Couldn't load plugin base parameters %s :\n %s") % (PlugName, str(exc))) self.logger.write_error(traceback.format_exc()) # Get the xml tree @@ -566,7 +586,7 @@ self.PlugParams[1].loadXMLTree(tree.childNodes[0]) xmlfile.close() except Exception, exc: - self.logger.write_error("Couldn't load plugin parameters %s :\n %s" % (PlugName, str(exc))) + self.logger.write_error(_("Couldn't load plugin parameters %s :\n %s") % (PlugName, str(exc))) self.logger.write_error(traceback.format_exc()) def LoadChilds(self): @@ -578,7 +598,7 @@ try: self.PlugAddChild(pname, ptype) except Exception, exc: - self.logger.write_error("Could not add child \"%s\", type %s :\n%s\n"%(pname, ptype, str(exc))) + self.logger.write_error(_("Could not add child \"%s\", type %s :\n%s\n")%(pname, ptype, str(exc))) self.logger.write_error(traceback.format_exc()) def EnableMethod(self, method, value): @@ -777,7 +797,7 @@ """ # Verify that choosen folder is empty if not os.path.isdir(ProjectPath) or len(os.listdir(ProjectPath)) > 0: - return "Folder choosen isn't empty. You can't use it for a new project!" + return _("Folder choosen isn't empty. You can't use it for a new project!") dialog = ProjectDialog(self.AppFrame) if dialog.ShowModal() == wx.ID_OK: @@ -786,7 +806,7 @@ dialog.Destroy() else: dialog.Destroy() - return "Project not created" + return _("Project not created") # Create PLCOpen program self.CreateNewProject(values) @@ -812,7 +832,7 @@ # Verify that project contains a PLCOpen program plc_file = os.path.join(ProjectPath, "plc.xml") if not os.path.isfile(plc_file): - return "Folder choosen doesn't contain a program. It's not a valid project!" + return _("Folder choosen doesn't contain a program. It's not a valid project!") # Load PLCOpen file result = self.OpenXMLFile(plc_file) if result: @@ -854,18 +874,22 @@ def RefreshPluginsBlockLists(self): if getattr(self, "PluggedChilds", None) is not None: self.ClearPluginTypes() - self.AddPluginBlockList(self.BlockTypesFactory()) - for child in self.IterChilds(): - self.AddPluginBlockList(child.BlockTypesFactory()) + self.AddPluginBlockList(self.PluginsBlockTypesFactory()) if self.PLCEditor is not None: self.PLCEditor.RefreshEditor() + 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 ParentsBlockTypesFactory(self): + return self.BlockTypesFactory() + def _getBuildPath(self): if self.BuildPath is None: return os.path.join(self.ProjectPath, "build") @@ -886,14 +910,6 @@ # define name for IEC raw code file return os.path.join(self.PlugPath(), "raw_plc.st") - def _getPYTHONcodepath(self): - # define name for IEC raw code file - return os.path.join(self.PlugPath(), "runtime.py") - - def _getWXGLADEpath(self): - # define name for IEC raw code file - return os.path.join(self.PlugPath(), "hmi.wxg") - def GetLocations(self): locations = [] filepath = os.path.join(self._getBuildPath(),"LOCATED_VARIABLES.h") @@ -928,26 +944,21 @@ # Update PLCOpenEditor Plugin Block types before generate ST code self.RefreshPluginsBlockLists() - self.logger.write("Generating SoftPLC IEC-61131 ST/IL/SFC code...\n") + 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") + 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]) + self.logger.write_error(_("Error in ST/IL/SFC code generator :\n%s\n")%errors[0]) return False plc_file = open(self._getIECcodepath(), "w") - if getattr(self, "PluggedChilds", None) is not None: - # Add ST Library from plugins - plc_file.write(self.STLibraryFactory()) - plc_file.write("\n") - for child in self.IterChilds(): - plc_file.write(child.STLibraryFactory()) - plc_file.write("\n") + # 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") @@ -960,7 +971,7 @@ plc_file = open(self._getIECcodepath(), "a") plc_file.write(open(self._getIECgeneratedcodepath(), "r").read()) plc_file.close() - self.logger.write("Compiling IEC Program in to C code...\n") + self.logger.write(_("Compiling IEC Program in to 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( @@ -999,7 +1010,7 @@ f.close() - self.logger.write_error("Error : IEC to C compiler returned %d\n"%status) + self.logger.write_error(_("Error : IEC to C compiler returned %d\n")%status) return False # Now extract C files of stdout @@ -1007,11 +1018,11 @@ # 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 ressource must be declared in PLC !\n") + self.logger.write_error(_("Error : At least one configuration and one ressource 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") + 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 @@ -1034,7 +1045,7 @@ 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(_("Can't find module for target %s!\n")%targetname) self.logger.write_error(str(msg)) return None @@ -1054,15 +1065,6 @@ else: return None - 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) - ####################################################################### # # C CODE GENERATION METHODS @@ -1077,27 +1079,10 @@ @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND """ - res = ([(C_file_name, self.plcCFLAGS) + return ([(C_file_name, self.plcCFLAGS) for C_file_name in self.PLCGeneratedCFiles ], "", # no ldflags False) # do not expose retreive/publish calls - - pyfile=self._getPYTHONcodepath() - if os.path.exists(pyfile): - res += (("runtime.py", file(pyfile,"rb")),) - wxgfile=self._getWXGLADEpath() - if os.path.exists(wxgfile): - hmipyfile=os.path.join(self._getBuildPath(),"hmi.py") - if wx.Platform == '__WXMSW__': - wxgfile = "\"%s\""%wxgfile - _hmipyfile = "\"%s\""%hmipyfile - else: - _hmipyfile = hmipyfile - self.launch_wxglade(['-o', _hmipyfile, '-g', 'python', wxgfile], wait=True) - res += (("hmi.py", file(hmipyfile,"rb")),) - - return res - def ResetIECProgramsAndVariables(self): """ @@ -1158,7 +1143,7 @@ Idx=int(attrs["num"]) self._IECPathToIdx[IEC_path]=Idx except Exception,e: - self.logger.write_error("Cannot open/parse VARIABLES.csv!\n") + self.logger.write_error(_("Cannot open/parse VARIABLES.csv!\n")) self.logger.write_error(traceback.format_exc()) self.ResetIECProgramsAndVariables() return False @@ -1192,23 +1177,6 @@ return debug_code - def Generate_plc_python(self): - """ - Generate trace/debug code out of PLC variable list - """ - self.GetIECProgramsAndVariables() - - python_eval_fb_list = [] - for v in self._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 debug code - python_code = targets.code("plc_python") % { - "python_eval_fb_count": python_eval_fb_count} - return python_code - def Generate_plc_common_main(self): """ Use plugins layout given in LocationCFilesAndCFLAGS to @@ -1270,7 +1238,7 @@ self.EnableMethod("_Clean", True) self.logger.flush() - self.logger.write("Start build in %s\n" % buildpath) + self.logger.write(_("Start build in %s\n") % buildpath) # Generate SoftPLC IEC code IECGenRes = self._Generate_SoftPLC() @@ -1278,7 +1246,7 @@ # If IEC code gen fail, bail out. if not IECGenRes: - self.logger.write_error("IEC-61131-3 code generation failed !\n") + self.logger.write_error(_("IEC-61131-3 code generation failed !\n")) return False # Reset variable and program list that are parsed from @@ -1286,17 +1254,17 @@ self.ResetIECProgramsAndVariables() # Generate C code and compilation params from plugin hierarchy - self.logger.write("Generating plugins C code\n") + 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(_("Plugins code generation failed !\n")) self.logger.write_error(traceback.format_exc()) return False - # Get temprary directory path + # Get temporary directory path extrafilespath = self._getExtraFilesPath() # Remove old directory if os.path.exists(extrafilespath): @@ -1315,8 +1283,6 @@ for generator, filename, name in [ # debugger code (self.Generate_plc_debugger, "plc_debugger.c", "Debugger"), - # IEC<->python gateway code - (self.Generate_plc_python, "plc_python.c", "IEC-Python gateway"), # init/cleanup/retrieve/publish, run and align code (self.Generate_plc_common_main,"plc_common_main.c","Common runtime")]: try: @@ -1329,25 +1295,25 @@ # 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(name+_(" generation failed !\n")) self.logger.write_error(traceback.format_exc()) return False - self.logger.write("C code generated successfully.\n") + 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.logger.write_error(_("Fatal : cannot get builder.\n")) return False # Build try: if not builder.build() : - self.logger.write_error("C Build failed.\n") + 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(_("C Build crashed !\n")) self.logger.write_error(traceback.format_exc()) return False @@ -1388,32 +1354,6 @@ new_dialog.Show() - def _editPYTHONcode(self): - from PythonSTC import PythonCodePanel - new_dialog = wx.Frame(self.AppFrame) - - PYTHON_viewer = PythonCodePanel(new_dialog, self.AppFrame) - #ST_viewer.Enable(False) - pyfile=self._getPYTHONcodepath() - PYTHON_viewer.LoadSourceFile(pyfile) - - new_dialog.Show() - - def _editWXGLADE(self): - wxg_filename = self._getWXGLADEpath() - if not os.path.exists(wxg_filename): - open(wxg_filename,"w").write(""" - - - - frame_1 - - -""") - if wx.Platform == '__WXMSW__': - wxg_filename = "\"%s\""%wxg_filename - self.launch_wxglade([wxg_filename]) - def _EditPLC(self): if self.PLCEditor is None: self.RefreshPluginsBlockLists() @@ -1428,10 +1368,10 @@ def _Clean(self): if os.path.isdir(os.path.join(self._getBuildPath())): - self.logger.write("Cleaning the build directory\n") + 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.logger.write_error(_("Build directory already clean\n")) self.ShowMethod("_showIECcode", False) self.EnableMethod("_Clean", False) # kill the builder @@ -1446,28 +1386,29 @@ status = self._connector.GetPLCstatus() else: status = "Disconnected" + _ = lambda x : x for args in { - "Started":[("_Run", False), - ("_Debug", False), - ("_Stop", True)], - "Stopped":[("_Run", True), - ("_Debug", True), - ("_Stop", False)], - "Empty": [("_Run", False), - ("_Debug", False), - ("_Stop", False)], - "Dirty": [("_Run", True), - ("_Debug", True), - ("_Stop", False)], - "Broken": [("_Run", True), - ("_Debug", True), - ("_Stop", False)], - "Disconnected": [("_Run", False), - ("_Debug", False), - ("_Stop", False), - ("_Transfer", False), - ("_Connect", True), - ("_Disconnect", False)], + _("Started"): [("_Run", False), + ("_Debug", False), + ("_Stop", True)], + _("Stopped"): [("_Run", True), + ("_Debug", True), + ("_Stop", False)], + _("Empty"): [("_Run", False), + ("_Debug", False), + ("_Stop", False)], + _("Dirty"): [("_Run", True), + ("_Debug", True), + ("_Stop", False)], + _("Broken"): [("_Run", True), + ("_Debug", True), + ("_Stop", False)], + _("Disconnected"):[("_Run", False), + ("_Debug", False), + ("_Stop", False), + ("_Transfer", False), + ("_Connect", True), + ("_Disconnect", False)], }.get(status,[]): self.ShowMethod(*args) return status @@ -1478,7 +1419,11 @@ current_status = self.UpdateMethodsFromPLCStatus() if current_status != self.previous_plcstate: self.previous_plcstate = current_status - self.StatusPrint.get(current_status, self.logger.write)("PLC is %s\n"%current_status) + if current_status is not None: + status = _(current_status) + else: + status = "" + self.StatusPrint.get(current_status, self.logger.write)(_("PLC is %s\n")%status) self.AppFrame.RefreshAll() def _Run(self): @@ -1509,7 +1454,7 @@ Idxs.append(Idx) self.TracedIECPath.append(IECPath) else: - self.logger.write_warning("Debug : Unknown variable %s\n"%IECPath) + self.logger.write_warning(_("Debug : Unknown variable %s\n")%IECPath) for IECPathToPop in IECPathsToPop: self.IECdebug_datas.pop(IECPathToPop) @@ -1604,12 +1549,12 @@ self.CallWeakcallables("__tick__", "NewDataAvailable") elif debug_vars is not None: wx.CallAfter(self.logger.write_warning, - "Debug data not coherent %d != %d\n"%(len(debug_vars), len(self.TracedIECPath))) + _("Debug data not coherent %d != %d\n")%(len(debug_vars), len(self.TracedIECPath))) elif debug_tick == -1: #wx.CallAfter(self.logger.write, "Debugger unavailable\n") pass else: - wx.CallAfter(self.logger.write, "Debugger disabled\n") + wx.CallAfter(self.logger.write, _("Debugger disabled\n")) self.debug_break = True self.IECdebug_lock.release() @@ -1617,7 +1562,7 @@ self.debug_break = True self.DebugThread.join(timeout=1) if self.DebugThread.isAlive(): - self.logger.write_warning("Debug Thread couldn't be killed") + self.logger.write_warning(_("Debug Thread couldn't be killed")) self.DebugThread = None def _Debug(self): @@ -1626,7 +1571,7 @@ """ if self.GetIECProgramsAndVariables(): self._connector.StartPLC(debug=True) - self.logger.write("Starting PLC (debug mode)\n") + self.logger.write(_("Starting PLC (debug mode)\n")) if self.PLCDebug is None: self.RefreshPluginsBlockLists() def _onclose(): @@ -1639,7 +1584,7 @@ self.DebugThread = Thread(target=self.DebugThreadProc) self.DebugThread.start() else: - self.logger.write_error("Couldn't start PLC debug !\n") + self.logger.write_error(_("Couldn't start PLC debug !\n")) self.UpdateMethodsFromPLCStatus() @@ -1665,17 +1610,17 @@ Stop PLC """ if self.DebugThread is not None: - self.logger.write("Stopping debug\n") + self.logger.write(_("Stopping debug\n")) self.KillDebugThread() if not self._connector.StopPLC(): - self.logger.write_error("Couldn't stop PLC !\n") + self.logger.write_error(_("Couldn't stop PLC !\n")) 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") + self.logger.write_error(_("Already connected. Please disconnect\n")) return # Get connector uri @@ -1702,13 +1647,13 @@ try: self._connector = connectors.ConnectorFactory(uri, self) except Exception, msg: - self.logger.write_error("Exception while connecting %s!\n"%uri) + 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) + self.logger.write_error(_("Connection failed to %s!\n")%uri) else: self.ShowMethod("_Connect", False) self.ShowMethod("_Disconnect", True) @@ -1718,7 +1663,11 @@ # Init with actual PLC status and print it self.previous_plcstate = self.UpdateMethodsFromPLCStatus() - self.logger.write("PLC is %s\n"%self.previous_plcstate) + 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) @@ -1732,16 +1681,16 @@ if MD5 is not None: if not self._connector.MatchMD5(MD5): self.logger.write_warning( - "Latest build do not match with target, please transfer.\n") + _("Latest build do not match with target, please transfer.\n")) self.EnableMethod("_Transfer", True) else: self.logger.write( - "Latest build match target, no transfer needed.\n") + _("Latest build match target, no transfer needed.\n")) self.EnableMethod("_Transfer", True) #self.EnableMethod("_Transfer", False) else: self.logger.write_warning( - "Cannot compare latest build to target. Please build.\n") + _("Cannot compare latest build to target. Please build.\n")) self.EnableMethod("_Transfer", False) @@ -1756,13 +1705,13 @@ # 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") + 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 match current target. Transfering anyway...\n") + _("Latest build already match current target. Transfering anyway...\n")) # Get temprary directory path extrafilespath = self._getExtraFilesPath() @@ -1782,75 +1731,67 @@ self.PLCDebug = None self.UnsubscribeAllDebugIECVariable() self.ProgramTransferred() - self.logger.write("Transfer completed successfully.\n") + self.logger.write(_("Transfer completed successfully.\n")) else: - self.logger.write_error("Transfer failed\n") + self.logger.write_error(_("Transfer failed\n")) else: - self.logger.write_error("No PLC to transfer (did build success ?)\n") + self.logger.write_error(_("No PLC to transfer (did build success ?)\n")) self.UpdateMethodsFromPLCStatus() PluginMethods = [ {"bitmap" : opjimg("editPLC"), - "name" : "Edit PLC", - "tooltip" : "Edit PLC program with PLCOpenEditor", + "name" : _("Edit PLC"), + "tooltip" : _("Edit PLC program with PLCOpenEditor"), "method" : "_EditPLC"}, {"bitmap" : opjimg("Build"), - "name" : "Build", - "tooltip" : "Build project into build folder", + "name" : _("Build"), + "tooltip" : _("Build project into build folder"), "method" : "_build"}, {"bitmap" : opjimg("Clean"), - "name" : "Clean", + "name" : _("Clean"), "enabled" : False, - "tooltip" : "Clean project build folder", + "tooltip" : _("Clean project build folder"), "method" : "_Clean"}, {"bitmap" : opjimg("Run"), - "name" : "Run", + "name" : _("Run"), "shown" : False, - "tooltip" : "Start PLC", + "tooltip" : _("Start PLC"), "method" : "_Run"}, {"bitmap" : opjimg("Debug"), - "name" : "Debug", + "name" : _("Debug"), "shown" : False, - "tooltip" : "Start PLC (debug mode)", + "tooltip" : _("Start PLC (debug mode)"), "method" : "_Debug"}, # {"bitmap" : opjimg("Debug"), # "name" : "Do_Test_Debug", # "tooltip" : "Test debug mode)", # "method" : "_Do_Test_Debug"}, {"bitmap" : opjimg("Stop"), - "name" : "Stop", + "name" : _("Stop"), "shown" : False, - "tooltip" : "Stop Running PLC", + "tooltip" : _("Stop Running PLC"), "method" : "_Stop"}, {"bitmap" : opjimg("Connect"), - "name" : "Connect", - "tooltip" : "Connect to the target PLC", + "name" : _("Connect"), + "tooltip" : _("Connect to the target PLC"), "method" : "_Connect"}, {"bitmap" : opjimg("Transfer"), - "name" : "Transfer", + "name" : _("Transfer"), "shown" : False, - "tooltip" : "Transfer PLC", + "tooltip" : _("Transfer PLC"), "method" : "_Transfer"}, {"bitmap" : opjimg("Disconnect"), - "name" : "Disconnect", + "name" : _("Disconnect"), "shown" : False, - "tooltip" : "Disconnect from PLC", + "tooltip" : _("Disconnect from PLC"), "method" : "_Disconnect"}, {"bitmap" : opjimg("ShowIECcode"), - "name" : "Show code", + "name" : _("Show code"), "shown" : False, - "tooltip" : "Show IEC code generated by PLCGenerator", + "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", + "name" : _("Raw IEC code"), + "tooltip" : _("Edit raw IEC code added to code generated by PLCGenerator"), "method" : "_editIECrawcode"}, - {"bitmap" : opjimg("editPYTHONcode"), - "name" : "Python code", - "tooltip" : "Write Python runtime code, for use with python_eval FBs", - "method" : "_editPYTHONcode"}, - {"bitmap" : opjimg("editWXGLADE"), - "name" : "WXGLADE GUI", - "tooltip" : "Edit a WxWidgets GUI with WXGlade", - "method" : "_editWXGLADE"}, ] diff -r 75ae46b66315 -r 71c441104cac plugins/c_ext/c_ext.py --- a/plugins/c_ext/c_ext.py Wed Aug 12 16:23:59 2009 -0600 +++ b/plugins/c_ext/c_ext.py Thu Aug 13 11:37:38 2009 +0200 @@ -201,8 +201,8 @@ PluginMethods = [ {"bitmap" : os.path.join("images", "EditCfile"), - "name" : "Edit C File", - "tooltip" : "Edit C File", + "name" : _("Edit C File"), + "tooltip" : _("Edit C File"), "method" : "_OpenView"}, ] diff -r 75ae46b66315 -r 71c441104cac plugins/canfestival/canfestival.py --- a/plugins/canfestival/canfestival.py Wed Aug 12 16:23:59 2009 -0600 +++ b/plugins/canfestival/canfestival.py Thu Aug 13 11:37:38 2009 +0200 @@ -183,12 +183,12 @@ buildpath = self._getBuildPath() # Eventually create build dir if not os.path.exists(buildpath): - self.logger.write_error("Error: No PLC built\n") + self.logger.write_error(_("Error: No PLC built\n")) return masterpath = os.path.join(buildpath, "MasterGenerated.od") if not os.path.exists(masterpath): - self.logger.write_error("Error: No Master generated\n") + self.logger.write_error(_("Error: No Master generated\n")) return new_dialog = objdictedit(None, filesOpen=[masterpath]) @@ -196,11 +196,11 @@ PluginMethods = [ {"bitmap" : os.path.join("images", "NetworkEdit"), - "name" : "Edit network", - "tooltip" : "Edit CanOpen Network with NetworkEdit", + "name" : _("Edit network"), + "tooltip" : _("Edit CanOpen Network with NetworkEdit"), "method" : "_OpenView"}, - {"name" : "Show Master", - "tooltip" : "Show Master generated by config_utils", + {"name" : _("Show Master"), + "tooltip" : _("Show Master generated by config_utils"), "method" : "_ShowMasterGenerated"} ] diff -r 75ae46b66315 -r 71c441104cac plugins/canfestival/config_utils.py --- a/plugins/canfestival/config_utils.py Wed Aug 12 16:23:59 2009 -0600 +++ b/plugins/canfestival/config_utils.py Thu Aug 13 11:37:38 2009 +0200 @@ -332,13 +332,13 @@ name = location["NAME"] if name in self.IECLocations: if self.IECLocations[name]["type"] != COlocationtype: - raise PDOmappingException, "Conflict type for location \"%s\"" % name + raise PDOmappingException, _("Conflict type 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) + raise PDOmappingException, _("Bad location size : %s") % str(loc) elif len(loc) == 2: continue @@ -351,14 +351,14 @@ # 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) + 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) + 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) @@ -368,19 +368,19 @@ 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) + 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) + 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) + raise PDOmappingException, _("Not PDO mappable variable : '%s' (ID:%d,Idx:%x,sIdx:%x))") % (name,nodeid,index,subindex) #------------------------------------------------------------------------------- # Search for locations already mapped @@ -452,7 +452,7 @@ pdomapping = [] result = self.GetEmptyPDO(nodeid, pdotype) if result is None: - raise PDOmappingException, "Impossible to define PDO mapping for node %02x"%nodeid + raise PDOmappingException, _("Impossible to define PDO mapping for node %02x") % nodeid pdoindex, pdocobid, pdonbparams = result for name, loc_infos in locations[pdotype]: pdosize += loc_infos["size"] @@ -466,7 +466,7 @@ pdomapping = [(name, loc_infos)] result = self.GetEmptyPDO(nodeid, pdotype, pdoindex + 1) if result is None: - raise PDOmappingException, "Impossible to define PDO mapping for node %02x"%nodeid + raise PDOmappingException, _("Impossible to define PDO mapping for node %02x") % nodeid pdoindex, pdocobid, pdonbparams = result else: pdomapping.append((name, loc_infos)) @@ -614,13 +614,13 @@ name = location["NAME"] if name in IECLocations: if IECLocations[name] != COlocationtype: - raise PDOmappingException, "Conflict type for location \"%s\"" % name + raise PDOmappingException, _("Conflict type 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) + raise PDOmappingException, _("Bad location size : %s") % str(loc) elif len(loc) != 2: continue @@ -629,12 +629,12 @@ # 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) + 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) + 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 diff -r 75ae46b66315 -r 71c441104cac plugins/python/PythonEditor.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/PythonEditor.py Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,594 @@ +import wx, wx.grid +import wx.stc as stc +import keyword + +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, + } + +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_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(stc.StyledTextCtrl): + + fold_symbols = 3 + + def __init__(self, parent, window, controler): + stc.StyledTextCtrl.__init__(self, parent, ID_PYTHONEDITOR, wx.DefaultPosition, + wx.DefaultSize, 0) + + 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_PYTHON) + self.SetKeyWords(0, " ".join(keyword.kwlist)) + + 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) + + # Set up the numbers in the margin for margin #1 + self.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER) + # Reasonable value for, say, 4-5 digits using a mono font (40 pix) + self.SetMarginWidth(1, 40) + + # Setup a margin to hold fold markers + 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) + + # Global default style + if wx.Platform == '__WXMSW__': + self.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.StyleSetSpec(stc.STC_STYLE_DEFAULT, + 'fore:#000000,back:#FFFFFF,face:Monaco') + else: + defsize = wx.SystemSettings.GetFont(wx.SYS_ANSI_FIXED_FONT).GetPointSize() + self.StyleSetSpec(stc.STC_STYLE_DEFAULT, + 'fore:#000000,back:#FFFFFF,face:Courier,size:%d'%defsize) + + # Clear styles and revert to default. + self.StyleClearAll() + + # Following style specs only indicate differences from default. + # The rest remains unchanged. + + # Line numbers in margin + self.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2') + # Highlighted brace + self.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00') + # Unmatched brace + self.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000') + # Indentation guide + self.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD") + + # Python styles + self.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000') + # Comments + self.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, 'fore:#008000,back:#F0FFF0') + self.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0') + # Numbers + self.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080') + # Strings and characters + self.StyleSetSpec(wx.stc.STC_P_STRING, 'fore:#800080') + self.StyleSetSpec(wx.stc.STC_P_CHARACTER, 'fore:#800080') + # Keywords + self.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold') + # Triple quotes + self.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA') + self.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA') + # Class names + self.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold') + # Function names + self.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold') + # Operators + self.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.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, 'fore:#000000') + + # Caret color + self.SetCaretForeground("BLUE") + # Selection background + self.SetSelBackground(1, '#66CCFF') + + self.SetSelBackground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)) + self.SetSelForeground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)) + + # 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 and tab stuff + self.SetIndent(4) # Proscribed indent size for wx + self.SetIndentationGuides(True) # Show indent guides + self.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space + self.SetTabIndents(True) # Tab key indents + self.SetTabWidth(4) # Proscribed tab size for wx + self.SetUseTabs(False) # Use spaces rather than tabs, or + # TabTimmy will complain! + # White space + self.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.SetEOLMode(wx.stc.STC_EOL_LF) + self.SetViewEOL(False) + + # No right-edge mode indicator + self.SetEdgeMode(stc.STC_EDGE_NONE) + + self.Controler = controler + self.ParentWindow = window + + self.DisableEvents = True + 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_PYTHONEDITOR) + self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) + self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_PYTHONEDITOR) + + 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()) + 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()) + event.Skip() + + def OnDoDrop(self, event): + self.ResetBuffer() + wx.CallAfter(self.RefreshModel) + event.Skip() + + def IsViewing(self, name): + return self.Name == name + + # Buffer the last model state + def RefreshBuffer(self): + self.Controler.BufferPython() + if self.ParentWindow: + self.ParentWindow.RefreshTitle() + self.ParentWindow.RefreshEditMenu() + + def StartBuffering(self): + self.Controler.StartBuffering() + if self.ParentWindow: + self.ParentWindow.RefreshTitle() + self.ParentWindow.RefreshEditMenu() + + 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.GetPythonCode() + 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 RefreshModel(self): + self.Controler.SetPythonCode(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 keyword.kwlist])) + else: + wx.CallAfter(self.RefreshModel) + 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 + + +#------------------------------------------------------------------------------- +# PythonEditor Main Frame Class +#------------------------------------------------------------------------------- + + +[ID_PYTHONEDITORFRAME, +] = [wx.NewId() for _init_ctrls in range(1)] + +class PythonEditorFrame(wx.Frame): + + 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_EditMenu_Items(self, parent): + AppendMenu(parent, help='', id=wx.ID_REFRESH, + kind=wx.ITEM_NORMAL, text=u'Refresh\tCTRL+R') + AppendMenu(parent, help='', id=wx.ID_UNDO, + kind=wx.ITEM_NORMAL, text=u'Undo\tCTRL+Z') + AppendMenu(parent, help='', id=wx.ID_REDO, + kind=wx.ITEM_NORMAL, text=u'Redo\tCTRL+Y') + self.Bind(wx.EVT_MENU, self.OnRefreshMenu, id=wx.ID_REFRESH) + self.Bind(wx.EVT_MENU, self.OnUndoMenu, id=wx.ID_UNDO) + self.Bind(wx.EVT_MENU, self.OnRedoMenu, id=wx.ID_REDO) + + def _init_coll_MenuBar_Menus(self, parent): + parent.Append(menu=self.EditMenu, title=u'&Edit') + + def _init_utils(self): + self.MenuBar = wx.MenuBar() + + self.EditMenu = wx.Menu(title='') + + self._init_coll_MenuBar_Menus(self.MenuBar) + self._init_coll_EditMenu_Items(self.EditMenu) + + def _init_ctrls(self, prnt): + wx.Frame.__init__(self, id=ID_PYTHONEDITORFRAME, name=u'PythonEditor', + parent=prnt, pos=wx.DefaultPosition, size=wx.Size(800, 650), + style=wx.DEFAULT_FRAME_STYLE, title=u'PythonEditor') + self._init_utils() + self.SetClientSize(wx.Size(1000, 600)) + self.SetMenuBar(self.MenuBar) + self.Bind(wx.EVT_CLOSE, self.OnCloseFrame) + + self.Bind(wx.EVT_MENU, self.OnSaveMenu, id=wx.ID_SAVE) + accel = wx.AcceleratorTable([wx.AcceleratorEntry(wx.ACCEL_CTRL, 83, wx.ID_SAVE)]) + self.SetAcceleratorTable(accel) + + if wx.VERSION >= (2, 8, 0): + self.AUIManager = wx.aui.AuiManager(self) + self.AUIManager.SetDockSizeConstraint(0.5, 0.5) + + self.PythonEdited = PythonEditor(self, self, self.Controler) + if wx.VERSION < (2, 8, 0): + self.MainSizer = wx.BoxSizer(wx.VERTICAL) + self.MainSizer.AddWindow(self.PythonEdited, 0, border=0, flag=wx.GROW) + self.SetSizer(self.MainSizer) + else: + self.AUIManager.AddPane(self.PythonEdited, wx.aui.AuiPaneInfo().CentrePane()) + + self.StatusBar = wx.StatusBar( name='HelpBar', + parent=self, style=wx.ST_SIZEGRIP) + self.SetStatusBar(self.StatusBar) + + if wx.VERSION >= (2, 8, 0): + self.AUIManager.Update() + + def __init__(self, parent, controler): + self.Controler = controler + + self._init_ctrls(parent) + + self.PythonEdited.RefreshView() + self.RefreshTitle() + self.RefreshEditMenu() + + def OnCloseFrame(self, event): + if wx.VERSION >= (2, 8, 0): + self.AUIManager.UnInit() + if getattr(self, "_onclose", None) is not None: + self._onclose() + event.Skip() + + def OnSaveMenu(self, event): + if getattr(self, "_onsave", None) != None: + self._onsave() + self.RefreshTitle() + self.RefreshEditMenu() + event.Skip() + + def RefreshTitle(self): + self.SetTitle("PythonEditor - %s"%self.Controler.GetFilename()) + +#------------------------------------------------------------------------------- +# Edit Project Menu Functions +#------------------------------------------------------------------------------- + + def RefreshEditMenu(self): + undo, redo = self.Controler.GetBufferState() + self.EditMenu.Enable(wx.ID_UNDO, undo) + self.EditMenu.Enable(wx.ID_REDO, redo) + + def OnRefreshMenu(self, event): + self.PythonEdited.RefreshView() + event.Skip() + + def OnUndoMenu(self, event): + self.Controler.LoadPrevious() + self.PythonEdited.RefreshView() + self.RefreshTitle() + self.RefreshEditMenu() + event.Skip() + + def OnRedoMenu(self, event): + self.Controler.LoadNext() + self.PythonEdited.RefreshView() + self.RefreshTitle() + self.RefreshEditMenu() + event.Skip() + diff -r 75ae46b66315 -r 71c441104cac plugins/python/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/README Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,1 @@ +Asynchronous \ No newline at end of file diff -r 75ae46b66315 -r 71c441104cac plugins/python/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/__init__.py Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,1 @@ +from python import * diff -r 75ae46b66315 -r 71c441104cac plugins/python/modules/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/__init__.py Thu Aug 13 11:37:38 2009 +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 75ae46b66315 -r 71c441104cac plugins/python/modules/svgui/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/svgui/README Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,1 @@ +SVGUI HMI \ No newline at end of file diff -r 75ae46b66315 -r 71c441104cac plugins/python/modules/svgui/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/svgui/__init__.py Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,1 @@ +from svgui import * diff -r 75ae46b66315 -r 71c441104cac plugins/python/modules/svgui/livesvg.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/svgui/livesvg.js Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,71 @@ +// import Nevow.Athena +// import Divmod.Base +function init() { + Nevow.Athena.Widget.fromAthenaID(1).callRemote('HMIexec', 'initClient'); +} + +function updateAttr(id, param, value) { + Nevow.Athena.Widget.fromAthenaID(1).callRemote('HMIexec', 'setattr', id, param, value); +} + +var svguiWidgets={}; + +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); + newState = json_parse(dataReceived.kwargs).state + svguiWidgets[dataReceived.back_id].updateState(newState); + //console.log("OBJET : " + dataReceived.back_id + " STATE : " + newState); + }, + + function SvguiButton(self,elt_back, args){ + var btn = new svguilib.button(self, elt_back, args.sele_id, args.toggle, args.state, args.active); + return btn; + }, + + function SvguiTextCtrl(self, elt_back, args){ + var txtCtrl = new svguilib.textControl(self, elt_back, args.state); + return txtCtrl; + }, + + function init(self, arg1){ + //console.log("Object received : " + arg1); + for (ind in arg1) { + gad = json_parse(arg1[ind]); + args = json_parse(gad.kwargs); + gadget = self[gad.__class__](gad.back_id, args); + svguiWidgets[gadget.back_elt.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); + } +); + +Divmod.Base.addLoadEvent(init); \ No newline at end of file diff -r 75ae46b66315 -r 71c441104cac plugins/python/modules/svgui/pous.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/svgui/pous.xml Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,1061 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 'int(SVGUI("SvguiButton","' + + + + + + + '",sele_id="' + + + + + + + '",state=' + + + + + + + ',toggle=True,active=True))' + + + + + + + BOOL#1 + + + + + + + back_id + + + + + + + sele_id + + + + + + + set_state + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + current_state + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 'SVGUI("SvguiTextCtrl","' + + + + + + + back_id + + + + + + + state + + + + + + + '",state="' + + + + + + + '")' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + code + + + + + + + BOOL#1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 'int(SVGUI("SvguiButton","' + + + + + + + '",sele_id="' + + + + + + + '",state=' + + + + + + + ',active=True))' + + + + + + + BOOL#1 + + + + + + + back_id + + + + + + + sele_id + + + + + + + set_state + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + current_state + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 'SVGUI("SvguiButton","' + + + + + + + '",sele_id="' + + + + + + + back_id + + + + + + + sele_id + + + + + + + ',toggle=True)' + + + + + + + '", state=' + + + + + + + state + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + BOOL#1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 75ae46b66315 -r 71c441104cac plugins/python/modules/svgui/pyjs/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/svgui/pyjs/__init__.py Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,2 @@ +from pyjs import * + diff -r 75ae46b66315 -r 71c441104cac plugins/python/modules/svgui/pyjs/build.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/svgui/pyjs/build.py Thu Aug 13 11:37:38 2009 +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 75ae46b66315 -r 71c441104cac plugins/python/modules/svgui/pyjs/jsonrpc/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/svgui/pyjs/jsonrpc/README.txt Thu Aug 13 11:37:38 2009 +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 75ae46b66315 -r 71c441104cac plugins/python/modules/svgui/pyjs/jsonrpc/django/jsonrpc.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/svgui/pyjs/jsonrpc/django/jsonrpc.py Thu Aug 13 11:37:38 2009 +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 75ae46b66315 -r 71c441104cac plugins/python/modules/svgui/pyjs/jsonrpc/jsonrpc.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/svgui/pyjs/jsonrpc/jsonrpc.py Thu Aug 13 11:37:38 2009 +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 75ae46b66315 -r 71c441104cac plugins/python/modules/svgui/pyjs/jsonrpc/web2py/jsonrpc.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/svgui/pyjs/jsonrpc/web2py/jsonrpc.py Thu Aug 13 11:37:38 2009 +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 75ae46b66315 -r 71c441104cac plugins/python/modules/svgui/pyjs/lib/_pyjs.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/svgui/pyjs/lib/_pyjs.js Thu Aug 13 11:37:38 2009 +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 75ae46b66315 -r 71c441104cac plugins/python/modules/svgui/pyjs/lib/json.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/svgui/pyjs/lib/json.js Thu Aug 13 11:37:38 2009 +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 75ae46b66315 -r 71c441104cac plugins/python/modules/svgui/pyjs/lib/pyjslib.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/svgui/pyjs/lib/pyjslib.py Thu Aug 13 11:37:38 2009 +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 75ae46b66315 -r 71c441104cac plugins/python/modules/svgui/pyjs/lib/sys.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/svgui/pyjs/lib/sys.py Thu Aug 13 11:37:38 2009 +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 75ae46b66315 -r 71c441104cac plugins/python/modules/svgui/pyjs/pyjs.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/svgui/pyjs/pyjs.py Thu Aug 13 11:37:38 2009 +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 75ae46b66315 -r 71c441104cac plugins/python/modules/svgui/svgui.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/svgui/svgui.py Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,105 @@ +import wx +import os, sys + +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(): + print "SVGUI start" + website.LoadHMI(%(svgui_class)s, %(jsmodules)s) + +def _runtime_%(location)s_cleanup(): + print "SVGUI stop" + 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.logger.write_error("No such SVG file: %s\n"%svgpath) + dialog.Destroy() + + def _StartInkscape(self): + svgfile = self._getSVGpath() + if not os.path.isfile(svgfile): + svgfile = None + open_svg(svgfile) diff -r 75ae46b66315 -r 71c441104cac plugins/python/modules/svgui/svgui_server.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/svgui/svgui_server.py Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,84 @@ +#!/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={} + +class SvguiWidget: + + def __init__(self, classname, back_id, **kwargs): + self.classname = classname + self.back_id = back_id + self.attrs = kwargs.copy() + self.lastattrs = kwargs.copy() + self.inhibit = False + self.changed = False + + def setattr(self, attrname, value): + self.attrs[attrname] = value + + def getattr(self, attrname): + return self.args.get(attrname, None) + + def update(self, **kwargs): + for attrname, value in kwargs.iteritems(): + if self.lastattrs.get(attrname, None) != value: + self.changed = True + self.attrs[attrname] = value + self.lastattrs[attrname] = value + interface = website.getHMI() + if interface is not None and self.changed and not self.inhibit: + self.changed = False + interface.sendData(self) + + return self.attrs["state"] + +def convert_to_builtin_type(obj): + # Convert objects to a dictionary of their representation + d = { '__class__':obj.classname, + 'back_id':obj.back_id, + 'kwargs':json.dumps(obj.attrs), + } + return d + +def dataToSend(): + gadgets = [] + for gadget in svguiWidgets.values(): + gadgets.append(unicode(json.dumps(gadget, default=convert_to_builtin_type, indent=2), 'ascii')) + return gadgets + + +class SVGUI_HMI(athena.LiveElement): + jsClass = u"LiveSVGPage.LiveSVGWidget" + + docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[ + tags.xml(loaders.xmlfile(os.path.join(WorkingDir, svgfile))), + ]) + + def sendData(self,data): + objDefer = self.callRemote('receiveData',unicode(json.dumps(data, default=convert_to_builtin_type, indent=2), 'ascii')) + + def initClient(self): + self.callRemote('init', dataToSend()) + + def setattr(self, id, attrname, value): + svguiWidgets[id].setattr(attrname, value) + +def SVGUI(*args, **kwargs): + classname, back_id = args + gad = svguiWidgets.get(back_id, None) + if gad is None: + gad = SvguiWidget(classname, back_id, **kwargs) + svguiWidgets[back_id] = gad + gadget = [unicode(json.dumps(gad, default=convert_to_builtin_type, indent=2), 'ascii')] + interface = website.getHMI() + if interface is not None: + interface.callRemote('init', gadget) + + return gad.update(**kwargs) diff -r 75ae46b66315 -r 71c441104cac plugins/python/modules/svgui/svguilib.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/svgui/svguilib.py Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,106 @@ + +class button: + + def __init__(self, parent, back_id, sele_id, toggle, state, active): + self.parent = parent + self.back_elt = getSVGElementById(back_id) + self.sele_elt = getSVGElementById(sele_id) + self.toggle = toggle + self.state = state + self.active = active + self.dragging = False + if toggle: + self.up = not 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("visibility", "hidden") + self.back_elt.setAttribute("visibility", "visible") + else: + self.sele_elt.setAttribute("visibility", "visible") + self.back_elt.setAttribute("visibility", "hidden") + + def updateState(self, value): + self.up = not value + 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.back_elt.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.back_elt.id, 'state', self.state) + elif not self.toggle: + self.up = True + self.state = False + updateAttr(self.back_elt.id, 'state', self.state) + self.updateElements() + self.dragging = False + +class textControl: + + def __init__(self, parent, back_id, state): + self.parent = parent + self.back_elt = getSVGElementById(back_id) + self.state = state + self.setValue(self.state) + + def handleEvent(self, evt): + pass + + def getValue(self): + return self.back_elt.firstChild.firstChild.textContent + + def setValue(self, value): + self.back_elt.firstChild.firstChild.textContent = value + + def updateState(self, value): + self.setValue(value) + \ No newline at end of file diff -r 75ae46b66315 -r 71c441104cac plugins/python/modules/wxglade_hmi/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/wxglade_hmi/README Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,1 @@ +WxGlade HMI \ No newline at end of file diff -r 75ae46b66315 -r 71c441104cac plugins/python/modules/wxglade_hmi/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/wxglade_hmi/__init__.py Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,1 @@ +from wxglade_hmi import * diff -r 75ae46b66315 -r 71c441104cac plugins/python/modules/wxglade_hmi/wxglade_hmi.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/modules/wxglade_hmi/wxglade_hmi.py Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,113 @@ +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 + hmipyfile_path = "\"%s\""%hmipyfile_path + self.launch_wxglade(['-o', hmipyfile_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() + if not os.path.exists(wxg_filename): + hmi_name = self.BaseParams.getName() + open(wxg_filename,"w").write(""" + + + + frame_1 + + +""" % {"name": hmi_name, "class": "Class_%s" % hmi_name}) + if wx.Platform == '__WXMSW__': + wxg_filename = "\"%s\""%wxg_filename + self.launch_wxglade([wxg_filename]) diff -r 75ae46b66315 -r 71c441104cac plugins/python/plc_python.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/plc_python.c Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,214 @@ +/* + * 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(((data__->TRIG && !data__->TRIGM1) || + /* polling is equivalent to trig on value rather than on rising edge*/ + (poll && data__->TRIG )) && + /* trig only if not already trigged */ + data__->TRIGGED == 0){ + /* mark as trigged */ + data__->TRIGGED = 1; + /* make a safe copy of the code */ + data__->PREBUFFER = data__->CODE; + } + /* retain value for next rising edge detection */ + data__->TRIGM1 = data__->TRIG; + + /* python thread is not in ? */ + if( PythonState & PYTHON_LOCKED_BY_PLC){ + /* if some answer are waiting, publish*/ + if(data__->STATE == PYTHON_FB_ANSWERED){ + /* Copy buffer content into result*/ + data__->RESULT = data__->BUFFER; + /* signal result presece to PLC*/ + data__->ACK = 1; + /* Mark as free */ + data__->STATE = PYTHON_FB_FREE; + /* mark as not trigged */ + if(!poll) + 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 */ + data__->ACK = 0; + } + /* got the order to act ?*/ + if(data__->TRIGGED == 1 && + /* and not already being processed */ + 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*/ + data__->BUFFER = 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*/ + data__->ACK = 0; + }else{ + /* when in polling, acting reset trigger */ + data__->TRIGGED = 0; + } + /* Mark FB busy */ + 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); + /* 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 */ + data__->STATE == PYTHON_FB_PROCESSING){ /* some answer awaited*/ + /* If result not None */ + if(result){ + /* Get results len */ + data__->BUFFER.len = strlen(result); + /* prevent results overrun */ + if(data__->BUFFER.len > STR_MAX_LEN) + { + data__->BUFFER.len = STR_MAX_LEN; + /* TODO : signal error */ + } + /* Copy results to buffer */ + strncpy(data__->BUFFER.body, result, data__->BUFFER.len); + }else{ + data__->BUFFER.len = 0; + } + /* remove block from fifo*/ + EvalFBs[Current_Python_EvalFB] = NULL; + /* Mark block as answered */ + 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 */ + 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 */ + data__->STATE = PYTHON_FB_PROCESSING; + //printf("PythonIterator\n"); + /* make BUFFER a null terminated string */ + data__->BUFFER.body[data__->BUFFER.len] = 0; + /* next command is BUFFER */ + next_command = data__->BUFFER.body; + /* free python mutex */ + UnLockPython(); + /* return the next command to eval */ + return next_command; +} + diff -r 75ae46b66315 -r 71c441104cac plugins/python/pous.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/pous.xml Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,457 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + N + + + + + + + TRIG + + + + + + + CODE + + + + + + + + + + + ACK + + + + + + + + + + + RESULT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + COUNTER + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + USINT#1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + USINT#0 + + + + + + + + + + + COUNTER + + + + + + + + + + diff -r 75ae46b66315 -r 71c441104cac plugins/python/python.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/python.py Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,272 @@ +import wx +import os +import modules +from plugger import PlugTemplate, opjimg +from PythonEditor import PythonEditorFrame + +from xml.dom import minidom +from xmlclass import * +import cPickle + +PythonClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "python_xsd.xsd")) + +#------------------------------------------------------------------------------- +# Undo Buffer for PythonCode +#------------------------------------------------------------------------------- + +# Length of the buffer +UNDO_BUFFER_LENGTH = 20 + +""" +Class implementing a buffer of changes made on the current editing model +""" +class UndoBuffer: + + # Constructor initialising buffer + def __init__(self, currentstate, issaved = False): + self.Buffer = [] + self.CurrentIndex = -1 + self.MinIndex = -1 + self.MaxIndex = -1 + # if current state is defined + if currentstate: + self.CurrentIndex = 0 + self.MinIndex = 0 + self.MaxIndex = 0 + # Initialising buffer with currentstate at the first place + for i in xrange(UNDO_BUFFER_LENGTH): + if i == 0: + self.Buffer.append(currentstate) + else: + self.Buffer.append(None) + # Initialising index of state saved + if issaved: + self.LastSave = 0 + else: + self.LastSave = -1 + + # Add a new state in buffer + def Buffering(self, currentstate): + self.CurrentIndex = (self.CurrentIndex + 1) % UNDO_BUFFER_LENGTH + self.Buffer[self.CurrentIndex] = currentstate + # Actualising buffer limits + self.MaxIndex = self.CurrentIndex + if self.MinIndex == self.CurrentIndex: + # If the removed state was the state saved, there is no state saved in the buffer + if self.LastSave == self.MinIndex: + self.LastSave = -1 + self.MinIndex = (self.MinIndex + 1) % UNDO_BUFFER_LENGTH + self.MinIndex = max(self.MinIndex, 0) + + # Return current state of buffer + def Current(self): + return self.Buffer[self.CurrentIndex] + + # Change current state to previous in buffer and return new current state + def Previous(self): + if self.CurrentIndex != self.MinIndex: + self.CurrentIndex = (self.CurrentIndex - 1) % UNDO_BUFFER_LENGTH + return self.Buffer[self.CurrentIndex] + return None + + # Change current state to next in buffer and return new current state + def Next(self): + if self.CurrentIndex != self.MaxIndex: + self.CurrentIndex = (self.CurrentIndex + 1) % UNDO_BUFFER_LENGTH + return self.Buffer[self.CurrentIndex] + return None + + # Return True if current state is the first in buffer + def IsFirst(self): + return self.CurrentIndex == self.MinIndex + + # Return True if current state is the last in buffer + def IsLast(self): + return self.CurrentIndex == self.MaxIndex + + # Note that current state is saved + def CurrentSaved(self): + self.LastSave = self.CurrentIndex + + # Return True if current state is saved + def IsCurrentSaved(self): + return self.LastSave == self.CurrentIndex + +class PythonCodeTemplate: + + def __init__(self): + + self.PluginMethods.insert(0, + {"bitmap" : opjimg("editPYTHONcode"), + "name" : _("Edit Python File"), + "tooltip" : _("Edit Python File"), + "method" : "_OpenView"}, + ) + + filepath = self.PythonFileName() + + self.Buffering = False + self.PythonCode = PythonClasses["Python"]() + self.PythonBuffer = UndoBuffer(self.Copy(self.PythonCode), False) + 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.PythonBuffer = UndoBuffer(self.Copy(self.PythonCode), True) + else: + 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() + + _View = None + def _OpenView(self): + if not self._View: + def _onclose(): + self._View = None + def _onsave(): + self.GetPlugRoot().SaveProject() + self._View = PythonEditorFrame(self.GetPlugRoot().AppFrame, self) + self._View._onclose = _onclose + self._View._onsave = _onsave + self._View.Show() + + 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) + xmlfile.close() + + self.PythonBuffer.CurrentSaved() + return True + +#------------------------------------------------------------------------------- +# Current Buffering Management Functions +#------------------------------------------------------------------------------- + + """ + Return a copy of the project + """ + def Copy(self, model): + return cPickle.loads(cPickle.dumps(model)) + + def BufferPython(self): + self.PythonBuffer.Buffering(self.Copy(self.PythonCode)) + + def StartBuffering(self): + self.PythonBuffer.Buffering(self.PythonCode) + self.Buffering = True + + def EndBuffering(self): + if self.Buffering: + self.PythonCode = self.Copy(self.PythonCode) + self.Buffering = False + + def PythonCodeIsSaved(self): + if self.PythonBuffer: + return self.PythonBuffer.IsCurrentSaved() + else: + return True + + def LoadPrevious(self): + self.PythonCode = self.Copy(self.PythonBuffer.Previous()) + + def LoadNext(self): + self.PythonCode = self.Copy(self.PythonBuffer.Next()) + + def GetBufferState(self): + first = self.PythonBuffer.IsFirst() + 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() + + if wx.Platform == '__WXMSW__': + matiec_flags = " -I../../matiec/lib" + else: + matiec_flags = " -I../matiec/lib" + + return [(Gen_Pythonfile_path, matiec_flags)], "", True, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb")) diff -r 75ae46b66315 -r 71c441104cac plugins/python/python_xsd.xsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/python/python_xsd.xsd Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,18 @@ + + + + + + + Formatted text according to parts of XHTML 1.1 + + + + + + + diff -r 75ae46b66315 -r 71c441104cac plugins/svgui/.cvsignore --- a/plugins/svgui/.cvsignore Wed Aug 12 16:23:59 2009 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -*.pyc diff -r 75ae46b66315 -r 71c441104cac plugins/svgui/README --- a/plugins/svgui/README Wed Aug 12 16:23:59 2009 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -SVGUI HMI \ No newline at end of file diff -r 75ae46b66315 -r 71c441104cac plugins/svgui/__init__.py --- a/plugins/svgui/__init__.py Wed Aug 12 16:23:59 2009 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -from svgui import * -controller = None -view = None \ No newline at end of file diff -r 75ae46b66315 -r 71c441104cac plugins/svgui/svgui.py --- a/plugins/svgui/svgui.py Wed Aug 12 16:23:59 2009 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,798 +0,0 @@ -import os, shutil, sys -base_folder = os.path.split(sys.path[0])[0] -sys.path.append(os.path.join(base_folder, "wxsvg", "SVGUIEditor")) -sys.path.append(os.path.join(base_folder, "plcopeneditor", "graphics")) - -import wx, subprocess - -from SVGUIGenerator import * -from SVGUIControler import * -from SVGUIEditor import * -from FBD_Objects import * -from PLCGenerator import PLCGenException - -from wxPopen import ProcessLogger -from wx.wxsvg import SVGDocument -from docutils import * - -[ID_SVGUIEDITORFBDPANEL, -] = [wx.NewId() for _init_ctrls in range(1)] - -SVGUIFB_Types = {ITEM_CONTAINER : "Container", - ITEM_BUTTON : "Button", - ITEM_TEXT : "TextCtrl", - ITEM_SCROLLBAR : "ScrollBar", - ITEM_ROTATING : "RotatingCtrl", - ITEM_NOTEBOOK : "NoteBook", - ITEM_TRANSFORM : "Transform"} - -class _SVGUIEditor(SVGUIEditor): - """ - This Class add IEC specific features to the SVGUIEditor : - - FDB preview - - FBD begin drag - """ - - def _init_coll_EditorGridSizer_Items(self, parent): - SVGUIEditor._init_coll_EditorGridSizer_Items(self, parent) - parent.AddWindow(self.FBDPanel, 0, border=0, flag=wx.GROW) - - def _init_ctrls(self, prnt): - SVGUIEditor._init_ctrls(self, prnt, False) - - self.FBDPanel = wx.Panel(id=ID_SVGUIEDITORFBDPANEL, - name='FBDPanel', parent=self.EditorPanel, pos=wx.Point(0, 0), - size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) - self.FBDPanel.SetBackgroundColour(wx.WHITE) - self.FBDPanel.Bind(wx.EVT_LEFT_DOWN, self.OnFBDPanelClick) - self.FBDPanel.Bind(wx.EVT_PAINT, self.OnPaintFBDPanel) - - setattr(self.FBDPanel, "GetScaling", lambda: None) - setattr(self.FBDPanel, "IsOfType", self.IsOfType) - setattr(self.FBDPanel, "GetBlockType", self.GetBlockType) - - self._init_sizers() - - def __init__(self, parent, controler = None, fileOpen = None): - SVGUIEditor.__init__(self, parent, controler, fileOpen) - - self.FBDBlock = None - - def IsOfType(self, type, reference): - return self.Controler.GetPlugRoot().IsOfType(type, reference) - - def GetBlockType(self, type, inputs = None): - return self.Controler.GetPlugRoot().GetBlockType(type, inputs) - - def RefreshView(self, select_id = None): - SVGUIEditor.RefreshView(self, select_id) - self.FBDPanel.Refresh() - - def OnPaintFBDPanel(self,event): - dc = wx.ClientDC(self.FBDPanel) - dc.Clear() - selected = self.GetSelected() - if selected is not None: - selected_type = self.Controler.GetElementType(selected) - if selected_type is not None: - self.FBDBlock = FBD_Block(parent=self.FBDPanel,type=SVGUIFB_Types[selected_type],name=self.Controler.GetElementName(selected)) - width, height = self.FBDBlock.GetMinSize() - self.FBDBlock.SetSize(width,height) - clientsize = self.FBDPanel.GetClientSize() - x = (clientsize.width - width) / 2 - y = (clientsize.height - height) / 2 - self.FBDBlock.SetPosition(x, y) - self.FBDBlock.Draw(dc) - else: - self.FBDBlock = None - event.Skip() - - def OnFBDPanelClick(self, event): - if self.FBDBlock: - data = wx.TextDataObject(str((self.FBDBlock.GetType(), "functionBlock", self.FBDBlock.GetName()))) - DropSrc = wx.DropSource(self.FBDPanel) - DropSrc.SetData(data) - DropSrc.DoDragDrop() - event.Skip() - - def OnInterfaceTreeItemSelected(self, event): - self.FBDPanel.Refresh() - SVGUIEditor.OnInterfaceTreeItemSelected(self, event) - - def OnGenerate(self,event): - self.SaveProject() - self.Controler.PlugGenerate_C(sys.path[0],(0,0,4,5),None) - event.Skip() - -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"} - -CTYPECONVERSION = {"BOOL" : "IEC_BOOL", "UINT" : "IEC_UINT", "STRING" : "IEC_STRING", "REAL" : "IEC_REAL"} -CPRINTTYPECONVERSION = {"BOOL" : "d", "UINT" : "d", "STRING" : "s", "REAL" : "f"} - -class RootClass(SVGUIControler): - - def __init__(self): - SVGUIControler.__init__(self) - filepath = os.path.join(self.PlugPath(), "gui.xml") - - if os.path.isfile(filepath): - svgfile = os.path.join(self.PlugPath(), "gui.svg") - if os.path.isfile(svgfile): - self.SvgFilepath = svgfile - self.OpenXMLFile(filepath) - else: - self.CreateNewInterface() - self.SetFilePath(filepath) - - def GetElementIdFromName(self, name): - element = self.GetElementByName(name) - if element is not None: - return element.getid() - return None - - _View = None - def _OpenView(self): - if not self._View: - def _onclose(): - self._View = None - def _onsave(): - self.GetPlugRoot().SaveProject() - self._View = _SVGUIEditor(self.GetPlugRoot().AppFrame, self) - self._View._onclose = _onclose - self._View._onsave = _onsave - self._View.Show() - - def _ImportSVG(self): - if not self._View: - 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, os.path.join(self.PlugPath(), "gui.svg")) - else: - self.logger.write_error("No such SVG file: %s\n"%svgpath) - dialog.Destroy() - - def _ImportXML(self): - if not self._View: - dialog = wx.FileDialog(self.GetPlugRoot().AppFrame, "Choose a XML file", os.getcwd(), "", "XML files (*.xml)|*.xml|All files|*.*", wx.OPEN) - if dialog.ShowModal() == wx.ID_OK: - xmlpath = dialog.GetPath() - if os.path.isfile(xmlpath): - shutil.copy(xmlpath, os.path.join(self.PlugPath(), "gui.xml")) - else: - self.logger.write_error("No such XML file: %s\n"%xmlpath) - dialog.Destroy() - - def _StartInkscape(self): - svgfile = os.path.join(self.PlugPath(), "gui.svg") - if not os.path.isfile(svgfile): - svgfile = None - open_svg(svgfile) - - PluginMethods = [ - {"bitmap" : os.path.join("images","HMIEditor"), - "name" : "HMI Editor", - "tooltip" : "HMI Editor", - "method" : "_OpenView"}, - {"bitmap" : os.path.join("images","ImportSVG"), - "name" : "Import SVG", - "tooltip" : "Import SVG", - "method" : "_ImportSVG"}, - {"bitmap" : os.path.join("images","ImportDEF"), - "name" : "Import XML", - "tooltip" : "Import XML", - "method" : "_ImportXML"}, - {"bitmap" : os.path.join("images","ImportSVG"), - "name" : "Inkscape", - "tooltip" : "Create HMI", - "method" : "_StartInkscape"}, - ] - - def OnPlugSave(self): - self.SaveXMLFile(os.path.join(self.PlugPath(), "gui.xml")) - return True - - def PlugGenerate_C(self, buildpath, locations): - progname = "SVGUI_%s"%"_".join(map(str, self.GetCurrentLocation())) - - doc = SVGDocument(self.GetSVGFilePath()) - root_element = doc.GetRootElement() - window_size = (int(float(root_element.GetAttribute("width"))), - int(float(root_element.GetAttribute("height")))) - -# svgfilepath = self.GetSVGFilePath() -# xmlfilepath = self.GetFilePath() -# shutil.copy(svgfilepath, buildpath) -# shutil.copy(xmlfilepath, buildpath) - - SVGFilePath = self.GetSVGFilePath() - SVGFileBaseName = os.path.split(SVGFilePath)[1] - FilePath = self.GetFilePath() - FileBaseName = os.path.split(FilePath)[1] - - generator = _SVGUICGenerator(self, self.GetElementsByType(), - os.path.split(self.GetSVGFilePath())[1], - os.path.split(self.GetFilePath())[1], - self.GetCurrentLocation()) - generator.GenerateProgram(window_size, buildpath, progname) - Gen_C_file = os.path.join(buildpath, progname+".cpp" ) - - if wx.Platform == '__WXMSW__': - cxx_flags = "-I..\\lib\\wx\\include\\msw-unicode-release-2.8 -I..\\include\\wx-2.8 -I..\\..\\matiec\\lib -DWXUSINGDLL -D__WXMSW__ -mthreads" - libs = "\"..\\lib\\libwxsvg.a\" \"..\\lib\\libwxsvg_agg.a\" \"..\\lib\\libagg.a\" \"..\\lib\\libaggplatformwin32.a\" \"..\\lib\\libaggfontwin32tt.a\" -L..\\lib -mwindows -mthreads -Wl,--subsystem,windows -mwindows -lwx_mswu_richtext-2.8 -lwx_mswu_aui-2.8 -lwx_mswu_xrc-2.8 -lwx_mswu_qa-2.8 -lwx_mswu_html-2.8 -lwx_mswu_adv-2.8 -lwx_mswu_core-2.8 -lwx_baseu_xml-2.8 -lwx_baseu_net-2.8 -lwx_baseu-2.8" - else: - status, result, err_result = ProcessLogger(self.logger, "wx-config --cxxflags", no_stdout=True).spin() - if status: - self.logger.write_error("Unable to get wx cxxflags\n") - cxx_flags = result.strip() + " -I../matiec/lib" - - status, result, err_result = ProcessLogger(self.logger, "wx-config --libs", no_stdout=True).spin() - if status: - self.logger.write_error("Unable to get wx libs\n") - libs = result.strip() + " -lwxsvg" - - return [(Gen_C_file, cxx_flags)],libs,True,(SVGFileBaseName, file(SVGFilePath, "rb")), (FileBaseName, file(FilePath, "rb")) - - def BlockTypesFactory(self): - - SVGUIBlock_Types = [] - - def GetSVGUIBlockType(type): - for category in SVGUIBlock_Types: - for blocktype in category["list"]: - if blocktype["name"] == type: - return blocktype - setattr(self, "GetSVGUIBlockType", GetSVGUIBlockType) - - def generate_svgui_block(generator, block, body, link, order=False): - name = block.getinstanceName() - block_id = self.GetElementIdFromName(name) - if block_id == None: - raise PLCGenException, "Undefined SVGUI Block \"%s\""%name - type = block.gettypeName() - block_infos = GetSVGUIBlockType(type) - current_location = ".".join(map(str, self.GetCurrentLocation())) - if not generator.ComputedBlocks.get(block, False) and not order: - generator.ComputedBlocks[block] = True - for num, variable in enumerate(block.inputVariables.getvariable()): - connections = variable.connectionPointIn.getconnections() - if connections is not None: - input_info = (generator.TagName, "block", block.getlocalId(), "input", num) - parameter = "%sQ%s%s.%d.%d"%("%", TYPECONVERSION[block_infos["inputs"][num][1]], current_location, block_id, num+1) - value = generator.ComputeExpression(body, connections) - generator.Program += [(generator.CurrentIndent, ()), - (parameter, input_info), - (" := ", ())] - generator.Program += generator.ExtractModifier(variable, value, input_info) - generator.Program += [(";\n", ())] - if link: - connectionPoint = link.getposition()[-1] - for num, variable in enumerate(block.outputVariables.getvariable()): - blockPointx, blockPointy = variable.connectionPointOut.getrelPositionXY() - output_info = (generator.TagName, "block", block.getlocalId(), "output", num) - parameter = "%sI%s%s.%d.%d"%("%", TYPECONVERSION[block_infos["outputs"][num][1]], current_location, block_id, num+1) - if block.getx() + blockPointx == connectionPoint.getx() and block.gety() + blockPointy == connectionPoint.gety(): - return generator.ExtractModifier(variable, [(parameter, output_info)], output_info) - raise PLCGenException, "No corresponding output variable found on SVGUI Block \"%s\""%name - else: - return None - - def initialise_block(type, name, block = None): - block_id = self.GetElementIdFromName(name) - if block_id == None: - raise PLCGenException, "Undefined SVGUI Block \"%s\""%name - block_infos = GetSVGUIBlockType(type) - current_location = ".".join(map(str, self.GetCurrentLocation())) - variables = [] - if block is not None: - input_variables = block.inputVariables.getvariable() - output_variables = block.outputVariables.getvariable() - else: - input_variables = None - output_variables = None - for num, (input_name, input_type, input_modifier) in enumerate(block_infos["inputs"]): - if input_variables is not None and num < len(input_variables): - connections = input_variables[num].connectionPointIn.getconnections() - if input_variables is None or connections and len(connections) == 1: - variables.append((input_type, None, "%sQ%s%s.%d.%d"%("%", TYPECONVERSION[input_type], current_location, block_id, num+1), None)) - for num, (output_name, output_type, output_modifier) in enumerate(block_infos["outputs"]): - variables.append((output_type, None, "%sI%s%s.%d.%d"%("%", TYPECONVERSION[input_type], current_location, block_id, num+1), None)) - return variables - - SVGUIBlock_Types.extend([{"name" : "SVGUI function blocks", "list" : - [{"name" : "Container", "type" : "functionBlock", "extensible" : False, - "inputs" : [("Show","BOOL","none"),("Enable","BOOL","none")], - "outputs" : [], - "comment" : "SVGUI Container", - "generate" : generate_svgui_block, "initialise" : initialise_block}, - {"name" : "Button", "type" : "functionBlock", "extensible" : False, - "inputs" : [("Show","BOOL","none"),("Enable","BOOL","none"),("Value","BOOL","none")], - "outputs" : [("State","BOOL","none")], - "comment" : "SVGUI Button", - "generate" : generate_svgui_block, "initialise" : initialise_block}, - {"name" : "TextCtrl", "type" : "functionBlock", "extensible" : False, - "inputs" : [("Show","BOOL","none"),("Enable","BOOL","none"),("SetText","STRING","none")], - "outputs" : [("Text","STRING","none")], - "comment" : "SVGUI Text Control", - "generate" : generate_svgui_block, "initialise" : initialise_block}, - {"name" : "ScrollBar", "type" : "functionBlock", "extensible" : False, - "inputs" : [("Show","BOOL","none"),("Enable","BOOL","none"),("SetThumb","UINT","none"),("SetRange","UINT","none"),("SetPosition","UINT","none")], - "outputs" : [("Position","UINT","none")], - "comment" : "SVGUI ScrollBar", - "generate" : generate_svgui_block, "initialise" : initialise_block}, - {"name" : "NoteBook", "type" : "functionBlock", "extensible" : False, - "inputs" : [("Show","BOOL","none"),("Enable","BOOL","none"),("SetSelected","BOOL","none")], - "outputs" : [("Selected","UINT","none")], - "comment" : "SVGUI Notebook", - "generate" : generate_svgui_block, "initialise" : initialise_block}, - {"name" : "RotatingCtrl", "type" : "functionBlock", "extensible" : False, - "inputs" : [("Show","BOOL","none"),("Enable","BOOL","none"),("SetAngle","REAL","none")], - "outputs" : [("Angle","REAL","none")], - "comment" : "SVGUI Rotating Control", - "generate" : generate_svgui_block, "initialise" : initialise_block}, - {"name" : "Transform", "type" : "functionBlock", "extensible" : False, - "inputs" : [("Show","BOOL","none"),("Enable","BOOL","none"),("SetX","REAL","none"),("SetY","REAL","none"),("SetXScale","REAL","none"),("SetYScale","REAL","none"),("SetAngle","REAL","none")], - "outputs" : [("X","REAL","none"),("Y","REAL","none")], - "comment" : "SVGUI Transform", - "generate" : generate_svgui_block, "initialise" : initialise_block}, - ]} - ]) - - return SVGUIBlock_Types - - -class _SVGUICGenerator(SVGUICGenerator): - - def __init__(self, controler, elements, svgfile, xmlfile, current_location): - SVGUICGenerator.__init__(self, elements, svgfile, xmlfile) - - self.CurrentLocation = current_location - self.Controler = controler - - def GenerateProgramHeadersPublicVars(self): - text = """ - void OnPlcOutEvent(wxEvent& event); - - void Retrieve(); - void Publish(); - void Initialize(); -""" -# text += " void Print();\n" - return text - - def GenerateIECVars(self): - text = "" - for element in self.Elements: - text += "STATE_TYPE out_state_%d;\n"%element.getid() - text += "STATE_TYPE in_state_%d;\n"%element.getid() - text +="\n" - current_location = "_".join(map(str, self.CurrentLocation)) - #Declaration des variables - for element in self.Elements: - block_infos = self.Controler.GetSVGUIBlockType(SVGUIFB_Types[GetElementType(element)]) - block_id = element.getid() - for i, input in enumerate(block_infos["inputs"]): - element_c_type = CTYPECONVERSION[input[1]] - variable = "__Q%s%s_%d_%d"%(TYPECONVERSION[input[1]], current_location, block_id, i + 1) - text += "%s beremiz%s;\n"%(element_c_type, variable) - text += "%s* %s = &beremiz%s;\n"%(element_c_type, variable, variable) - text += "%s _copy%s;\n"%(element_c_type, variable) - for i, output in enumerate(block_infos["outputs"]): - element_c_type = CTYPECONVERSION[output[1]] - variable = "__I%s%s_%d_%d"%(TYPECONVERSION[output[1]], current_location, block_id, i + 1) - text += "%s beremiz%s;\n"%(element_c_type, variable) - text += "%s* %s = &beremiz%s;\n"%(element_c_type, variable, variable) - text += "%s _copy%s;\n"%(element_c_type, variable) - text +="\n" - return text - - def GenerateGlobalVarsAndFuncs(self, size): - text = """#include "iec_types.h" -#ifdef __WXMSW__ -#define COMPARE_AND_SWAP_VAL(Destination, comparand, exchange) InterlockedCompareExchange(Destination, exchange, comparand) -#define THREAD_RETURN_TYPE DWORD WINAPI -#define STATE_TYPE long int -#else -#define COMPARE_AND_SWAP_VAL(Destination, comparand, exchange) __sync_val_compare_and_swap(Destination, comparand, exchange) -#define THREAD_RETURN_TYPE void* -#define STATE_TYPE volatile int -#endif - -""" - - text += self.GenerateIECVars() - - text += """IMPLEMENT_APP_NO_MAIN(SVGViewApp); -SVGViewApp *myapp = NULL; -wxSemaphore MyInitSem; - -#ifdef __WXMSW__ -HANDLE wxMainLoop; -DWORD wxMainLoopId; -#else -pthread_t wxMainLoop; -#endif - -""" - - text += """int myargc = 0; -char** myargv = NULL; - -#define UNCHANGED 1 -#define PLC_BUSY 2 -#define CHANGED 3 -#define GUI_BUSY 4 -#ifdef __WXMSW__ -#else -#endif - -bool refresh = false; -bool refreshing = false; - -THREAD_RETURN_TYPE InitWxEntry(void* args) -{ - wxEntry(myargc,myargv); - myapp = NULL; - MyInitSem.Post(); - return 0; -} - -""" - - text += """ -bool SVGViewApp::OnInit() -{ - #ifndef __WXMSW__ - setlocale(LC_NUMERIC, "C"); - #endif -""" - - text += """ frame = new MainFrame(NULL, wxT("Program"),wxDefaultPosition, wxSize(%d, %d)); - frame->Show(); - myapp = this; -"""%size - text += """ return true; -} - -extern "C" { - -int __init_%(location)s(int argc, char** argv) -{ - myargc = argc; - myargv = argv; -#ifdef __WXMSW__ - wxMainLoop = CreateThread(NULL, 0, InitWxEntry, 0, 0, &wxMainLoopId); -#else - pthread_create(&wxMainLoop, NULL, InitWxEntry, NULL); -#endif - MyInitSem.Wait(); - return 0; -} - -void __cleanup_%(location)s() -{ - if(myapp){ - wxCloseEvent event(wxEVT_CLOSE_WINDOW); - myapp->frame->AddPendingEvent(event); - myapp = NULL; - } - MyInitSem.Wait(); -} - -void __retrieve_%(location)s() -{ - if(myapp){ - myapp->frame->m_svgCtrl->Retrieve(); - } -} - -void __publish_%(location)s() -{ - if(myapp){ - myapp->frame->m_svgCtrl->Publish(); - } -} - -} - -IEC_STRING wxStringToIEC_STRING(wxString s) -{ - IEC_STRING res = {0,""}; - int i; - for(i = 0; iargv[1], wxT("%s")); - wxFileName xmlfilepath(wxTheApp->argv[1], wxT("%s")); - - m_svgCtrl = new Program(this); - if (m_svgCtrl->LoadFiles(svgfilepath.GetFullPath(), xmlfilepath.GetFullPath())) - { - Show(true); - m_svgCtrl->SetFocus(); - m_svgCtrl->SetFitToFrame(true); - m_svgCtrl->InitScrollBars(); - m_svgCtrl->Initialize(); - m_svgCtrl->Update(); - } - else - { - printf("Error while opening SVGUI files\\n"); - } -} - - -"""%(self.SVGFilePath, self.XMLFilePath) - - return text - - def GenerateProgramInitProgram(self): - text = "Program::Program(wxWindow* parent):SVGUIWindow(parent)\n{\n" - for element in self.Elements: - text += " out_state_%d = UNCHANGED;\n"%element.getid() - text += " in_state_%d = UNCHANGED;\n"%element.getid() - text += "}\n\n" - return text - - def GenerateProgramEventFunctions(self): - text = "" - current_location = "_".join(map(str, self.CurrentLocation)) - for element in self.Elements: - element_type = GetElementType(element) - element_lock = """ - if (COMPARE_AND_SWAP_VAL(&in_state_%d, CHANGED, GUI_BUSY) == CHANGED || - COMPARE_AND_SWAP_VAL(&in_state_%d, UNCHANGED, GUI_BUSY) == UNCHANGED) { -"""%(element.getid(), element.getid()) - element_unlock = """ - COMPARE_AND_SWAP_VAL(&in_state_%d, GUI_BUSY, CHANGED); - event.Skip(); - }else{ - /* re post event for idle */ - AddPendingEvent(event); - } -} - -"""%element.getid() - element_name = element.getname() - - if element_type == ITEM_BUTTON: - text += """void Program::On%sClick(wxCommandEvent& event) -{ - SVGUIButton* button = (SVGUIButton*)GetElementByName(wxT("%s"));\n"""%(element_name, element_name) - text += element_lock - text += " _copy__IX%s_%d_1 = button->GetToggle();\n"%(current_location, element.getid()) - text += element_unlock - elif element_type == ITEM_ROTATING: - text += """void Program::On%sChanging(wxScrollEvent& event) -{ - SVGUIRotatingCtrl* rotating = (SVGUIRotatingCtrl*)GetElementByName(wxT("%s")); -"""%(element_name, element_name) - text += element_lock - text += " _copy__ID%s_%d_1 = rotating->GetAngle();\n"%(current_location, element.getid()) - text += element_unlock - elif element_type == ITEM_NOTEBOOK: - text += """void Program::On%sTabChanged(wxNotebookEvent& event) -{ - SVGUINoteBook* notebook = (SVGUINoteBook*)GetElementByName(wxT("%s")); -"""%(element_name, element_name) - text += element_lock - text += " _copy__IB%s_%d_1 = notebook->GetCurrentPage();\n"%(current_location, element.getid()) - text += element_unlock - elif element_type == ITEM_TRANSFORM: - text += """void Program::On%sChanging(wxScrollEvent& event) -{ - SVGUITransform* transform = (SVGUITransform*)GetElementByName(wxT("%s")); -"""%(element_name, element_name) - text += element_lock - text += " _copy__ID%s_%d_1 = transform->GetX();\n"%(current_location, element.getid()) - text += " _copy__ID%s_%d_2 = transform->GetY();\n"%(current_location, element.getid()) - text += element_unlock - - text += "/* OnPlcOutEvent update GUI with provided IEC __Q* PLC output variables */\n" - text += """void Program::OnPlcOutEvent(wxEvent& event) -{ - SVGUIElement* element; - - refreshing = true; - - -""" - for element in self.Elements: - element_type = GetElementType(element) - texts = {"location" : current_location, "id" : element.getid()} - - text += """ if (COMPARE_AND_SWAP_VAL(&out_state_%(id)d, CHANGED, GUI_BUSY) == CHANGED) - { - element = (SVGUIElement*)GetElementById(wxT("%(id)d")); - - if (_copy__QX%(location)s_%(id)d_1 != element->IsVisible()) { - if (_copy__QX%(location)s_%(id)d_1) - element->Show(); - else - element->Hide(); - } - if (_copy__QX%(location)s_%(id)d_2 != element->IsEnabled()) { - if (_copy__QX%(location)s_%(id)d_2) - element->Enable(); - else - element->Disable(); - } -"""%texts - if element_type == ITEM_BUTTON: - text += """ if (_copy__QX%(location)s_%(id)d_3 != ((SVGUIButton*)element)->GetToggle()) - ((SVGUIButton*)element)->SetToggle(_copy__QX%(location)s_%(id)d_3); -"""%texts - elif element_type == ITEM_TEXT: - text += """ if (((SVGUITextCtrl*)element)->GetValue().compare(_copy__QX%(location)s_%(id)d_3)) - { - wxString str = wxString::FromAscii(_copy__QB%(location)s_%(id)d_3); - ((SVGUITextCtrl*)element)->SetText(str); - } -"""%texts - elif element_type == ITEM_SCROLLBAR: - text += """ if (_copy__QW%(location)s_%(id)d_3 != ((SVGUIScrollBar*)element)->GetThumbPosition() || - _copy__QW%(location)s_%(id)d_4 != ((SVGUIScrollBar*)element)->GetThumbSize() || - _copy__QW%(location)s_%(id)d_5 != ((SVGUIScrollBar*)element)->GetRange()) - ((SVGUIScrollBar*)element)->Init_ScrollBar(_copy__QW%(location)s_%(id)d_3, _copy__QW%(location)s_%(id)d_4, _copy__QW%(location)s_%(id)d_5); -"""%texts - elif element_type == ITEM_ROTATING: - text += """ if (_copy__QD%(location)s_%(id)d_3 != ((SVGUIRotatingCtrl*)element)->GetAngle()) - ((SVGUIRotatingCtrl*)element)->SetAngle(_copy__QD%(location)s_%(id)d_3); -"""%texts - elif element_type == ITEM_NOTEBOOK: - text += """ if (_copy__QB%(location)s_%(id)d_3 != ((SVGUINoteBook*)element)->GetCurrentPage()) - ((SVGUINoteBook*)element)->SetCurrentPage(_copy__QB%(location)s_%(id)d_3); -"""%texts - elif element_type == ITEM_TRANSFORM: - text += """ if (_copy__QD%(location)s_%(id)d_3 != ((SVGUITransform*)element)->GetX() || - _copy__QD%(location)s_%(id)d_4 != ((SVGUITransform*)element)->GetY()) - ((SVGUITransform*)element)->Move(_copy__QD%(location)s_%(id)d_3, _copy__QD%(location)s_%(id)d_4); - if (_copy__QD%(location)s_%(id)d_5 != ((SVGUITransform*)element)->GetXScale() || - _copy__QD%(location)s_%(id)d_6 != ((SVGUITransform*)element)->GetYScale()) - ((SVGUITransform*)element)->Scale(_copy__QD%(location)s_%(id)d_5, _copy__QD%(location)s_%(id)d_6); - if (_copy__QD%(location)s_%(id)d_7 != ((SVGUITransform*)element)->GetAngle()) - ((SVGUITransform*)element)->Rotate(_copy__QD%(location)s_%(id)d_7); -"""%texts - text += " COMPARE_AND_SWAP_VAL(&out_state_%(id)d, GUI_BUSY, UNCHANGED);\n }\n"%texts - - text += """ - - refreshing = false; - - event.Skip(); -} - -""" - return text - - def GenerateProgramPrivateFunctions(self): - current_location = "_".join(map(str, self.CurrentLocation)) - - text = "void Program::Retrieve()\n{\n" - for element in self.Elements: - element_type = GetElementType(element) - texts = {"location" : current_location, "id" : element.getid()} - block_infos = self.Controler.GetSVGUIBlockType(SVGUIFB_Types[GetElementType(element)]) - if len(block_infos["outputs"]) > 0: - text += """ if (COMPARE_AND_SWAP_VAL(&in_state_%(id)d, CHANGED, PLC_BUSY) == CHANGED) { -"""%texts - for i, output in enumerate(block_infos["outputs"]): - texts["type"] = TYPECONVERSION[output[1]] - texts["pin"] = i + 1 - - variable = "__I%(type)s%(location)s_%(id)d_%(pin)d"%texts - text +=" beremiz%s = _copy%s;\n"%(variable, variable) - - text += """ COMPARE_AND_SWAP_VAL(&in_state_%(id)d, PLC_BUSY, UNCHANGED); - } -"""%texts - text += "}\n\n" - - text += "void Program::Publish()\n{\n STATE_TYPE new_state;\n\n" - for element in self.Elements: - element_type = GetElementType(element) - texts = {"location" : current_location, "id" : element.getid()} - block_infos = self.Controler.GetSVGUIBlockType(SVGUIFB_Types[GetElementType(element)]) - - text += """ if ((new_state = COMPARE_AND_SWAP_VAL(&out_state_%(id)d, UNCHANGED, PLC_BUSY)) == UNCHANGED || - (new_state = COMPARE_AND_SWAP_VAL(&out_state_%(id)d, CHANGED, PLC_BUSY)) == CHANGED) { -"""%texts - for i, input in enumerate(block_infos["inputs"]): - texts["type"] = TYPECONVERSION[input[1]] - texts["pin"] = i + 1 - variable = "__Q%(type)s%(location)s_%(id)d_%(pin)d"%texts - text += " if (_copy%s != beremiz%s) {\n"%(variable, variable) - text += " _copy%s = beremiz%s;\n"%(variable, variable) - text += " new_state = CHANGED;\n }\n"%texts - text += """ COMPARE_AND_SWAP_VAL(&out_state_%(id)d, PLC_BUSY, new_state); - refresh |= new_state == CHANGED; - } -"""%texts - - text += """ /* Replace this with determinist signal if called from RT */ - if (refresh && !refreshing) { - wxCommandEvent event( EVT_PLC ); - AddPendingEvent(event); - refresh = false; - } -}; - -""" - - text += """void Program::Initialize() -{ - SVGUIElement* element; -""" - for element in self.Elements: - element_type = GetElementType(element) - texts = {"location" : current_location, "id" : element.getid()} - - text += """ - element = (SVGUIElement*)GetElementById(wxT("%(id)d")); - beremiz__QX%(location)s_%(id)d_1 = _copy__QX%(location)s_%(id)d_1 = element->IsVisible(); - beremiz__QX%(location)s_%(id)d_2 = _copy__QX%(location)s_%(id)d_2 = element->IsEnabled(); -"""%texts - if element_type == ITEM_BUTTON: - text += " beremiz__QX%(location)s_%(id)d_3 = _copy__QX%(location)s_%(id)d_3 = ((SVGUIButton*)element)->GetToggle();\n"%texts - text += " beremiz__IX%(location)s_%(id)d_1 = _copy__IX%(location)s_%(id)d_1 = ((SVGUIButton*)element)->GetToggle();\n"%texts - elif element_type == ITEM_TEXT: - text += " beremiz__QB%(location)s_%(id)d_3 = _copy__QB%(location)s_%(id)d_3 = ((SVGUITextCtrl*)element)->GetValue();\n"%texts - text += " beremiz__IB%(location)s_%(id)d_1 = _copy__IB%(location)s_%(id)d_1 = ((SVGUITextCtrl*)element)->GetValue();\n"%texts - elif element_type == ITEM_SCROLLBAR: - text += " beremiz__QW%(location)s_%(id)d_3 = _copy__QW%(location)s_%(id)d_3 = ((SVGUIScrollBar*)element)->GetThumbSize();\n"%texts - text += " beremiz__QW%(location)s_%(id)d_4 = _copy__QW%(location)s_%(id)d_4 = ((SVGUIScrollBar*)element)->GetRange();\n"%texts - text += " beremiz__QW%(location)s_%(id)d_5 = _copy__QW%(location)s_%(id)d_5 = ((SVGUIScrollBar*)element)->GetThumbPosition();\n"%texts - text += " beremiz__IW%(location)s_%(id)d_1 = _copy__IW%(location)s_%(id)d_1 = ((SVGUIScrollBar*)element)->GetThumbPosition();\n"%texts - elif element_type == ITEM_ROTATING: - text += " beremiz__QD%(location)s_%(id)d_3 = _copy__QD%(location)s_%(id)d_3 = ((SVGUIRotatingCtrl*)element)->GetAngle();\n"%texts - text += " beremiz__ID%(location)s_%(id)d_1 = _copy__ID%(location)s_%(id)d_1 = ((SVGUIRotatingCtrl*)element)->GetAngle();\n"%texts - elif element_type == ITEM_NOTEBOOK: - text += " beremiz__QB%(location)s_%(id)d_3 = _copy__QB%(location)s_%(id)d_3 = ((SVGUINoteBook*)element)->GetCurrentPage();\n"%texts - text += " beremiz__IB%(location)s_%(id)d_1 = _copy__IB%(location)s_%(id)d_1 = ((SVGUINoteBook*)element)->GetCurrentPage();\n"%texts - elif element_type == ITEM_TRANSFORM: - text += " beremiz__QD%(location)s_%(id)d_3 = _copy__QD%(location)s_%(id)d_3 = ((SVGUITransform*)element)->GetX();\n"%texts - text += " beremiz__QD%(location)s_%(id)d_4 = _copy__QD%(location)s_%(id)d_4 = ((SVGUITransform*)element)->GetY();\n"%texts - text += " beremiz__QD%(location)s_%(id)d_5 = _copy__QD%(location)s_%(id)d_5 = ((SVGUITransform*)element)->GetXScale();\n"%texts - text += " beremiz__QD%(location)s_%(id)d_6 = _copy__QD%(location)s_%(id)d_6 = ((SVGUITransform*)element)->GetYScale();\n"%texts - text += " beremiz__QD%(location)s_%(id)d_7 = _copy__QD%(location)s_%(id)d_7 = ((SVGUITransform*)element)->GetAngle();\n"%texts - text += " beremiz__ID%(location)s_%(id)d_1 = _copy__ID%(location)s_%(id)d_1 = ((SVGUITransform*)element)->GetX();\n"%texts - text += " beremiz__ID%(location)s_%(id)d_2 = _copy__ID%(location)s_%(id)d_2 = ((SVGUITransform*)element)->GetY();\n"%texts - - text += "\n MyInitSem.Post();\n}\n\n" - return text diff -r 75ae46b66315 -r 71c441104cac pous.xml --- a/pous.xml Wed Aug 12 16:23:59 2009 -0600 +++ /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 75ae46b66315 -r 71c441104cac runtime/PLCObject.py --- a/runtime/PLCObject.py Wed Aug 12 16:23:59 2009 -0600 +++ b/runtime/PLCObject.py Thu Aug 13 11:37:38 2009 +0200 @@ -45,7 +45,7 @@ class PLCObject(pyro.ObjBase): _Idxs = [] - def __init__(self, workingdir, daemon, argv, statuschange, evaluator): + def __init__(self, workingdir, daemon, argv, statuschange, evaluator, website): pyro.ObjBase.__init__(self) self.evaluator = evaluator self.argv = [workingdir] + argv # force argv[0] to be "path" to exec... @@ -53,11 +53,13 @@ self.PLCStatus = "Stopped" self.PLClibraryHandle = None self.PLClibraryLock = Lock() + self.DummyIteratorLock = None # Creates fake C funcs proxies self._FreePLC() self.daemon = daemon self.statuschange = statuschange self.hmi_frame = None + self.website = website # Get the last transfered PLC if connector must be restart try: @@ -93,10 +95,30 @@ self._startPLC.restype = ctypes.c_int self._startPLC.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_char_p)] - def StopPLCLock(): - self.PLClibraryLock.acquire() - self.PLClibraryHandle.stopPLC() - self.PLClibraryLock.release() + self.DummyIteratorLock = Lock() + self.DummyIteratorLock.acquire() + + self._PythonIterator = getattr(self.PLClibraryHandle, "PythonIterator", None) + if self._PythonIterator is not None: + self._PythonIterator.restype = ctypes.c_char_p + self._PythonIterator.argtypes = [ctypes.c_char_p] + + def StopPLCLock(): + self.PLClibraryLock.acquire() + self.PLClibraryHandle.stopPLC() + self.PLClibraryLock.release() + + else: + def DummyIterator(res): + self.DummyIteratorLock.acquire() + return None + self._PythonIterator = DummyIterator + + def StopPLCLock(): + self.PLClibraryLock.acquire() + self.PLClibraryHandle.stopPLC() + self.DummyIteratorLock.release() + self.PLClibraryLock.release() self._stopPLC = StopPLCLock self._stopPLC.restype = None @@ -123,10 +145,6 @@ self._resumeDebug = self.PLClibraryHandle.resumeDebug self._resumeDebug.restype = None - - self._PythonIterator = self.PLClibraryHandle.PythonIterator - self._PythonIterator.restype = ctypes.c_char_p - self._PythonIterator.argtypes = [ctypes.c_char_p] return True except: @@ -188,59 +206,38 @@ def PrepareRuntimePy(self): self.python_threads_vars = globals().copy() self.python_threads_vars["WorkingDir"] = self.workingdir - pyfile = os.path.join(self.workingdir, "runtime.py") - hmifile = os.path.join(self.workingdir, "hmi.py") - if os.path.exists(hmifile): - try: - execfile(hmifile, self.python_threads_vars) - if os.path.exists(pyfile): - try: - # TODO handle exceptions in runtime.py - # pyfile may redefine _runtime_cleanup - # or even call _PythonThreadProc itself. - execfile(pyfile, self.python_threads_vars) - except: - PLCprint(traceback.format_exc()) - if self.python_threads_vars.has_key('wx'): - wx = self.python_threads_vars['wx'] - # try to instanciate the first frame found. - for name, obj in self.python_threads_vars.iteritems(): - # obj is a class - if type(obj)==type(type) and issubclass(obj,wx.Frame): - def create_frame(): - self.hmi_frame = obj(None) - self.python_threads_vars[name] = self.hmi_frame - # keep track of class... never know - self.python_threads_vars['Class_'+name] = obj - self.hmi_frame.Bind(wx.EVT_CLOSE, OnCloseFrame) - self.hmi_frame.Show() - - def OnCloseFrame(evt): - wx.MessageBox("Please stop PLC to close") - create_frame() - break - except: - PLCprint(traceback.format_exc()) - elif os.path.exists(pyfile): - try: - # TODO handle exceptions in runtime.py - # pyfile may redefine _runtime_cleanup - # or even call _PythonThreadProc itself. - execfile(pyfile, self.python_threads_vars) - except: - PLCprint(traceback.format_exc()) - runtime_begin = self.python_threads_vars.get("_runtime_begin",None) - if runtime_begin is not None: + self.python_threads_vars["website"] = self.website + self.python_threads_vars["_runtime_begin"] = [] + self.python_threads_vars["_runtime_cleanup"] = [] + + for filename in os.listdir(self.workingdir): + name, ext = os.path.splitext(filename) + if name.startswith("runtime") and ext == ".py": + try: + # TODO handle exceptions in runtime.py + # pyfile may redefine _runtime_cleanup + # or even call _PythonThreadProc itself. + execfile(os.path.join(self.workingdir, filename), self.python_threads_vars) + except: + PLCprint(traceback.format_exc()) + runtime_begin = self.python_threads_vars.get("_%s_begin" % name, None) + if runtime_begin is not None: + self.python_threads_vars["_runtime_begin"].append(runtime_begin) + runtime_cleanup = self.python_threads_vars.get("_%s_cleanup" % name, None) + if runtime_cleanup is not None: + self.python_threads_vars["_runtime_cleanup"].append(runtime_cleanup) + + for runtime_begin in self.python_threads_vars.get("_runtime_begin", []): runtime_begin() + + if self.website is not None: + self.website.PLCStarted() def FinishRuntimePy(self): - runtime_cleanup = None - if self.python_threads_vars is not None: - runtime_cleanup = self.python_threads_vars.get("_runtime_cleanup",None) - if runtime_cleanup is not None: - runtime_cleanup() - if self.hmi_frame is not None: - self.hmi_frame.Destroy() + for runtime_cleanup in self.python_threads_vars.get("_runtime_cleanup", []): + runtime_cleanup() + if self.website is not None: + self.website.PLCStopped() self.python_threads_vars = None def PythonThreadProc(self, debug): @@ -317,9 +314,9 @@ try: os.remove(os.path.join(self.workingdir, self.CurrentPLCFilename)) - for filename in file(extra_files_log, "r").readlines() + extra_files_log: + for filename in file(extra_files_log, "r").readlines() + [extra_files_log]: try: - os.remove(os.path.join(self.workingdir, filename)) + os.remove(os.path.join(self.workingdir, filename.strip())) except: pass except: diff -r 75ae46b66315 -r 71c441104cac targets/Xenomai/__init__.py --- a/targets/Xenomai/__init__.py Wed Aug 12 16:23:59 2009 -0600 +++ b/targets/Xenomai/__init__.py Thu Aug 13 11:37:38 2009 +0200 @@ -13,7 +13,7 @@ status, result, err_result = ProcessLogger(self.logger, xeno_config + " --xeno-ldflags", no_stdout=True).spin() if status: - self.logger.write_error("Unable to get Xenomai's LDFLAGS\n") + self.logger.write_error(_("Unable to get Xenomai's LDFLAGS\n")) xeno_ldlags = result.strip() return toolchain_gcc.getBuilderLDFLAGS(self) + [xeno_ldlags, "-shared", "-lnative"] @@ -24,7 +24,7 @@ status, result, err_result = ProcessLogger(self.logger, xeno_config + " --xeno-cflags", no_stdout=True).spin() if status: - self.logger.write_error("Unable to get Xenomai's CFLAGS\n") + self.logger.write_error(_("Unable to get Xenomai's CFLAGS\n")) xeno_cflags = result.strip() return toolchain_gcc.getBuilderCFLAGS(self) + [xeno_cflags] diff -r 75ae46b66315 -r 71c441104cac targets/plc_common_main.c --- a/targets/plc_common_main.c Wed Aug 12 16:23:59 2009 -0600 +++ b/targets/plc_common_main.c Thu Aug 13 11:37:38 2009 +0200 @@ -18,11 +18,6 @@ /*void __retrieve_debug(void);*/ void __publish_debug(void); -void __init_python(void); -void __cleanup_python(void); -void __retrieve_python(void); -void __publish_python(void); - /* * Variables used by generated C softPLC and plugins **/ @@ -47,14 +42,10 @@ %(retrieve_calls)s - __retrieve_python(); - /*__retrieve_debug();*/ config_run__(__tick); - __publish_python(); - __publish_debug(); %(publish_calls)s @@ -71,7 +62,6 @@ setlocale(LC_NUMERIC, "C"); config_init__(); __init_debug(); - __init_python(); %(init_calls)s return 0; } @@ -82,7 +72,6 @@ { %(cleanup_calls)s __cleanup_debug(); - __cleanup_python(); } diff -r 75ae46b66315 -r 71c441104cac targets/plc_python.c --- a/targets/plc_python.c Wed Aug 12 16:23:59 2009 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,213 +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); - -void __init_python() -{ - 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; -} - -void __cleanup_python() -{ - PythonState = PYTHON_FINISHED; - UnBlockPythonCommands(); -} - -void __retrieve_python() -{ - /* 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_python() -{ - 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(((data__->TRIG && !data__->TRIGM1) || - /* polling is equivalent to trig on value rather than on rising edge*/ - (poll && data__->TRIG )) && - /* trig only if not already trigged */ - data__->TRIGGED == 0){ - /* mark as trigged */ - data__->TRIGGED = 1; - /* make a safe copy of the code */ - data__->PREBUFFER = data__->CODE; - } - /* retain value for next rising edge detection */ - data__->TRIGM1 = data__->TRIG; - - /* python thread is not in ? */ - if( PythonState & PYTHON_LOCKED_BY_PLC){ - /* if some answer are waiting, publish*/ - if(data__->STATE == PYTHON_FB_ANSWERED){ - /* Copy buffer content into result*/ - data__->RESULT = data__->BUFFER; - /* signal result presece to PLC*/ - data__->ACK = 1; - /* Mark as free */ - data__->STATE = PYTHON_FB_FREE; - /* mark as not trigged */ - if(!poll) - 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 */ - data__->ACK = 0; - } - /* got the order to act ?*/ - if(data__->TRIGGED == 1 && - /* and not already being processed */ - 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*/ - data__->BUFFER = 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*/ - data__->ACK = 0; - }else{ - /* when in polling, acting reset trigger */ - data__->TRIGGED = 0; - } - /* Mark FB busy */ - 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); - /* 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 */ - data__->STATE == PYTHON_FB_PROCESSING){ /* some answer awaited*/ - /* If result not None */ - if(result){ - /* Get results len */ - data__->BUFFER.len = strlen(result); - /* prevent results overrun */ - if(data__->BUFFER.len > STR_MAX_LEN) - { - data__->BUFFER.len = STR_MAX_LEN; - /* TODO : signal error */ - } - /* Copy results to buffer */ - strncpy(data__->BUFFER.body, result, data__->BUFFER.len); - }else{ - data__->BUFFER.len = 0; - } - /* remove block from fifo*/ - EvalFBs[Current_Python_EvalFB] = NULL; - /* Mark block as answered */ - 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 */ - 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 */ - data__->STATE = PYTHON_FB_PROCESSING; - //printf("PythonIterator\n"); - /* make BUFFER a null terminated string */ - data__->BUFFER.body[data__->BUFFER.len] = 0; - /* next command is BUFFER */ - next_command = data__->BUFFER.body; - /* free python mutex */ - UnLockPython(); - /* return the next command to eval */ - return next_command; -} - diff -r 75ae46b66315 -r 71c441104cac targets/toolchain_gcc.py --- a/targets/toolchain_gcc.py Wed Aug 12 16:23:59 2009 -0600 +++ b/targets/toolchain_gcc.py Thu Aug 13 11:37:38 2009 +0200 @@ -90,9 +90,9 @@ relink = False for Location, CFilesAndCFLAGS, DoCalls in self.PluginsRootInstance.LocationCFilesAndCFLAGS: if Location: - self.logger.write("Plugin : " + self.PluginsRootInstance.GetChildByIECLocation(Location).GetCurrentName() + " " + str(Location)+"\n") + self.logger.write(_("Plugin : ") + self.PluginsRootInstance.GetChildByIECLocation(Location).GetCurrentName() + " " + str(Location)+"\n") else: - self.logger.write("PLC :\n") + self.logger.write(_("PLC :\n")) for CFile, CFLAGS in CFilesAndCFLAGS: bn = os.path.basename(CFile) @@ -116,7 +116,7 @@ if status : self.srcmd5.pop(bn) - self.logger.write_error("C compilation of "+ bn +" failed.\n") + self.logger.write_error(_("C compilation of %s failed.\n")%bn) return False obns.append(obn) @@ -124,7 +124,7 @@ ######### GENERATE library FILE ######################################## # Link all the object files into one binary file - self.logger.write("Linking :\n") + self.logger.write(_("Linking :\n")) if relink: objstring = [] diff -r 75ae46b66315 -r 71c441104cac tests/linux/test_svgui/.cvsignore --- a/tests/linux/test_svgui/.cvsignore Wed Aug 12 16:23:59 2009 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -build diff -r 75ae46b66315 -r 71c441104cac tests/linux/test_svgui/CANopen@canfestival/Master@CanOpenNode/baseplugin.xml --- a/tests/linux/test_svgui/CANopen@canfestival/Master@CanOpenNode/baseplugin.xml Wed Aug 12 16:23:59 2009 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ - - diff -r 75ae46b66315 -r 71c441104cac tests/linux/test_svgui/CANopen@canfestival/Master@CanOpenNode/eds/DS401_Slave_Gui.eds --- a/tests/linux/test_svgui/CANopen@canfestival/Master@CanOpenNode/eds/DS401_Slave_Gui.eds Wed Aug 12 16:23:59 2009 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1142 +0,0 @@ -[FileInfo] -FileName=DS401_Slave_Gui.eds -FileVersion=1 -FileRevision=1 -EDSVersion=4.0 -Description= -CreationTime=05:58PM -CreationDate=10-02-2007 -CreatedBy=CANFestival -ModificationTime=05:58PM -ModificationDate=10-02-2007 -ModifiedBy=CANFestival - -[DeviceInfo] -VendorName=CANFestival -VendorNumber=0x00000175 -ProductName=ObjDict -ProductNumber=0x00100000 -RevisionNumber=0x00010001 -BaudRate_10=1 -BaudRate_20=1 -BaudRate_50=1 -BaudRate_125=1 -BaudRate_250=1 -BaudRate_500=1 -BaudRate_800=1 -BaudRate_1000=1 -SimpleBootUpMaster=0 -SimpleBootUpSlave=1 -Granularity=8 -DynamicChannelsSupported=0 -CompactPDO=0 -GroupMessaging=0 -NrOfRXPDO=2 -NrOfTXPDO=3 -LSS_Supported=0 - -[DummyUsage] -Dummy0001=0 -Dummy0002=1 -Dummy0003=1 -Dummy0004=1 -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=983441 -PDOMapping=0 - -[1001] -ParameterName=Error Register -ObjectType=0x7 -DataType=0x0005 -AccessType=ro -DefaultValue=0 -PDOMapping=1 - -[1018] -ParameterName=Identity -ObjectType=0x8 -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=373 -PDOMapping=0 - -[1018sub2] -ParameterName=Product Code -ObjectType=0x7 -DataType=0x0007 -AccessType=ro -DefaultValue=1048576 -PDOMapping=0 - -[1018sub3] -ParameterName=Revision Number -ObjectType=0x7 -DataType=0x0007 -AccessType=ro -DefaultValue=65537 -PDOMapping=0 - -[OptionalObjects] -SupportedObjects=35 -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=0x1200 -14=0x1400 -15=0x1401 -16=0x1600 -17=0x1601 -18=0x1800 -19=0x1801 -20=0x1802 -21=0x1A00 -22=0x1A01 -23=0x1A02 -24=0x6000 -25=0x6002 -26=0x6200 -27=0x6202 -28=0x6206 -29=0x6207 -30=0x6401 -31=0x6411 -32=0x6423 -33=0x6426 -34=0x6443 -35=0x6444 - -[1002] -ParameterName=Manufacturer Status Register -ObjectType=0x7 -DataType=0x0007 -AccessType=ro -DefaultValue=0 -PDOMapping=1 - -[1005] -ParameterName=SYNC COB ID -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=128 -PDOMapping=0 - -[1008] -ParameterName=Manufacturer Device Name -ObjectType=0x7 -DataType=0x0009 -AccessType=ro -DefaultValue=0 -PDOMapping=0 - -[1009] -ParameterName=Manufacturer Hardware Version -ObjectType=0x7 -DataType=0x0009 -AccessType=ro -DefaultValue=0 -PDOMapping=0 - -[100A] -ParameterName=Manufacturer Software Version -ObjectType=0x7 -DataType=0x0009 -AccessType=ro -DefaultValue=0 -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=0 -PDOMapping=0 - -[1010] -ParameterName=Store parameters -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 -DefaultValue=0 -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 -DefaultValue=0 -PDOMapping=0 - -[1016] -ParameterName=Consumer Heartbeat Time -ObjectType=0x9 -SubNumber=4 - -[1016sub0] -ParameterName=Number of Entries -ObjectType=0x7 -DataType=0x0005 -AccessType=ro -DefaultValue=3 -PDOMapping=0 - -[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=ro -DefaultValue=0 -PDOMapping=0 - -[1020sub2] -ParameterName=Configuration Time -ObjectType=0x7 -DataType=0x0007 -AccessType=ro -DefaultValue=0 -PDOMapping=0 - -[1200] -ParameterName=Server SDO Parameter -ObjectType=0x8 -SubNumber=3 - -[1200sub0] -ParameterName=Number of Entries -ObjectType=0x7 -DataType=0x0005 -AccessType=ro -DefaultValue=2 -PDOMapping=0 - -[1200sub1] -ParameterName=COB ID Client to Server (Receive SDO) -ObjectType=0x7 -DataType=0x0007 -AccessType=ro -DefaultValue=$NODEID+0x600 -PDOMapping=0 - -[1200sub2] -ParameterName=COB ID Server to Client (Transmit SDO) -ObjectType=0x7 -DataType=0x0007 -AccessType=ro -DefaultValue=$NODEID+0x580 -PDOMapping=0 - -[1400] -ParameterName=Receive PDO 1 Parameter -ObjectType=0x8 -SubNumber=3 - -[1400sub0] -ParameterName=Highest SubIndex Supported -ObjectType=0x7 -DataType=0x0005 -AccessType=ro -DefaultValue=2 -PDOMapping=0 - -[1400sub1] -ParameterName=COB ID used by PDO -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=$NODEID+0x200 -PDOMapping=0 - -[1400sub2] -ParameterName=Transmission Type -ObjectType=0x7 -DataType=0x0005 -AccessType=rw -DefaultValue=1 -PDOMapping=0 - -[1401] -ParameterName=Receive PDO 2 Parameter -ObjectType=0x8 -SubNumber=3 - -[1401sub0] -ParameterName=Highest SubIndex Supported -ObjectType=0x7 -DataType=0x0005 -AccessType=ro -DefaultValue=2 -PDOMapping=0 - -[1401sub1] -ParameterName=COB ID used by PDO -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=$NODEID+0x300 -PDOMapping=0 - -[1401sub2] -ParameterName=Transmission Type -ObjectType=0x7 -DataType=0x0005 -AccessType=rw -DefaultValue=1 -PDOMapping=0 - -[1600] -ParameterName=Receive PDO 1 Mapping -ObjectType=0x9 -SubNumber=2 - -[1600sub0] -ParameterName=Number of Entries -ObjectType=0x7 -DataType=0x0005 -AccessType=rw -DefaultValue=1 -PDOMapping=0 - -[1600sub1] -ParameterName=PDO 1 Mapping for an application object 1 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=1644167432 -PDOMapping=0 - -[1601] -ParameterName=Receive PDO 2 Mapping -ObjectType=0x9 -SubNumber=5 - -[1601sub0] -ParameterName=Number of Entries -ObjectType=0x7 -DataType=0x0005 -AccessType=rw -DefaultValue=4 -PDOMapping=0 - -[1601sub1] -ParameterName=PDO 2 Mapping for an application object 1 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=1678835984 -PDOMapping=0 - -[1601sub2] -ParameterName=PDO 2 Mapping for an application object 2 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=1678836240 -PDOMapping=0 - -[1601sub3] -ParameterName=PDO 2 Mapping for an application object 3 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=1678836496 -PDOMapping=0 - -[1601sub4] -ParameterName=PDO 2 Mapping for an application object 4 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=1678836752 -PDOMapping=0 - -[1800] -ParameterName=Transmit PDO 1 Parameter -ObjectType=0x8 -SubNumber=5 - -[1800sub0] -ParameterName=Highest SubIndex Supported -ObjectType=0x7 -DataType=0x0005 -AccessType=ro -DefaultValue=5 -PDOMapping=0 - -[1800sub1] -ParameterName=COB ID used by PDO -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=$NODEID+0x180 -PDOMapping=0 - -[1800sub2] -ParameterName=Transmission Type -ObjectType=0x7 -DataType=0x0005 -AccessType=rw -DefaultValue=1 -PDOMapping=0 - -[1800sub3] -ParameterName=Inhibit Time -ObjectType=0x7 -DataType=0x0006 -AccessType=rw -DefaultValue=0 -PDOMapping=0 - -[1800sub5] -ParameterName=Event Timer -ObjectType=0x7 -DataType=0x0006 -AccessType=rw -DefaultValue=0 -PDOMapping=0 - -[1801] -ParameterName=Transmit PDO 2 Parameter -ObjectType=0x8 -SubNumber=5 - -[1801sub0] -ParameterName=Highest SubIndex Supported -ObjectType=0x7 -DataType=0x0005 -AccessType=ro -DefaultValue=5 -PDOMapping=0 - -[1801sub1] -ParameterName=COB ID used by PDO -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=$NODEID+0x280 -PDOMapping=0 - -[1801sub2] -ParameterName=Transmission Type -ObjectType=0x7 -DataType=0x0005 -AccessType=rw -DefaultValue=1 -PDOMapping=0 - -[1801sub3] -ParameterName=Inhibit Time -ObjectType=0x7 -DataType=0x0006 -AccessType=rw -DefaultValue=0 -PDOMapping=0 - -[1801sub5] -ParameterName=Event Timer -ObjectType=0x7 -DataType=0x0006 -AccessType=rw -DefaultValue=0 -PDOMapping=0 - -[1802] -ParameterName=Transmit PDO 3 Parameter -ObjectType=0x8 -SubNumber=5 - -[1802sub0] -ParameterName=Highest SubIndex Supported -ObjectType=0x7 -DataType=0x0005 -AccessType=ro -DefaultValue=5 -PDOMapping=0 - -[1802sub1] -ParameterName=COB ID used by PDO -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=$NODEID+0x380 -PDOMapping=0 - -[1802sub2] -ParameterName=Transmission Type -ObjectType=0x7 -DataType=0x0005 -AccessType=rw -DefaultValue=1 -PDOMapping=0 - -[1802sub3] -ParameterName=Inhibit Time -ObjectType=0x7 -DataType=0x0006 -AccessType=rw -DefaultValue=0 -PDOMapping=0 - -[1802sub5] -ParameterName=Event Timer -ObjectType=0x7 -DataType=0x0006 -AccessType=rw -DefaultValue=0 -PDOMapping=0 - -[1A00] -ParameterName=Transmit PDO 1 Mapping -ObjectType=0x9 -SubNumber=2 - -[1A00sub0] -ParameterName=Number of Entries -ObjectType=0x7 -DataType=0x0005 -AccessType=rw -DefaultValue=1 -PDOMapping=0 - -[1A00sub1] -ParameterName=PDO 1 Mapping for a process data variable 1 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=1610613000 -PDOMapping=0 - -[1A01] -ParameterName=Transmit PDO 2 Mapping -ObjectType=0x9 -SubNumber=5 - -[1A01sub0] -ParameterName=Number of Entries -ObjectType=0x7 -DataType=0x0005 -AccessType=rw -DefaultValue=4 -PDOMapping=0 - -[1A01sub1] -ParameterName=PDO 2 Mapping for a process data variable 1 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=1677787408 -PDOMapping=0 - -[1A01sub2] -ParameterName=PDO 2 Mapping for a process data variable 2 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=1677787664 -PDOMapping=0 - -[1A01sub3] -ParameterName=PDO 2 Mapping for a process data variable 3 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=1677787920 -PDOMapping=0 - -[1A01sub4] -ParameterName=PDO 2 Mapping for a process data variable 4 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=1677788176 -PDOMapping=0 - -[1A02] -ParameterName=Transmit PDO 3 Mapping -ObjectType=0x9 -SubNumber=5 - -[1A02sub0] -ParameterName=Number of Entries -ObjectType=0x7 -DataType=0x0005 -AccessType=rw -DefaultValue=4 -PDOMapping=0 - -[1A02sub1] -ParameterName=PDO 3 Mapping for a process data variable 1 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=1677788432 -PDOMapping=0 - -[1A02sub2] -ParameterName=PDO 3 Mapping for a process data variable 2 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=1677788688 -PDOMapping=0 - -[1A02sub3] -ParameterName=PDO 3 Mapping for a process data variable 3 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=1677788944 -PDOMapping=0 - -[1A02sub4] -ParameterName=PDO 3 Mapping for a process data variable 4 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=1677789200 -PDOMapping=0 - -[6000] -ParameterName=Read Inputs 8 Bit -ObjectType=0x9 -SubNumber=2 - -[6000sub0] -ParameterName=Number of Input 8 bit -ObjectType=0x7 -DataType=0x0005 -AccessType=ro -DefaultValue=1 -PDOMapping=0 - -[6000sub1] -ParameterName=Read Inputs 0x1 to 0x8 -ObjectType=0x7 -DataType=0x0005 -AccessType=ro -DefaultValue=0 -PDOMapping=1 - -[6002] -ParameterName=Polarity Input 8 Bit -ObjectType=0x9 -SubNumber=2 - -[6002sub0] -ParameterName=Number of Input 8 bit -ObjectType=0x7 -DataType=0x0005 -AccessType=ro -DefaultValue=1 -PDOMapping=0 - -[6002sub1] -ParameterName=Polarity Input 0x1 to 0x8 -ObjectType=0x7 -DataType=0x0005 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6200] -ParameterName=Write Outputs 8 Bit -ObjectType=0x9 -SubNumber=2 - -[6200sub0] -ParameterName=Number of Output 8 Bit -ObjectType=0x7 -DataType=0x0005 -AccessType=ro -DefaultValue=1 -PDOMapping=0 - -[6200sub1] -ParameterName=Write Outputs 0x1 to 0x8 -ObjectType=0x7 -DataType=0x0005 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6202] -ParameterName=Change Polarity Outputs 8 Bit -ObjectType=0x9 -SubNumber=2 - -[6202sub0] -ParameterName=Number of Output 8 Bit -ObjectType=0x7 -DataType=0x0005 -AccessType=ro -DefaultValue=1 -PDOMapping=0 - -[6202sub1] -ParameterName=Change Polarity Outputs 0x1 to 0x8 -ObjectType=0x7 -DataType=0x0005 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6206] -ParameterName=Error Mode Outputs 8 Bit -ObjectType=0x9 -SubNumber=2 - -[6206sub0] -ParameterName=Number of Output 8 Bit -ObjectType=0x7 -DataType=0x0005 -AccessType=ro -DefaultValue=1 -PDOMapping=0 - -[6206sub1] -ParameterName=Error Mode Outputs 0x1 to 0x8 -ObjectType=0x7 -DataType=0x0005 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6207] -ParameterName=Error Value Outputs 8 Bit -ObjectType=0x9 -SubNumber=2 - -[6207sub0] -ParameterName=Number of Output 8 Bit -ObjectType=0x7 -DataType=0x0005 -AccessType=ro -DefaultValue=1 -PDOMapping=0 - -[6207sub1] -ParameterName=Error Value Outputs 0x1 to 0x8 -ObjectType=0x7 -DataType=0x0005 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6401] -ParameterName=Read Analogue Input 16 Bit -ObjectType=0x9 -SubNumber=9 - -[6401sub0] -ParameterName=Number of Analogue Input 16 Bit -ObjectType=0x7 -DataType=0x0005 -AccessType=ro -DefaultValue=8 -PDOMapping=0 - -[6401sub1] -ParameterName=Analogue Input 1 -ObjectType=0x7 -DataType=0x0003 -AccessType=ro -DefaultValue=0 -PDOMapping=1 - -[6401sub2] -ParameterName=Analogue Input 2 -ObjectType=0x7 -DataType=0x0003 -AccessType=ro -DefaultValue=0 -PDOMapping=1 - -[6401sub3] -ParameterName=Analogue Input 3 -ObjectType=0x7 -DataType=0x0003 -AccessType=ro -DefaultValue=0 -PDOMapping=1 - -[6401sub4] -ParameterName=Analogue Input 4 -ObjectType=0x7 -DataType=0x0003 -AccessType=ro -DefaultValue=0 -PDOMapping=1 - -[6401sub5] -ParameterName=Analogue Input 5 -ObjectType=0x7 -DataType=0x0003 -AccessType=ro -DefaultValue=0 -PDOMapping=1 - -[6401sub6] -ParameterName=Analogue Input 6 -ObjectType=0x7 -DataType=0x0003 -AccessType=ro -DefaultValue=0 -PDOMapping=1 - -[6401sub7] -ParameterName=Analogue Input 7 -ObjectType=0x7 -DataType=0x0003 -AccessType=ro -DefaultValue=0 -PDOMapping=1 - -[6401sub8] -ParameterName=Analogue Input 8 -ObjectType=0x7 -DataType=0x0003 -AccessType=ro -DefaultValue=0 -PDOMapping=1 - -[6411] -ParameterName=Write Analogue Output 16 Bit -ObjectType=0x9 -SubNumber=5 - -[6411sub0] -ParameterName=Number of Analogue Input 16 Bit -ObjectType=0x7 -DataType=0x0005 -AccessType=ro -DefaultValue=4 -PDOMapping=0 - -[6411sub1] -ParameterName=Analogue Output 1 -ObjectType=0x7 -DataType=0x0003 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6411sub2] -ParameterName=Analogue Output 2 -ObjectType=0x7 -DataType=0x0003 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6411sub3] -ParameterName=Analogue Output 3 -ObjectType=0x7 -DataType=0x0003 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6411sub4] -ParameterName=Analogue Output 4 -ObjectType=0x7 -DataType=0x0003 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6423] -ParameterName=Analogue Input Global Interrupt Enable -ObjectType=0x7 -DataType=0x0001 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6426] -ParameterName=Analogue Input Interrupt Delta Unsigned -ObjectType=0x9 -SubNumber=9 - -[6426sub0] -ParameterName=Number of Analogue Inputs -ObjectType=0x7 -DataType=0x0005 -AccessType=ro -DefaultValue=8 -PDOMapping=0 - -[6426sub1] -ParameterName=Analogue Input 1 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6426sub2] -ParameterName=Analogue Input 2 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6426sub3] -ParameterName=Analogue Input 3 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6426sub4] -ParameterName=Analogue Input 4 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6426sub5] -ParameterName=Analogue Input 5 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6426sub6] -ParameterName=Analogue Input 6 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6426sub7] -ParameterName=Analogue Input 7 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6426sub8] -ParameterName=Analogue Input 8 -ObjectType=0x7 -DataType=0x0007 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6443] -ParameterName=Analogue Output Error Mode -ObjectType=0x9 -SubNumber=5 - -[6443sub0] -ParameterName=Number of Analogue Outputs -ObjectType=0x7 -DataType=0x0005 -AccessType=ro -DefaultValue=4 -PDOMapping=0 - -[6443sub1] -ParameterName=Error Mode Analogue Output 1 -ObjectType=0x7 -DataType=0x0005 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6443sub2] -ParameterName=Error Mode Analogue Output 2 -ObjectType=0x7 -DataType=0x0005 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6443sub3] -ParameterName=Error Mode Analogue Output 3 -ObjectType=0x7 -DataType=0x0005 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6443sub4] -ParameterName=Error Mode Analogue Output 4 -ObjectType=0x7 -DataType=0x0005 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6444] -ParameterName=Analogue Output Error Value Integer -ObjectType=0x9 -SubNumber=5 - -[6444sub0] -ParameterName=Number of Analogue Outputs -ObjectType=0x7 -DataType=0x0005 -AccessType=ro -DefaultValue=4 -PDOMapping=0 - -[6444sub1] -ParameterName=Analogue Output 1 -ObjectType=0x7 -DataType=0x0004 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6444sub2] -ParameterName=Analogue Output 2 -ObjectType=0x7 -DataType=0x0004 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6444sub3] -ParameterName=Analogue Output 3 -ObjectType=0x7 -DataType=0x0004 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[6444sub4] -ParameterName=Analogue Output 4 -ObjectType=0x7 -DataType=0x0004 -AccessType=rw -DefaultValue=0 -PDOMapping=1 - -[ManufacturerObjects] -SupportedObjects=0 diff -r 75ae46b66315 -r 71c441104cac tests/linux/test_svgui/CANopen@canfestival/Master@CanOpenNode/eds/PEAK MicroMod.eds --- a/tests/linux/test_svgui/CANopen@canfestival/Master@CanOpenNode/eds/PEAK MicroMod.eds Wed Aug 12 16:23:59 2009 -0600 +++ /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 75ae46b66315 -r 71c441104cac tests/linux/test_svgui/CANopen@canfestival/Master@CanOpenNode/master.od --- a/tests/linux/test_svgui/CANopen@canfestival/Master@CanOpenNode/master.od Wed Aug 12 16:23:59 2009 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,224 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 75ae46b66315 -r 71c441104cac tests/linux/test_svgui/CANopen@canfestival/Master@CanOpenNode/nodelist.cpj --- a/tests/linux/test_svgui/CANopen@canfestival/Master@CanOpenNode/nodelist.cpj Wed Aug 12 16:23:59 2009 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -[TOPOLOGY] -NetName=None -Nodes=0x02 -Node16Present=0x01 -Node16Name=DS401_Slave_GUI -Node16DCFName=DS401_Slave_Gui.eds -Node32Present=0x01 -Node32Name=GUI2 -Node32DCFName=DS401_Slave_Gui.eds -EDSBaseName=eds diff -r 75ae46b66315 -r 71c441104cac tests/linux/test_svgui/CANopen@canfestival/Master@CanOpenNode/plugin.xml --- a/tests/linux/test_svgui/CANopen@canfestival/Master@CanOpenNode/plugin.xml Wed Aug 12 16:23:59 2009 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ - - diff -r 75ae46b66315 -r 71c441104cac tests/linux/test_svgui/CANopen@canfestival/baseplugin.xml --- a/tests/linux/test_svgui/CANopen@canfestival/baseplugin.xml Wed Aug 12 16:23:59 2009 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ - - diff -r 75ae46b66315 -r 71c441104cac tests/linux/test_svgui/CANopen@canfestival/plugin.xml --- a/tests/linux/test_svgui/CANopen@canfestival/plugin.xml Wed Aug 12 16:23:59 2009 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ - - diff -r 75ae46b66315 -r 71c441104cac tests/linux/test_svgui/beremiz.xml --- a/tests/linux/test_svgui/beremiz.xml Wed Aug 12 16:23:59 2009 -0600 +++ b/tests/linux/test_svgui/beremiz.xml Thu Aug 13 11:37:38 2009 +0200 @@ -1,6 +1,6 @@ - + diff -r 75ae46b66315 -r 71c441104cac tests/linux/test_svgui/methods.py --- a/tests/linux/test_svgui/methods.py Wed Aug 12 16:23:59 2009 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -self.logger.write_error("Welcome to the Beremiz Demo\n\n") -self.logger.write("This demo provides a PLC working with the CANopen plugin\n") -self.logger.write("""Some external programs are also provided:\n -- a CAN TCP server to simulate the CANopen network -- a virtual slave node to simulate input block -- a virtual slave node to simulate output block -""") -self.logger.write("\nInfo: For this demo, %s plugin has some special methods to run external programs.\nThese methods are defined in methods.py\n" % (PlugName or "Root")) -#open_pdf(os.path.join(os.path.split(__file__)[0], "doc", "manual_beremiz.pdf"), pagenum=21) - -if wx.Platform == '__WXMSW__': - self.listLaunchProg = [ - {'name' : 'Can Tcp Server', - 'command' : 'can_tcp_win32_server.exe', - 'keyword' : 'Accepts', - 'pid' : None, - 'no_gui' : True}, - {'name' : 'DS401 Slave Gui NodeId 32', - 'command' : 'DS401_Slave_Gui.exe -sI -l can_tcp_win32.dll -b 127.0.0.1 -i 20 -B 125K', - 'keyword' : '[OK]', - 'pid' : None, - 'no_gui' : False}, - {'name' : 'DS401 Slave Gui NodeId 16', - 'command' : 'DS401_Slave_Gui.exe -sO -l can_tcp_win32.dll -b 127.0.0.1 -i 10 -B 125K', - 'keyword' : '[OK]', - 'pid' : None, - 'no_gui' : False} - ] -else: - self.listLaunchProg = [ - {'name' : 'DS401 Slave Gui NodeId 32', - 'command' : '../CanFestival-3/examples/DS401_Slave_Gui/DS401_Slave_Gui -sI -l ../CanFestival-3/drivers/can_socket/libcanfestival_can_socket.so -b vcan0 -i 20 -B 125K', - 'keyword' : '[OK]', - 'pid' : None, - 'no_gui' : False}, - {'name' : 'DS401 Slave Gui NodeId 16', - 'command' : '../CanFestival-3/examples/DS401_Slave_Gui/DS401_Slave_Gui -sO -l ../CanFestival-3/drivers/can_socket/libcanfestival_can_socket.so -b vcan0 -i 10 -B 125K', - 'keyword' : '[OK]', - 'pid' : None, - 'no_gui' : False} - ] - - -def my_methods(self): - def _Run(): - # External programs list - # Launch them and get their pid - for prog in self.listLaunchProg: - self.logger.write("Starting %s\n" % prog['name']) - prog['pid'] = ProcessLogger(self.logger, prog['command'], no_gui=prog['no_gui']) - prog['pid'].spin( - timeout=200, - keyword = prog['keyword'], - kill_it = False) - - PluginsRoot._Run(self) - - def _Stop(): - PluginsRoot._Stop(self) - for prog in self.listLaunchProg: - self.logger.write("Stopping %s\n" % prog['name']) - prog['pid'].kill() - - return _Run, _Stop - -self._Run, self._Stop = my_methods(self) \ No newline at end of file diff -r 75ae46b66315 -r 71c441104cac tests/linux/test_svgui/plc.xml --- a/tests/linux/test_svgui/plc.xml Wed Aug 12 16:23:59 2009 -0600 +++ b/tests/linux/test_svgui/plc.xml Thu Aug 13 11:37:38 2009 +0200 @@ -2,17 +2,15 @@ + xsi:schemaLocation="http://www.plcopen.org/xml/tc6.xsd"> - + productName="Beremiz" + productVersion="0.0" + creationDateTime="2008-12-14T16:21:19"/> + + @@ -25,2676 +23,890 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - - - - - - - - + + + + + + + + - - - - - - - - - - - - DigitalOut - - - - + + + + + + + + + + + + + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AnalogOut1 - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + - AnalogOut1 - - - - - - - AnalogIn1 - - - - - + + + + counter + + + + + + + INT#1 + + + + + + + 'stop_back' + + + + + + + 'stop_sele' + + + + + + + 'text_compteur' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 'led_stop' + + + + + + + 'led_start' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 'btn1_back' + + + + + + + 'btn1_sele' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 'btn2_back' + + + + + + + 'btn3_sele' + + + + + + + 'btn3_back' + + + + + + + 'btn2_sele' + + + + + + + 'btn4_back' + + + + + + + 'btn4_sele' + + + + + + + 'btn5_back' + + + + + + + 'btn5_sele' + + + + + + + 'btn6_back' + + + + + + + 'btn6_sele' + + + + + + + 'btn7_back' + + + + + + + 'btn7_sele' + + + + + + + 'btn8_back' + + + + + + + 'btn8_sele' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - AnalogOut2 + DigitalBit0 - - - - - - AnalogOut2 - - - - - - - AnalogIn2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - UINT#7 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + + - DigitalOut + DigitalBit1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - T#1s - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + + - AnalogOut3 + DigitalBit7 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REAL#10000.0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REAL#400.0 - - - - - - - REAL#-180.0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REAL#-180.0 - - - - - - - REAL#400.0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INPUT_BYTE - - - - - - - NUM_BIT - - - + + - - - + + + - GETBIT + DigitalBit6 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - BYTE#1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INPUT_BYTE - - - - - - - INPUT_BIT - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - NUM_BIT - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - BYTE#1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + + - SETBIT + DigitalBit5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - + + + + - - - - IN1 - - - + DigitalBit4 + + + - - - - + + + + - - - - IN2 - - - + DigitalBit3 + + + - - - - - - - - - - + + + + - - - - OUT_OR - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IN1 - - - - - - - - - - - - - - IN2 - - - - - - - - - - - - - - OUT_AND - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IN1 - - - - - - - - - - - - - - IN1 - - - - - - - - - - - - - - IN2 - - - - - - - - - - - - - - IN2 - - - - - - - - - - - - - - - - - - - - OUT_XOR - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IN1 - - - - - - - - - - - - - - IN2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OUT_SR - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -= UPPER1;]]> - - - - - - -= UPPER2;]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CNT1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CNT2 - - - - - - - - - - - - - - - - - - - - CNT1 - - - - - - - - - - - - - - CNT2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_ARRAY[0, 1] - - - - - - - UINT#0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + DigitalBit2 + + - - - - - + + + + diff -r 75ae46b66315 -r 71c441104cac tests/linux/test_svgui/python@python/baseplugin.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/linux/test_svgui/python@python/baseplugin.xml Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,2 @@ + + diff -r 75ae46b66315 -r 71c441104cac tests/linux/test_svgui/python@python/python.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/linux/test_svgui/python@python/python.xml Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,8 @@ + + + + diff -r 75ae46b66315 -r 71c441104cac tests/linux/test_svgui/python@python/svgui@svgui/baseplugin.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/linux/test_svgui/python@python/svgui@svgui/baseplugin.xml Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,2 @@ + + diff -r 75ae46b66315 -r 71c441104cac tests/linux/test_svgui/python@python/svgui@svgui/gui.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/linux/test_svgui/python@python/svgui@svgui/gui.svg Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,1505 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + Default + + + + + + Start + + + + + Stop + Stop + + + + + + + + + + + + + + + + + + 8 + + + + + + + + + 7 + + + + + + + + + 6 + + + + + + + + + 5 + + + + + + + + + 4 + + + + + + + + + 3 + + + + + + + + + 2 + + + + + + + + + 1 + + + + + + + + + + + 8 + + + + + + + + + 7 + + + + + + + + + 6 + + + + + + + + + 5 + + + + + + + + + 4 + + + + + + + + + 3 + + + + + + + + + 2 + + + + + + + + + 1 + + + + + diff -r 75ae46b66315 -r 71c441104cac tests/linux/test_svgui/python@python/svgui@svgui/python.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/linux/test_svgui/python@python/svgui@svgui/python.xml Thu Aug 13 11:37:38 2009 +0200 @@ -0,0 +1,4 @@ + + + + diff -r 75ae46b66315 -r 71c441104cac tests/linux/test_svgui/supervisor@svgui/baseplugin.xml --- a/tests/linux/test_svgui/supervisor@svgui/baseplugin.xml Wed Aug 12 16:23:59 2009 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ - - diff -r 75ae46b66315 -r 71c441104cac tests/linux/test_svgui/supervisor@svgui/gui.svg --- a/tests/linux/test_svgui/supervisor@svgui/gui.svg Wed Aug 12 16:23:59 2009 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,834 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - Pre-Alpha Release. Copyright © LOLITECH 2008 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Test 1 - - - - Test 1 - - - - Test 2 - - - - Test 2 - - AND - OR - XOR - SR - - - - - - - 100 - 200 - 300 - 400 - 0 - - - - - - - 100 - 200 - 300 - 400 - 0 - - - - - - diff -r 75ae46b66315 -r 71c441104cac tests/linux/test_svgui/supervisor@svgui/gui.xml --- a/tests/linux/test_svgui/supervisor@svgui/gui.xml Wed Aug 12 16:23:59 2009 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ - - -