--- a/Beremiz.py Tue Oct 27 16:32:54 2009 +0100
+++ b/Beremiz.py Mon Nov 02 15:38:49 2009 +0100
@@ -293,6 +293,8 @@
kind=wx.ITEM_NORMAL, text=_(u'Open\tCTRL+O'))
AppendMenu(parent, help='', id=wx.ID_SAVE,
kind=wx.ITEM_NORMAL, text=_(u'Save\tCTRL+S'))
+ AppendMenu(parent, help='', id=wx.ID_SAVEAS,
+ kind=wx.ITEM_NORMAL, text=_(u'Save as\tCTRL+SHIFT+S'))
AppendMenu(parent, help='', id=wx.ID_CLOSE,
kind=wx.ITEM_NORMAL, text=_(u'Close Tab\tCTRL+W'))
AppendMenu(parent, help='', id=wx.ID_CLOSE_ALL,
@@ -314,6 +316,7 @@
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)
+ self.Bind(wx.EVT_MENU, self.OnSaveProjectAsMenu, id=wx.ID_SAVEAS)
self.Bind(wx.EVT_MENU, self.OnCloseTabMenu, id=wx.ID_CLOSE)
self.Bind(wx.EVT_MENU, self.OnCloseProjectMenu, id=wx.ID_CLOSE_ALL)
self.Bind(wx.EVT_MENU, self.OnPageSetupMenu, id=wx.ID_PAGE_SETUP)
@@ -367,6 +370,7 @@
self.PLCConfig.SetBackgroundColour(wx.WHITE)
self.PLCConfig.Bind(wx.EVT_LEFT_DOWN, self.OnPanelLeftDown)
self.PLCConfig.Bind(wx.EVT_SIZE, self.OnMoveWindow)
+ self.PLCConfig.Bind(wx.EVT_MOUSEWHEEL, self.OnPLCConfigScroll)
self.BottomNoteBook.InsertPage(0, self.PLCConfig, _("Topology"), True)
self.LogConsole = wx.TextCtrl(id=ID_BEREMIZLOGCONSOLE, value='',
@@ -388,6 +392,8 @@
self.local_runtime_tmpdir = None
self.DisableEvents = False
+ # Variable allowing disabling of PLCConfig scroll when Popup shown
+ self.ScrollingEnabled = True
self.PluginInfos = {}
@@ -477,39 +483,46 @@
infos = self.PluginRoot.ShowError(self.Log,
(int(first_line), int(first_column)),
(int(last_line), int(last_column)))
-
+
+ ## Function displaying an Error dialog in PLCOpenEditor.
+ # @return False if closing cancelled.
+ def CheckSaveBeforeClosing(self, title=_("Close Project")):
+ if self.PluginRoot.ProjectTestModified():
+ dialog = wx.MessageDialog(self,
+ _("There are changes, do you want to save?"),
+ title,
+ wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
+ answer = dialog.ShowModal()
+ dialog.Destroy()
+ if answer == wx.ID_YES:
+ self.PluginRoot.SaveProject()
+ elif answer == wx.ID_CANCEL:
+ return False
+ return True
+
def OnCloseFrame(self, event):
- if self.PluginRoot is not None:
- if self.PluginRoot.ProjectTestModified():
- dialog = wx.MessageDialog(self,
- _("Save changes ?"),
- _("Close Application"),
- wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
- answer = dialog.ShowModal()
- dialog.Destroy()
- if answer == wx.ID_YES:
- self.PluginRoot.SaveProject()
- event.Skip()
- elif answer == wx.ID_NO:
- event.Skip()
- return
- else:
- event.Veto()
- return
-
- self.KillLocalRuntime()
-
- event.Skip()
+ if self.PluginRoot is None or self.CheckSaveBeforeClosing(_("Close Application")):
+ self.KillLocalRuntime()
+ event.Skip()
+ else:
+ event.Veto()
def OnMoveWindow(self, event):
self.GetBestSize()
self.RefreshScrollBars()
event.Skip()
+ def EnableScrolling(self, enable):
+ self.ScrollingEnabled = enable
+
+ def OnPLCConfigScroll(self, event):
+ if self.ScrollingEnabled:
+ event.Skip()
+
def OnPanelLeftDown(self, event):
focused = self.FindFocus()
if isinstance(focused, TextCtrlAutoComplete.TextCtrlAutoComplete):
- focused._showDropDown(False)
+ focused.DismissListBox()
event.Skip()
def RefreshFileMenu(self):
@@ -533,6 +546,7 @@
self.FileMenu.Enable(wx.ID_PRINT, False)
self.FileMenu.Enable(wx.ID_PAGE_SETUP, True)
self.FileMenu.Enable(wx.ID_SAVE, True)
+ self.FileMenu.Enable(wx.ID_SAVEAS, True)
self.FileMenu.Enable(wx.ID_PROPERTIES, True)
self.FileMenu.Enable(wx.ID_CLOSE_ALL, True)
else:
@@ -541,6 +555,7 @@
self.FileMenu.Enable(wx.ID_PREVIEW, False)
self.FileMenu.Enable(wx.ID_PRINT, False)
self.FileMenu.Enable(wx.ID_SAVE, False)
+ self.FileMenu.Enable(wx.ID_SAVEAS, False)
self.FileMenu.Enable(wx.ID_PROPERTIES, False)
self.FileMenu.Enable(wx.ID_CLOSE_ALL, False)
@@ -1201,7 +1216,7 @@
id = wx.NewId()
if isinstance(element_infos["type"], types.ListType):
combobox = wx.ComboBox(id=id, name=element_infos["name"], parent=parent,
- pos=wx.Point(0, 0), size=wx.Size(150, 28), style=wx.CB_READONLY)
+ pos=wx.Point(0, 0), size=wx.Size(300, 28), style=wx.CB_READONLY)
boxsizer.AddWindow(combobox, 0, border=0, flag=0)
if element_infos["use"] == "optional":
combobox.Append("")
@@ -1234,7 +1249,7 @@
if "max" in element_infos["type"]:
scmax = element_infos["type"]["max"]
spinctrl = wx.SpinCtrl(id=id, name=element_infos["name"], parent=parent,
- pos=wx.Point(0, 0), size=wx.Size(150, 25), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT)
+ pos=wx.Point(0, 0), size=wx.Size(300, 25), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT)
spinctrl.SetRange(scmin,scmax)
boxsizer.AddWindow(spinctrl, 0, border=0, flag=0)
spinctrl.SetValue(element_infos["value"])
@@ -1253,7 +1268,7 @@
scmin = -(2**31)
scmax = 2**31-1
spinctrl = wx.SpinCtrl(id=id, name=element_infos["name"], parent=parent,
- pos=wx.Point(0, 0), size=wx.Size(150, 25), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT)
+ pos=wx.Point(0, 0), size=wx.Size(300, 25), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT)
spinctrl.SetRange(scmin, scmax)
boxsizer.AddWindow(spinctrl, 0, border=0, flag=0)
spinctrl.SetValue(element_infos["value"])
@@ -1263,10 +1278,11 @@
textctrl = TextCtrlAutoComplete.TextCtrlAutoComplete(id=id,
name=element_infos["name"],
parent=parent,
+ appframe=self,
choices=choices,
element_path=element_path,
pos=wx.Point(0, 0),
- size=wx.Size(150, 25),
+ size=wx.Size(300, 25),
style=0)
boxsizer.AddWindow(textctrl, 0, border=0, flag=0)
@@ -1284,6 +1300,9 @@
self.DebugVariablePanel.SetDataProducer(None)
def OnNewProjectMenu(self, event):
+ if self.PluginRoot is not None and not self.CheckSaveBeforeClosing():
+ return
+
if not self.Config.HasEntry("lastopenedfolder"):
defaultpath = os.path.expanduser("~")
else:
@@ -1309,6 +1328,9 @@
self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU)
def OnOpenProjectMenu(self, event):
+ if self.PluginRoot is not None and not self.CheckSaveBeforeClosing():
+ return
+
if not self.Config.HasEntry("lastopenedfolder"):
defaultpath = os.path.expanduser("~")
else:
@@ -1337,21 +1359,12 @@
dialog.Destroy()
def OnCloseProjectMenu(self, event):
- if self.PluginRoot is not None:
- if self.PluginRoot.ProjectTestModified():
- dialog = wx.MessageDialog(self,
- _("Save changes ?"),
- _("Close Application"),
- wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
- answer = dialog.ShowModal()
- dialog.Destroy()
- if answer == wx.ID_YES:
- self.PluginRoot.SaveProject()
- elif answer == wx.ID_CANCEL:
- return
- self.ResetView()
- self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU)
- self.RefreshAll()
+ if self.PluginRoot is not None and not self.CheckSaveBeforeClosing():
+ return
+
+ self.ResetView()
+ self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU)
+ self.RefreshAll()
def OnSaveProjectMenu(self, event):
if self.PluginRoot is not None:
@@ -1359,6 +1372,13 @@
self.RefreshAll()
self.RefreshTitle()
+ def OnSaveProjectAsMenu(self, event):
+ if self.PluginRoot is not None:
+ self.PluginRoot.SaveProjectAs()
+ self.RefreshAll()
+ self.RefreshTitle()
+ event.Skip()
+
def OnPropertiesMenu(self, event):
self.ShowProperties()
@@ -1391,24 +1411,26 @@
return DeleteButtonFunction
def AddPlugin(self, PluginType, plugin):
- 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)
- self.RefreshPluginTree()
- self.PluginRoot.RefreshPluginsBlockLists()
- dialog.Destroy()
+ if self.PluginRoot.CheckProjectPathPerm():
+ 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)
+ self.RefreshPluginTree()
+ self.PluginRoot.RefreshPluginsBlockLists()
+ dialog.Destroy()
def DeletePlugin(self, plugin):
- 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()
- del plugin
- self.PluginRoot.RefreshPluginsBlockLists()
- self.RefreshPluginTree()
- dialog.Destroy()
-
+ if self.PluginRoot.CheckProjectPathPerm():
+ 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()
+ del plugin
+ self.PluginRoot.RefreshPluginsBlockLists()
+ self.RefreshPluginTree()
+ dialog.Destroy()
+
#-------------------------------------------------------------------------------
# Exception Handler
#-------------------------------------------------------------------------------
@@ -1436,10 +1458,8 @@
An unhandled exception (bug) occured. Bug report saved at :
(%s)
-Please contact LOLITech at:
-+33 (0)3 29 57 60 42
-or please be kind enough to send this file to:
-bugs_beremiz@lolitech.fr
+Please be kind enough to send this file to:
+edouard.tisserant@gmail.com
You should now restart Beremiz.
--- a/TextCtrlAutoComplete.py Tue Oct 27 16:32:54 2009 +0100
+++ b/TextCtrlAutoComplete.py Mon Nov 02 15:38:49 2009 +0100
@@ -1,207 +1,250 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-#This file is part of Beremiz, a Integrated Development Environment for
-#programming IEC 61131-3 automates supporting plcopen standard and CanFestival.
-#
-#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
-#
-#See COPYING file for copyrights details.
-#
-#This library is free software; you can redistribute it and/or
-#modify it under the terms of the GNU General Public
-#License as published by the Free Software Foundation; either
-#version 2.1 of the License, or (at your option) any later version.
-#
-#This library is distributed in the hope that it will be useful,
-#but WITHOUT ANY WARRANTY; without even the implied warranty of
-#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-#General Public License for more details.
-#
-#You should have received a copy of the GNU General Public
-#License along with this library; if not, write to the Free Software
-#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-import wx
-import cPickle
-
-MAX_ITEM_COUNT = 10
-MAX_ITEM_SHOWN = 6
-ITEM_HEIGHT = 25
-
-class TextCtrlAutoComplete(wx.TextCtrl):
-
- def __init__ (self, parent, choices=None, dropDownClick=True,
- element_path=None, **therest):
- """
- Constructor works just like wx.TextCtrl except you can pass in a
- list of choices. You can also change the choice list at any time
- by calling setChoices.
- """
-
- therest['style'] = wx.TE_PROCESS_ENTER | therest.get('style', 0)
-
- wx.TextCtrl.__init__(self, parent, **therest)
-
- #Some variables
- self._dropDownClick = dropDownClick
- self._lastinsertionpoint = None
-
- self._screenheight = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)
- self.element_path = element_path
-
- #widgets
- self.dropdown = wx.PopupWindow(self)
-
- #Control the style
- flags = wx.LB_HSCROLL | wx.LB_SINGLE | wx.LB_SORT
-
- #Create the list and bind the events
- self.dropdownlistbox = wx.ListBox(self.dropdown, style=flags,
- pos=wx.Point(0, 0))
-
- self.SetChoices(choices)
-
- #gp = self
- #while ( gp != None ) :
- # gp.Bind ( wx.EVT_MOVE , self.onControlChanged, gp )
- # gp.Bind ( wx.EVT_SIZE , self.onControlChanged, gp )
- # gp = gp.GetParent()
-
- self.Bind(wx.EVT_KILL_FOCUS, self.onControlChanged, self)
- self.Bind(wx.EVT_TEXT_ENTER, self.onControlChanged, self)
- self.Bind(wx.EVT_TEXT, self.onEnteredText, self)
- self.Bind(wx.EVT_KEY_DOWN, self.onKeyDown, self)
-
- #If need drop down on left click
- if dropDownClick:
- self.Bind(wx.EVT_LEFT_DOWN , self.onClickToggleDown, self)
- self.Bind(wx.EVT_LEFT_UP , self.onClickToggleUp, self)
-
- self.dropdownlistbox.Bind(wx.EVT_LISTBOX, self.onListItemSelected)
- self.dropdownlistbox.Bind(wx.EVT_LISTBOX_DCLICK, self.onListItemSelected)
-
- def ChangeValue(self, value):
- wx.TextCtrl.ChangeValue(self, value)
- self._refreshListBoxChoices()
-
- def onEnteredText(self, event):
- wx.CallAfter(self._refreshListBoxChoices)
- event.Skip()
-
- def onKeyDown(self, event) :
- """ Do some work when the user press on the keys:
- up and down: move the cursor
- """
- visible = self.dropdown.IsShown()
- keycode = event.GetKeyCode()
- if keycode in [wx.WXK_DOWN, wx.WXK_UP]:
- if not visible:
- self._showDropDown()
- elif keycode == wx.WXK_DOWN:
- self._moveSelection(1)
- else:
- self._moveSelection(-1)
- elif keycode in [wx.WXK_LEFT, wx.WXK_RIGHT, wx.WXK_RETURN] and visible:
- if self.dropdownlistbox.GetSelection() != wx.NOT_FOUND:
- self._setValueFromSelected()
- else:
- self._showDropDown(False)
- event.Skip()
- elif event.GetKeyCode() == wx.WXK_ESCAPE:
- self._showDropDown(False)
- else:
- event.Skip()
-
- def onListItemSelected(self, event):
- self._setValueFromSelected()
- event.Skip()
-
- def onClickToggleDown(self, event):
- self._lastinsertionpoint = self.GetInsertionPoint()
- event.Skip()
-
- def onClickToggleUp(self, event):
- if self.GetInsertionPoint() == self._lastinsertionpoint:
- self._showDropDown(not self.dropdown.IsShown())
- self._lastinsertionpoint = None
- event.Skip()
-
- def onControlChanged(self, event):
- res = self.GetValue()
- config = wx.ConfigBase.Get()
- listentries = cPickle.loads(str(config.Read(self.element_path, cPickle.dumps([]))))
- if res and res not in listentries:
- listentries = (listentries + [res])[-MAX_ITEM_COUNT:]
- config.Write(self.element_path, cPickle.dumps(listentries))
- config.Flush()
- self.SetChoices(listentries)
- self._showDropDown(False)
- event.Skip()
-
- def SetChoices(self, choices):
- self._choices = choices
- self._refreshListBoxChoices()
-
- def GetChoices(self):
- return self._choices
-
-#-------------------------------------------------------------------------------
-# Internal methods
-#-------------------------------------------------------------------------------
-
- def _refreshListBoxChoices(self):
- text = self.GetValue()
-
- self.dropdownlistbox.Clear()
- for choice in self._choices:
- if choice.startswith(text):
- self.dropdownlistbox.Append(choice)
-
- itemcount = min(len(self.dropdownlistbox.GetStrings()), MAX_ITEM_SHOWN)
- self.popupsize = wx.Size(self.GetSize()[0], ITEM_HEIGHT * itemcount + 4)
- self.dropdownlistbox.SetSize(self.popupsize)
- self.dropdown.SetClientSize(self.popupsize)
-
- def _moveSelection(self, direction):
- selected = self.dropdownlistbox.GetSelection()
- if selected == wx.NOT_FOUND:
- if direction >= 0:
- selected = 0
- else:
- selected = self.dropdownlistbox.GetCount() - 1
- else:
- selected = (selected + direction) % (self.dropdownlistbox.GetCount() + 1)
- if selected == self.dropdownlistbox.GetCount():
- selected = wx.NOT_FOUND
- self.dropdownlistbox.SetSelection(selected)
-
- def _setValueFromSelected(self):
- """
- Sets the wx.TextCtrl value from the selected wx.ListCtrl item.
- Will do nothing if no item is selected in the wx.ListCtrl.
- """
- selected = self.dropdownlistbox.GetStringSelection()
- if selected:
- self.SetValue(selected)
- self._showDropDown(False)
-
-
- def _showDropDown(self, show=True) :
- """
- Either display the drop down list (show = True) or hide it (show = False).
- """
- if show :
- size = self.dropdown.GetSize()
- width, height = self.GetSizeTuple()
- x, y = self.ClientToScreenXY(0, height)
- if size.GetWidth() != width :
- size.SetWidth(width)
- self.dropdown.SetSize(size)
- self.dropdownlistbox.SetSize(self.dropdown.GetClientSize())
- if (y + size.GetHeight()) < self._screenheight :
- self.dropdown.SetPosition(wx.Point(x, y))
- else:
- self.dropdown.SetPosition(wx.Point(x, y - height - size.GetHeight()))
- self.dropdown.Show(show)
-
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#This file is part of Beremiz, a Integrated Development Environment for
+#programming IEC 61131-3 automates supporting plcopen standard and CanFestival.
+#
+#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
+#
+#See COPYING file for copyrights details.
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+#General Public License for more details.
+#
+#You should have received a copy of the GNU General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import wx
+import cPickle
+
+MAX_ITEM_COUNT = 10
+MAX_ITEM_SHOWN = 6
+if wx.Platform == '__WXMSW__':
+ ITEM_INTERVAL_HEIGHT = 3
+else:
+ ITEM_INTERVAL_HEIGHT = 6
+
+if wx.Platform == '__WXMSW__':
+ popupclass = wx.PopupTransientWindow
+else:
+ popupclass = wx.PopupWindow
+
+class PopupWithListbox(popupclass):
+
+ def __init__(self, parent, choices=[]):
+ popupclass.__init__(self, parent, wx.SIMPLE_BORDER)
+
+ self.ListBox = wx.ListBox(self, -1, style=wx.LB_HSCROLL|wx.LB_SINGLE|wx.LB_SORT)
+ if not wx.Platform == '__WXMSW__':
+ self.ListBox.Bind(wx.EVT_LISTBOX, self.OnListBoxClick)
+ self.ListBox.Bind(wx.EVT_LISTBOX_DCLICK, self.OnListBoxClick)
+
+ self.SetChoices(choices)
+
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+
+ def SetChoices(self, choices):
+ max_text_width = 0
+ max_text_height = 0
+
+ self.ListBox.Clear()
+ for choice in choices:
+ self.ListBox.Append(choice)
+ w, h = self.ListBox.GetTextExtent(choice)
+ max_text_width = max(max_text_width, w)
+ max_text_height = max(max_text_height, h)
+
+ itemcount = min(len(choices), MAX_ITEM_SHOWN)
+ width = self.Parent.GetSize()[0]
+ height = max_text_height * itemcount + ITEM_INTERVAL_HEIGHT * (itemcount + 1)
+ if max_text_width + 10 > width:
+ height += 15
+ size = wx.Size(width, height)
+ self.ListBox.SetSize(size)
+ self.SetClientSize(size)
+
+ def MoveSelection(self, direction):
+ selected = self.ListBox.GetSelection()
+ if selected == wx.NOT_FOUND:
+ if direction >= 0:
+ selected = 0
+ else:
+ selected = self.ListBox.GetCount() - 1
+ else:
+ selected = (selected + direction) % (self.ListBox.GetCount() + 1)
+ if selected == self.ListBox.GetCount():
+ selected = wx.NOT_FOUND
+ self.ListBox.SetSelection(selected)
+
+ def GetSelection(self):
+ return self.ListBox.GetStringSelection()
+
+ def ProcessLeftDown(self, event):
+ selected = self.ListBox.HitTest(wx.Point(event.m_x, event.m_y))
+ if selected != wx.NOT_FOUND:
+ wx.CallAfter(self.Parent.SetValueFromSelected, self.ListBox.GetString(selected))
+ return False
+
+ def OnListBoxClick(self, event):
+ selected = event.GetSelection()
+ if selected != wx.NOT_FOUND:
+ wx.CallAfter(self.Parent.SetValueFromSelected, self.ListBox.GetString(selected))
+ event.Skip()
+
+ def OnKeyDown(self, event):
+ self.Parent.ProcessEvent(event)
+
+ def OnDismiss(self):
+ self.Parent.listbox = None
+ wx.CallAfter(self.Parent.DismissListBox)
+
+class TextCtrlAutoComplete(wx.TextCtrl):
+
+ def __init__ (self, parent, appframe, choices=None, dropDownClick=True,
+ element_path=None, **therest):
+ """
+ Constructor works just like wx.TextCtrl except you can pass in a
+ list of choices. You can also change the choice list at any time
+ by calling setChoices.
+ """
+
+ therest['style'] = wx.TE_PROCESS_ENTER | therest.get('style', 0)
+
+ wx.TextCtrl.__init__(self, parent, **therest)
+ self.AppFrame = appframe
+
+ #Some variables
+ self._dropDownClick = dropDownClick
+ self._lastinsertionpoint = None
+
+ self._screenheight = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)
+ self.element_path = element_path
+
+ self.listbox = None
+
+ self.SetChoices(choices)
+
+ #gp = self
+ #while ( gp != None ) :
+ # gp.Bind ( wx.EVT_MOVE , self.onControlChanged, gp )
+ # gp.Bind ( wx.EVT_SIZE , self.onControlChanged, gp )
+ # gp = gp.GetParent()
+
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnControlChanged)
+ self.Bind(wx.EVT_TEXT_ENTER, self.OnControlChanged)
+ self.Bind(wx.EVT_TEXT, self.OnEnteredText)
+ self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+
+ #If need drop down on left click
+ if dropDownClick:
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnClickToggleDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnClickToggleUp)
+
+ def __del__(self):
+ self.AppFrame = None
+
+ def ChangeValue(self, value):
+ wx.TextCtrl.ChangeValue(self, value)
+ self.RefreshListBoxChoices()
+
+ def OnEnteredText(self, event):
+ wx.CallAfter(self.RefreshListBoxChoices)
+ event.Skip()
+
+ def OnKeyDown(self, event):
+ """ Do some work when the user press on the keys:
+ up and down: move the cursor
+ """
+ keycode = event.GetKeyCode()
+ if keycode in [wx.WXK_DOWN, wx.WXK_UP]:
+ self.PopupListBox()
+ if keycode == wx.WXK_DOWN:
+ self.listbox.MoveSelection(1)
+ else:
+ self.listbox.MoveSelection(-1)
+ elif keycode in [wx.WXK_LEFT, wx.WXK_RIGHT, wx.WXK_RETURN] and self.listbox is not None:
+ self.SetValueFromSelected(self.listbox.GetSelection())
+ elif event.GetKeyCode() == wx.WXK_ESCAPE:
+ self.DismissListBox()
+ else:
+ event.Skip()
+
+ def OnClickToggleDown(self, event):
+ self._lastinsertionpoint = self.GetInsertionPoint()
+ event.Skip()
+
+ def OnClickToggleUp(self, event):
+ if self.GetInsertionPoint() == self._lastinsertionpoint:
+ wx.CallAfter(self.PopupListBox)
+ self._lastinsertionpoint = None
+ event.Skip()
+
+ def OnControlChanged(self, event):
+ res = self.GetValue()
+ config = wx.ConfigBase.Get()
+ listentries = cPickle.loads(str(config.Read(self.element_path, cPickle.dumps([]))))
+ if res and res not in listentries:
+ listentries = (listentries + [res])[-MAX_ITEM_COUNT:]
+ config.Write(self.element_path, cPickle.dumps(listentries))
+ config.Flush()
+ self.SetChoices(listentries)
+ self.DismissListBox()
+ event.Skip()
+
+ def SetChoices(self, choices):
+ self._choices = choices
+ self.RefreshListBoxChoices()
+
+ def GetChoices(self):
+ return self._choices
+
+ def SetValueFromSelected(self, selected):
+ """
+ Sets the wx.TextCtrl value from the selected wx.ListCtrl item.
+ Will do nothing if no item is selected in the wx.ListCtrl.
+ """
+ if selected != "":
+ self.SetValue(selected)
+ self.DismissListBox()
+
+ def RefreshListBoxChoices(self):
+ if self.listbox is not None:
+ text = self.GetValue()
+ choices = [choice for choice in self._choices if choice.startswith(text)]
+ self.listbox.SetChoices(choices)
+
+ def PopupListBox(self):
+ if self.listbox is None:
+ self.listbox = PopupWithListbox(self)
+
+ # Show the popup right below or above the button
+ # depending on available screen space...
+ pos = self.ClientToScreen((0, 0))
+ sz = self.GetSize()
+ self.listbox.Position(pos, (0, sz[1]))
+
+ self.RefreshListBoxChoices()
+
+ if wx.Platform == '__WXMSW__':
+ self.listbox.Popup()
+ else:
+ self.listbox.Show()
+ self.AppFrame.EnableScrolling(False)
+
+ def DismissListBox(self):
+ if self.listbox is not None:
+ if wx.Platform == '__WXMSW__':
+ self.listbox.Dismiss()
+ else:
+ self.listbox.Destroy()
+ self.listbox = None
+ self.AppFrame.EnableScrolling(True)
+
--- a/beremiz_postinst.py Tue Oct 27 16:32:54 2009 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-# La première ligne doit commencer par #! et contenir python.
-# Elle sera adaptée au système de destination automatiquement
-
-""" This is a part of Beremiz project.
-
- Post installation script for win32 system
-
- This script creat a shortcut for Beremiz.py in the desktop and the
- start menu, and remove them at the uninstallation
-
-"""
-
-import os
-import sys
-
-# Ce script sera aussi lancé lors de la désinstallation.
-# Pour n'exécuter du code que lors de l'installation :
-if sys.argv[1] == '-install':
- # On récupère le dossier où mes fichiers seront installés (dossier où python est aussi installé sous windows)
- python_path = sys.prefix
- # On récupère le chemin de pythonw.exe (l'exécutable python qui n'affiche pas de console).
- # Si vous voulez une console, remplacez pythonw.exe par python.exe
- pyw_path = os.path.abspath(os.path.join(python_path, 'pythonw.exe'))
- # On récupère le dossier coincoin
- Beremiz_dir = os.path.abspath(os.path.join(python_path, 'LOLITech', 'Beremiz'))
-
- # On récupère les chemins de coincoin.py, et de coincoin.ico
- # (Ben oui, l'icone est au format ico, oubliez le svg, ici on en est encore à la préhistoire.
- # Heureusement que the GIMP sait faire la conversion !)
- ico_path = os.path.join(Beremiz_dir, 'Beremiz.ico')
- script_path = os.path.join(Beremiz_dir, 'Beremiz.py')
-
- # Création des raccourcis
- # Pour chaque raccourci, on essaye de le faire pour tous les utilisateurs (Windows NT/2000/XP),
- # sinon on le fait pour l'utilisateur courant (Windows 95/98/ME)
-
- # Raccourcis du bureau
- # On essaye de trouver un bureau
- try:
- desktop_path = get_special_folder_path("CSIDL_COMMON_DESKTOPDIRECTORY")
- except OSError:
- desktop_path = get_special_folder_path("CSIDL_DESKTOPDIRECTORY")
-
- # On créé le raccourcis
- create_shortcut(pyw_path, # programme à lancer
- "Can Node Editor", # Description
- os.path.join(desktop_path, 'Beremiz.lnk'), # fichier du raccourcis (gardez le .lnk)
- script_path, # Argument (script python)
- Beremiz_dir, # Dossier courant
- ico_path # Fichier de l'icone
- )
- # On va cafter au programme de désinstallation qu'on a fait un fichier, pour qu'il soit supprimé
- # lors de la désinstallation
- file_created(os.path.join(desktop_path, 'Beremiz.lnk'))
-
- # Raccourcis dans le menu démarrer (idem qu'avant)
- try:
- start_path = get_special_folder_path("CSIDL_COMMON_PROGRAMS")
- except OSError:
- start_path = get_special_folder_path("CSIDL_PROGRAMS")
-
-
-
- # Création du dossier dans le menu programme
- programs_path = os.path.join(start_path, "Beremiz project")
- try :
- os.mkdir(programs_path)
-
- except OSError:
-
- pass
- directory_created(programs_path)
-
- create_shortcut(pyw_path, # Cible
- "Can Node Editor", #Description
- os.path.join(programs_path, 'Beremiz.lnk'), # Fichier
- script_path, # Argument
- Beremiz_dir, # Dossier de travail
- ico_path # Icone
- )
- file_created(os.path.join(programs_path, 'Beremiz.lnk'))
-
- # End (youpi-message)
- # Ce message sera affiché (très) furtivement dans l'installateur.
- # Vous pouvez vous en servir comme moyen de communication secret, c'est très in.
- sys.stdout.write("Shortcuts created.")
- # Fin du bidule
- sys.exit()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/Beremiz.directory Mon Nov 02 15:38:49 2009 +0100
@@ -0,0 +1,4 @@
+[Desktop Entry]
+Type=Directory
+Name=Beremiz
+Icon=/usr/share/beremiz/images/brz.png
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/Beremiz_demos.directory Mon Nov 02 15:38:49 2009 +0100
@@ -0,0 +1,4 @@
+[Desktop Entry]
+Type=Directory
+Name=Demos
+Icon=
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/Beremiz_docs.directory Mon Nov 02 15:38:49 2009 +0100
@@ -0,0 +1,4 @@
+[Desktop Entry]
+Type=Directory
+Name=Doc
+Icon=
--- a/debian/README.Debian Tue Oct 27 16:32:54 2009 +0100
+++ b/debian/README.Debian Mon Nov 02 15:38:49 2009 +0100
@@ -3,4 +3,4 @@
<possible notes regarding this package - if none, delete this file>
- -- lolitech <gregory.trelat@lolitech.fr> Thu, 29 Nov 2007 14:55:13 +0100
+ -- edouard <edouard.tisserant@gmail.com> Thu, 29 Nov 2007 14:55:13 +0100
--- a/debian/beremiz.desktop Tue Oct 27 16:32:54 2009 +0100
+++ b/debian/beremiz.desktop Mon Nov 02 15:38:49 2009 +0100
@@ -8,6 +8,6 @@
Terminal=false
MultipleArgs=false
Type=Application
-Categories=Application;Development;
+Categories=Beremiz;
StartupNotify=true
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/beremiz.menu Mon Nov 02 15:38:49 2009 +0100
@@ -0,0 +1,40 @@
+<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
+ "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
+<Menu>
+ <Name>Applications</Name>
+ <Directory>Applications.directory</Directory>
+
+ <!-- Read standard .directory and .desktop file locations -->
+ <DefaultAppDirs/>
+ <DefaultDirectoryDirs/>
+ <Menu>
+ <Name>Development</Name>
+ <Directory>Development.directory</Directory>
+
+ <!-- Beremiz submenu -->
+ <Menu>
+ <Name>Beremiz</Name>
+ <Directory>Beremiz.directory</Directory>
+ <Include>
+ <Category>Beremiz</Category>
+ </Include>
+ <Menu>
+ <Name>Demos</Name>
+ <Directory>Beremiz_demos.directory</Directory>
+ <Include>
+ <Category>Beremiz_demo</Category>
+ </Include>
+ </Menu> <!-- End Beremiz demo -->
+ <Menu>
+ <Name>Doc</Name>
+ <Directory>Beremiz_docs.directory</Directory>
+ <Include>
+ <Category>Beremiz_doc</Category>
+ </Include>
+ </Menu> <!-- End Beremiz doc -->
+ </Menu> <!-- End Beremiz -->
+
+ </Menu> <!-- End Development -->
+ <!-- possibly more submenus -->
+
+</Menu> <!-- End Applications -->
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/beremiz_doc.desktop Mon Nov 02 15:38:49 2009 +0100
@@ -0,0 +1,12 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Manual
+Comment=Open Source framework for automation
+Comment[fr]=Environnement de développement Open Source pour l'automatisme
+Exec=/usr/bin/xpdf /usr/share/beremiz/doc/manual_beremiz.pdf
+Icon=
+Terminal=false
+MultipleArgs=false
+Type=Application
+Categories=Beremiz_doc;
+StartupNotify=true
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/beremiz_svgui.desktop Mon Nov 02 15:38:49 2009 +0100
@@ -0,0 +1,13 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Beremiz Demo (svgui)
+Comment=Open Source framework for automation
+Comment[fr]=Environnement de développement Open Source pour l'automatisme
+Exec=/usr/bin/beremiz /usr/share/beremiz/tests/svgui
+Icon=/usr/share/beremiz/images/brz.png
+Terminal=false
+MultipleArgs=false
+Type=Application
+Categories=Beremiz_demo;
+StartupNotify=true
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/beremiz_wxglade.desktop Mon Nov 02 15:38:49 2009 +0100
@@ -0,0 +1,13 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Beremiz Demo (wxGlade)
+Comment=Open Source framework for automation
+Comment[fr]=Environnement de développement Open Source pour l'automatisme
+Exec=/usr/bin/beremiz /usr/share/beremiz/tests/wxGlade
+Icon=/usr/share/beremiz/images/brz.png
+Terminal=false
+MultipleArgs=false
+Type=Application
+Categories=Beremiz_demo;
+StartupNotify=true
+
--- a/debian/changelog Tue Oct 27 16:32:54 2009 +0100
+++ b/debian/changelog Mon Nov 02 15:38:49 2009 +0100
@@ -2,5 +2,5 @@
* Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP>
- -- lolitech <gregory.trelat@lolitech.fr> Thu, 29 Nov 2007 14:55:13 +0100
+ -- edouard <edouard.tisserant@gmail.com> Thu, 29 Nov 2007 14:55:13 +0100
--- a/debian/control Tue Oct 27 16:32:54 2009 +0100
+++ b/debian/control Mon Nov 02 15:38:49 2009 +0100
@@ -1,13 +1,13 @@
Source: beremiz
Section: devel
Priority: standard
-Maintainer: lolitech <gregory.trelat@lolitech.fr>
+Maintainer: edouard <edouard.tisserant@gmail.com>
Build-Depends: debhelper (>= 5)
Standards-Version: 3.7.2
Package: beremiz
Architecture: any
-Depends: build-essential, python-wxgtk2.8, python-ctypes, python-wxglade, xpdf, canfestival-devel, canfestival-objdictedit, matiec, docutils, pyro, xmlclass, plcopeneditor
+Depends: build-essential, python-wxgtk2.8, python-ctypes, python-numpy, python-twisted, python-nevow, python-simplejson, python-wxglade, xpdf, canfestival-devel, canfestival-objdictedit, matiec, docutils, pyro, xmlclass, plcopeneditor
Description: Beremiz is an Open Source framework for automation
With Beremiz, you can :
- Automate everything.
--- a/debian/rules Tue Oct 27 16:32:54 2009 +0100
+++ b/debian/rules Mon Nov 02 15:38:49 2009 +0100
@@ -1,17 +1,9 @@
#!/usr/bin/make -f
# -*- makefile -*-
-# Sample debian/rules that uses debhelper.
-# This file was originally written by Joey Hess and Craig Small.
-# As a special exception, when this file is copied by dh-make into a
-# dh-make output file, you may use that output file without restriction.
-# This special exception was added by Craig Small in version 0.37 of dh-make.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
-
-
-
CFLAGS = -Wall -g
ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
@@ -23,8 +15,6 @@
configure: configure-stamp
configure-stamp:
dh_testdir
- # Add here commands to configure the package.
-
touch configure-stamp
@@ -32,21 +22,12 @@
build-stamp: configure-stamp
dh_testdir
-
- # Add here commands to compile the package.
- #$(MAKE)
- #docbook-to-man debian/beremiz.sgml > beremiz.1
-
touch $@
clean:
dh_testdir
dh_testroot
rm -f build-stamp configure-stamp
-
- # Add here commands to clean up after the build process.
- #-$(MAKE) clean
-
dh_clean
install: build
@@ -55,35 +36,49 @@
dh_clean -k
dh_installdirs
- # Add here commands to install the package into debian/beremiz.
+ # Copy source files
mkdir -p $(CURDIR)/debian/beremiz/usr/share/beremiz
- mkdir -p $(CURDIR)/debian/beremiz/usr/share/applications
-
cp -a images $(CURDIR)/debian/beremiz/usr/share/beremiz
cp -a plugins $(CURDIR)/debian/beremiz/usr/share/beremiz
cp -a runtime $(CURDIR)/debian/beremiz/usr/share/beremiz
cp -a tests $(CURDIR)/debian/beremiz/usr/share/beremiz
cp -a connectors $(CURDIR)/debian/beremiz/usr/share/beremiz
cp -a targets $(CURDIR)/debian/beremiz/usr/share/beremiz
- cp *.xml $(CURDIR)/debian/beremiz/usr/share/beremiz
+ cp -a doc $(CURDIR)/debian/beremiz/usr/share/beremiz
+ cp -a locale $(CURDIR)/debian/beremiz/usr/share/beremiz
+ cp *.js $(CURDIR)/debian/beremiz/usr/share/beremiz
cp *.py $(CURDIR)/debian/beremiz/usr/share/beremiz
- cp debian/beremiz.desktop $(CURDIR)/debian/beremiz/usr/share/applications/beremiz.desktop
-
+ # Copy desktop directory file
+ mkdir -p $(CURDIR)/debian/beremiz/usr/share/desktop-directories
+ cp debian/Beremiz.directory $(CURDIR)/debian/beremiz/usr/share/desktop-directories
+ cp debian/Beremiz_demos.directory $(CURDIR)/debian/beremiz/usr/share/desktop-directories
+ cp debian/Beremiz_docs.directory $(CURDIR)/debian/beremiz/usr/share/desktop-directories
+
+ # Copy desktop menu file
+ mkdir -p $(CURDIR)/debian/beremiz/etc/xdg/menus/applications-merged
+ cp debian/beremiz.menu $(CURDIR)/debian/beremiz/etc/xdg/menus/applications-merged
+
+ # Copy desktop entry files
+ mkdir -p $(CURDIR)/debian/beremiz/usr/share/applications
+ cp debian/beremiz.desktop $(CURDIR)/debian/beremiz/usr/share/applications/
+ cp debian/beremiz_svgui.desktop $(CURDIR)/debian/beremiz/usr/share/applications/
+ cp debian/beremiz_wxglade.desktop $(CURDIR)/debian/beremiz/usr/share/applications/
+ cp debian/beremiz_doc.desktop $(CURDIR)/debian/beremiz/usr/share/applications/
+
rm -rf `find .|grep CVS`
rm -rf `find .|grep .cvsignore`
chmod -R a+r $(CURDIR)/debian/beremiz
# Build architecture-independent files here.
binary-indep: build install
-# We have nothing to do by default.
# Build architecture-dependent files here.
binary-arch: build install
dh_testdir
dh_testroot
- dh_installchangelogs
- dh_installdocs
+# dh_installchangelogs
+# dh_installdocs
dh_installexamples
# dh_install
# dh_installmenu
--- a/doc/about.html Tue Oct 27 16:32:54 2009 +0100
+++ b/doc/about.html Mon Nov 02 15:38:49 2009 +0100
@@ -17,15 +17,6 @@
<a href="http://www.fe.up.pt/si/web_page.inicial">http://www.fe.up.pt/si/web_page.inicial</a>
</TD>
</TR>
- <TR>
- <TD align="right" valign="top">
- Supported by :
- </TD>
- <TD align="left" valign="top">
- LOLITech<BR>
- <a href="http://www.lolitech.fr">http://www.lolitech.fr</a>
- </TD>
- </TR>
</TABLE>
</CENTER>
</BODY>
--- a/i18n/Beremiz_fr_FR.po Tue Oct 27 16:32:54 2009 +0100
+++ b/i18n/Beremiz_fr_FR.po Mon Nov 02 15:38:49 2009 +0100
@@ -7,25 +7,23 @@
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-10-09 16:27+0200\n"
-"PO-Revision-Date: 2009-10-09 17:48+0100\n"
+"POT-Creation-Date: 2009-11-02 10:40+0100\n"
+"PO-Revision-Date: 2009-11-02 10:52+0100\n"
"Last-Translator: \n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: ../Beremiz.py:1432
+#: ../Beremiz.py:1457
#, 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"
+"Please be kind enough to send this file to:\n"
+"edouard.tisserant@gmail.com\n"
"\n"
"You should now restart Beremiz.\n"
"\n"
@@ -35,20 +33,18 @@
"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"
+"Envoyez ce fichier à l'adresse :\n"
+"edouard.tisserant@gmail.com\n"
"\n"
"Vous devriez redémarrer Beremiz.\n"
"\n"
"Origine :\n"
-#: ../plugger.py:1370
+#: ../plugger.py:1453
msgid " generation failed !\n"
msgstr ": la construction a échouée !\n"
-#: ../Beremiz.py:1332
+#: ../Beremiz.py:1357
#, python-format
msgid "\"%s\" folder is not a valid Beremiz project\n"
msgstr "Le dossier \"%s\" ne contient pas de projet Beremiz valide\n"
@@ -57,48 +53,48 @@
msgid "&Edit"
msgstr "&Editer"
-#: ../Beremiz.py:1420
-#: ../Beremiz.py:1422
-#: ../Beremiz.py:1423
+#: ../Beremiz.py:1445
+#: ../Beremiz.py:1447
+#: ../Beremiz.py:1448
msgid ", "
msgstr ", "
-#: ../Beremiz.py:1418
+#: ../Beremiz.py:1443
msgid ". "
msgstr ". "
-#: ../plugger.py:432
+#: ../plugger.py:443
#, python-format
msgid "A child names \"%s\" already exist -> \"%s\"\n"
msgstr ""
-#: ../plugger.py:464
+#: ../plugger.py:475
#, python-format
msgid "A child with IEC channel %d already exist -> %d\n"
msgstr ""
-#: ../Beremiz.py:329
+#: ../Beremiz.py:332
msgid "About"
msgstr "A propos"
-#: ../Beremiz.py:1369
+#: ../Beremiz.py:1392
msgid "About Beremiz"
msgstr "A propos de Beremiz"
-#: ../Beremiz.py:1391
+#: ../Beremiz.py:1415
msgid "Add Plugin"
msgstr "Ajouter un plugin"
-#: ../Beremiz.py:585
-#: ../Beremiz.py:849
+#: ../Beremiz.py:603
+#: ../Beremiz.py:867
msgid "Add a sub plugin"
msgstr "Ajouter un sous plugin"
-#: ../plugger.py:1683
+#: ../plugger.py:1766
msgid "Already connected. Please disconnect\n"
msgstr "Déjà connecté. Veuillez déconnecter\n"
-#: ../Beremiz.py:1088
+#: ../Beremiz.py:1106
msgid "Append "
msgstr "Ajouter "
@@ -108,62 +104,62 @@
msgid "Bad location size : %s"
msgstr "Mauvaise taille d'adresse : %s"
-#: ../Beremiz.py:417
+#: ../Beremiz.py:426
msgid "Beremiz"
msgstr "Beremiz"
-#: ../Beremiz.py:327
+#: ../Beremiz.py:330
msgid "Beremiz\tF1"
msgstr "Beremiz\tF1"
-#: ../plugger.py:1466
+#: ../plugger.py:1549
msgid "Broken"
msgstr "Cassé"
-#: ../plugger.py:1807
+#: ../plugger.py:1890
msgid "Build"
msgstr "Compiler"
-#: ../plugger.py:1434
+#: ../plugger.py:1517
msgid "Build directory already clean\n"
msgstr "Le répertoire de compilation est déjà nettoyé\n"
-#: ../plugger.py:1808
+#: ../plugger.py:1891
msgid "Build project into build folder"
msgstr "Compiler le projet dans le répertoire ce compilation"
-#: ../plugger.py:1388
+#: ../plugger.py:1471
msgid "C Build crashed !\n"
msgstr "La compilation du C a mal fonctionné !\n"
-#: ../plugger.py:1385
+#: ../plugger.py:1468
msgid "C Build failed.\n"
msgstr "La compilation du C a échouée !\n"
-#: ../plugger.py:1374
+#: ../plugger.py:1457
msgid "C code generated successfully.\n"
msgstr "Code C généré avec succès.\n"
-#: ../targets/toolchain_gcc.py:125
+#: ../targets/toolchain_gcc.py:129
#, python-format
msgid "C compilation of %s failed.\n"
msgstr "La compilation C de %s a échouée.\n"
-#: ../plugger.py:1117
+#: ../plugger.py:1200
#, python-format
msgid "Can't find module for target %s!\n"
msgstr "Impossible de trouver le module correspondant à la cible %s !\n"
-#: ../plugger.py:1756
+#: ../plugger.py:1839
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:502
+#: ../plugger.py:513
#, python-format
msgid "Cannot create child %s of type %s "
msgstr "Impossible d'ajouter un élément \"%s\" de type \"%s\""
-#: ../plugger.py:457
+#: ../plugger.py:468
#, 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"
@@ -172,7 +168,7 @@
msgid "Cannot get PLC status - connection failed.\n"
msgstr "Impossible d'obtenir le statut de l'automate - la connexion a échoué.\n"
-#: ../plugger.py:1215
+#: ../plugger.py:1298
msgid "Cannot open/parse VARIABLES.csv!\n"
msgstr "Impossible d'ouvrir ou d'analyser le fichier VARIABLES.csv !\n"
@@ -201,8 +197,12 @@
msgid "Choose a SVG file"
msgstr "Choisissez un fichier SVG"
-#: ../Beremiz.py:1289
-#: ../Beremiz.py:1314
+#: ../plugger.py:969
+msgid "Choose a directory to save project"
+msgstr "Choisissez un dossier où enregistrer le projet"
+
+#: ../Beremiz.py:1311
+#: ../Beremiz.py:1339
msgid "Choose a project"
msgstr "Choisissez un projet"
@@ -210,48 +210,48 @@
msgid "Choose a working directory "
msgstr "Choisissez un dossier de travail"
-#: ../plugger.py:882
+#: ../plugger.py:927
msgid "Chosen folder 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:847
+#: ../plugger.py:892
msgid "Chosen folder 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 !"
-#: ../plugger.py:1811
+#: ../plugger.py:1894
msgid "Clean"
msgstr "Nettoyer"
-#: ../plugger.py:1813
+#: ../plugger.py:1896
msgid "Clean project build folder"
msgstr "Nettoyer le répertoire de compilation"
-#: ../plugger.py:1431
+#: ../plugger.py:1514
msgid "Cleaning the build directory\n"
msgstr "Répertoire de compilation en cours de nettoyage\n"
-#: ../Beremiz.py:483
-#: ../Beremiz.py:1341
+#: ../Beremiz.py:504
msgid "Close Application"
msgstr "Fermer l'application"
-#: ../Beremiz.py:299
+#: ../Beremiz.py:301
+#: ../Beremiz.py:489
msgid "Close Project"
msgstr "Fermer le projet"
-#: ../Beremiz.py:297
+#: ../Beremiz.py:299
msgid "Close Tab\tCTRL+W"
msgstr "Fermer l'onglet\tCTRL+W"
-#: ../plugger.py:1039
+#: ../plugger.py:1122
msgid "Compiling IEC Program into C code...\n"
msgstr "Compilation du program en IEC vers du code C en cours...\n"
-#: ../plugger.py:1835
+#: ../plugger.py:1918
msgid "Connect"
msgstr "Connecter"
-#: ../plugger.py:1836
+#: ../plugger.py:1919
msgid "Connect to the target PLC"
msgstr "Connecter à l'automate cible"
@@ -260,23 +260,23 @@
msgid "Connecting to URI : %s\n"
msgstr "Connection à l'URI %s en cours...\n"
-#: ../plugger.py:1702
+#: ../plugger.py:1785
msgid "Connection canceled!\n"
msgstr "La connection a été abandonnée !\n"
-#: ../plugger.py:1719
+#: ../plugger.py:1802
#, python-format
msgid "Connection failed to %s!\n"
msgstr "La connection à \"%s\" a échouée !\n"
-#: ../plugger.py:625
+#: ../plugger.py:634
#, python-format
msgid ""
"Could not add child \"%s\", type %s :\n"
"%s\n"
msgstr ""
-#: ../plugger.py:602
+#: ../plugger.py:611
#, python-format
msgid ""
"Couldn't load plugin base parameters %s :\n"
@@ -285,7 +285,7 @@
"Impossible de charger les paramètres de base du plugin %s :\n"
" %s"
-#: ../plugger.py:613
+#: ../plugger.py:622
#, python-format
msgid ""
"Couldn't load plugin parameters %s :\n"
@@ -294,11 +294,11 @@
"Impossible de charger les paramètres du plugin %s :\n"
" %s"
-#: ../plugger.py:1647
+#: ../plugger.py:1730
msgid "Couldn't start PLC debug !\n"
msgstr "Impossible d'arrêter le débogage de l'automate !\n"
-#: ../plugger.py:1677
+#: ../plugger.py:1760
msgid "Couldn't stop PLC !\n"
msgstr "Impossible d'arrêter l'automate !\n"
@@ -306,54 +306,54 @@
msgid "Create HMI"
msgstr "Créer une IHM"
-#: ../plugger.py:1821
+#: ../plugger.py:1904
msgid "Debug"
msgstr "Déboguer"
-#: ../plugger.py:1520
+#: ../plugger.py:1603
#, python-format
msgid "Debug : Unknown variable %s\n"
msgstr "Débogage : variable \"%s\" inconnue\n"
-#: ../plugger.py:1632
+#: ../plugger.py:1715
msgid "Debug Thread couldn't be killed"
msgstr "Le thread de débogage n'a pu être détruit"
-#: ../plugger.py:1616
+#: ../plugger.py:1699
#, 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"
-#: ../plugger.py:1624
+#: ../plugger.py:1707
msgid "Debugger disabled\n"
msgstr "Débogueur désactivé\n"
-#: ../Beremiz.py:840
+#: ../Beremiz.py:858
msgid "Delete this plugin"
msgstr "Supprimer ce plugin"
-#: ../plugger.py:1463
+#: ../plugger.py:1546
msgid "Dirty"
msgstr "Corrompu"
-#: ../plugger.py:1844
+#: ../plugger.py:1927
msgid "Disconnect"
msgstr "Déconnecter"
-#: ../plugger.py:1846
+#: ../plugger.py:1929
msgid "Disconnect from PLC"
msgstr "Déconnecter l'automate"
-#: ../plugger.py:1469
+#: ../plugger.py:1552
msgid "Disconnected"
msgstr "Déconnecté"
-#: ../plugins/c_ext/c_ext.py:236
-#: ../plugins/c_ext/c_ext.py:237
+#: ../plugins/c_ext/c_ext.py:250
+#: ../plugins/c_ext/c_ext.py:251
msgid "Edit C File"
msgstr "Editer le fichier C"
-#: ../plugins/canfestival/canfestival.py:217
+#: ../plugins/canfestival/canfestival.py:246
msgid "Edit CanOpen Network with NetworkEdit"
msgstr "Editer le réseau CANOpen à l'aide de NetworkEdit"
@@ -361,19 +361,19 @@
msgid "Edit a WxWidgets GUI with WXGlade"
msgstr "Editer une IHM WxWidgets à l'aide de WXGlade"
-#: ../plugins/canfestival/canfestival.py:216
+#: ../plugins/canfestival/canfestival.py:245
msgid "Edit network"
msgstr "Editer le réseau"
-#: ../plugger.py:1855
+#: ../plugger.py:1938
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:1460
+#: ../plugger.py:1543
msgid "Empty"
msgstr "Vide"
-#: ../Beremiz.py:790
+#: ../Beremiz.py:808
msgid "Enable/Disable this plugin"
msgstr "Activer/Désactiver le plugin"
@@ -389,23 +389,24 @@
msgid "Enter the IP of the interface to bind"
msgstr "Saisissez l'adresse IP de l'interface à lier"
-#: ../Beremiz.py:1446
-#: ../Beremiz.py:1456
+#: ../Beremiz.py:1469
+#: ../Beremiz.py:1479
+#: ../plugger.py:873
#: ../Beremiz_service.py:268
#: ../Beremiz_service.py:392
msgid "Error"
msgstr "Erreur"
-#: ../plugger.py:1087
+#: ../plugger.py:1170
msgid "Error : At least one configuration and one resource must be declared in PLC !\n"
msgstr "Erreur : Au moins une configuration ou une ressource doit être déclarée dans l'automate !\n"
-#: ../plugger.py:1079
+#: ../plugger.py:1162
#, 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:1021
+#: ../plugger.py:1104
#, python-format
msgid ""
"Error in ST/IL/SFC code generator :\n"
@@ -414,33 +415,33 @@
"Erreur dans le générateur de code ST/IL/SFC :\n"
"%s\n"
-#: ../plugger.py:207
+#: ../plugger.py:218
#, python-format
msgid "Error while saving \"%s\"\n"
msgstr "Erreur lors de l'enregistrement de \"%s\"\n"
-#: ../plugins/canfestival/canfestival.py:208
+#: ../plugins/canfestival/canfestival.py:237
msgid "Error: No Master generated\n"
msgstr "Erreur : Aucun maître généré\n"
-#: ../plugins/canfestival/canfestival.py:203
+#: ../plugins/canfestival/canfestival.py:232
msgid "Error: No PLC built\n"
msgstr "Erreur : Aucun automate compilé\n"
-#: ../plugger.py:1713
+#: ../plugger.py:1796
#, python-format
msgid "Exception while connecting %s!\n"
msgstr "Une exception est apparu au cours de la connexion %s !\n"
-#: ../plugger.py:1091
+#: ../plugger.py:1174
msgid "Extracting Located Variables...\n"
msgstr "Extraction des variables adressées en cours...\n"
-#: ../plugger.py:1771
+#: ../plugger.py:1854
msgid "Failed : Must build before transfer.\n"
msgstr "Echec : Le projet doit être compilé avant d'être transféré.\n"
-#: ../plugger.py:1379
+#: ../plugger.py:1462
msgid "Fatal : cannot get builder.\n"
msgstr "Erreur fatale : impossible de trouver un compilateur.\n"
@@ -448,15 +449,15 @@
msgid "Force runtime reload\n"
msgstr "Redémarrage du runtime forcé\n"
-#: ../plugger.py:1011
+#: ../plugger.py:1094
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:1329
+#: ../plugger.py:1412
msgid "Generating plugins C code\n"
msgstr "Création du code C des plugins en cours\n"
-#: ../plugger.py:1321
+#: ../plugger.py:1404
msgid "IEC-61131-3 code generation failed !\n"
msgstr "La création du code IEC-61131-3 a échouée !\n"
@@ -480,15 +481,15 @@
msgid "Invalid type \"%s\"-> %d != %d for location\"%s\""
msgstr "Type invalide \"%s\"-> %d != %d pour cette adresse \"%s\""
-#: ../plugger.py:1777
+#: ../plugger.py:1860
msgid "Latest build already matches current target. Transfering anyway...\n"
msgstr "La dernière compilation correspond à la cible actuelle...\n"
-#: ../plugger.py:1747
+#: ../plugger.py:1830
msgid "Latest build does 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:1751
+#: ../plugger.py:1834
msgid "Latest build matches 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"
@@ -500,7 +501,7 @@
msgid "Launch a live Python shell"
msgstr "Lancer une console Python"
-#: ../targets/toolchain_gcc.py:133
+#: ../targets/toolchain_gcc.py:137
msgid "Linking :\n"
msgstr "Linkage :\n"
@@ -508,11 +509,11 @@
msgid "Local"
msgstr "Local"
-#: ../Beremiz.py:376
+#: ../Beremiz.py:380
msgid "Log Console"
msgstr "Console de log"
-#: ../plugger.py:512
+#: ../plugger.py:523
#, python-format
msgid "Max count (%d) reached for this plugin of type %s "
msgstr "Nombre limite(%d) atteint pour les plugin de type %s"
@@ -525,7 +526,7 @@
msgid "New\tCTRL+N"
msgstr "Nouveau\tCTRL+N"
-#: ../plugger.py:1801
+#: ../plugger.py:1884
msgid "No PLC to transfer (did build succeed ?)\n"
msgstr "Aucun automate à transférer (la compilation a-t-elle réussi ?)\n"
@@ -562,29 +563,49 @@
msgid "Open\tCTRL+O"
msgstr "Ouvrir\tCTRL+O"
-#: ../targets/toolchain_gcc.py:101
+#: ../plugins/c_ext/c_ext.py:230
+msgid "Open CFileEditor"
+msgstr "Ouverture de CFileEditor"
+
+#: ../plugins/python/modules/svgui/svgui.py:105
+msgid "Open Inkscape"
+msgstr "Ouverture de Inkscape"
+
+#: ../plugins/canfestival/canfestival.py:208
+msgid "Open NetworkEdit"
+msgstr "Ouverture de NetworkEdit"
+
+#: ../plugins/canfestival/canfestival.py:108
+msgid "Open ObjDictEdit"
+msgstr "Ouverture de ObjdictEdit"
+
+#: ../plugins/python/modules/wxglade_hmi/wxglade_hmi.py:107
+msgid "Open wxGlade"
+msgstr "Ouverture de wxGlade"
+
+#: ../targets/toolchain_gcc.py:105
msgid "PLC :\n"
msgstr "Automate :\n"
-#: ../plugger.py:1489
-#: ../plugger.py:1733
+#: ../plugger.py:1572
+#: ../plugger.py:1816
#, python-format
msgid "PLC is %s\n"
msgstr "L'automate est dans l'état %s\n"
-#: ../Beremiz.py:302
+#: ../Beremiz.py:304
msgid "Page Setup"
msgstr "Mise en page..."
-#: ../Beremiz.py:1391
+#: ../Beremiz.py:1415
msgid "Please enter a name for plugin:"
msgstr "Saisissez un nom pour le plugin :"
-#: ../targets/toolchain_gcc.py:99
+#: ../targets/toolchain_gcc.py:103
msgid "Plugin : "
msgstr "Plugin :"
-#: ../plugger.py:1335
+#: ../plugger.py:1418
msgid "Plugins code generation failed !\n"
msgstr "La création du code des plugins a échoué !\n"
@@ -596,29 +617,29 @@
msgid "Port number must be an integer!"
msgstr "Le numéro de port doit être un entier !"
-#: ../Beremiz.py:304
+#: ../Beremiz.py:306
msgid "Preview"
msgstr "Aperçu avant impression"
-#: ../Beremiz.py:306
+#: ../Beremiz.py:308
msgid "Print"
msgstr "Imprimer"
-#: ../plugger.py:856
+#: ../plugger.py:901
msgid "Project not created"
msgstr "Le projet n'a pu être créé"
-#: ../plugger.py:540
+#: ../plugger.py:549
#, 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:309
+#: ../Beremiz.py:311
msgid "Properties"
msgstr "Propriétés"
#: ../plugins/python/PythonEditor.py:513
-#: ../plugins/python/PythonEditor.py:566
+#: ../plugins/python/PythonEditor.py:565
msgid "PythonEditor"
msgstr "PythonEditor"
@@ -626,15 +647,15 @@
msgid "Quit"
msgstr "Quitter"
-#: ../Beremiz.py:312
+#: ../Beremiz.py:314
msgid "Quit\tCTRL+Q"
msgstr "Quitter\tCTRL+Q"
-#: ../plugger.py:1854
+#: ../plugger.py:1937
msgid "Raw IEC code"
msgstr "Ajout code IEC"
-#: ../Beremiz.py:1400
+#: ../Beremiz.py:1425
msgid "Really delete plugin ?"
msgstr "Voulez-vous réellement supprimer le plugin ?"
@@ -650,11 +671,11 @@
msgid "Refresh\tCTRL+R"
msgstr "Actualiser\tCTRL+R"
-#: ../Beremiz.py:1400
+#: ../Beremiz.py:1425
msgid "Remove plugin"
msgstr "Enlever le plugin"
-#: ../plugger.py:1816
+#: ../plugger.py:1899
msgid "Run"
msgstr "Exécuter"
@@ -666,58 +687,57 @@
msgid "Save\tCTRL+S"
msgstr "Enregistrer\tCTRL+S"
-#: ../Beremiz.py:482
-#: ../Beremiz.py:1340
-msgid "Save changes ?"
-msgstr "Enregistrer les changements ?"
+#: ../Beremiz.py:297
+msgid "Save as\tCTRL+SHIFT+S"
+msgstr "Enregistrer sous...\tCTRL+SHIFT+S"
#: ../discovery.py:81
msgid "Services available:"
msgstr "Services disponibles:"
-#: ../plugger.py:1851
+#: ../plugger.py:1934
msgid "Show IEC code generated by PLCGenerator"
msgstr "Afficher le code IEC généré par PLCGenerator"
-#: ../plugins/canfestival/canfestival.py:220
+#: ../plugins/canfestival/canfestival.py:249
msgid "Show Master"
msgstr "Afficher le maître"
-#: ../plugins/canfestival/canfestival.py:221
+#: ../plugins/canfestival/canfestival.py:250
msgid "Show Master generated by config_utils"
msgstr "Afficher le maître généré par config_utils"
-#: ../plugger.py:1849
+#: ../plugger.py:1932
msgid "Show code"
msgstr "Afficher le code"
-#: ../plugger.py:1818
+#: ../plugger.py:1901
#: ../Beremiz_service.py:317
msgid "Start PLC"
msgstr "Démarrer l'automate"
-#: ../plugger.py:1823
+#: ../plugger.py:1906
msgid "Start PLC (debug mode)"
msgstr "Démarrer l'automate (en mode debug)"
-#: ../plugger.py:1313
+#: ../plugger.py:1396
#, python-format
msgid "Start build in %s\n"
msgstr "Début de la compilation dans %s\n"
-#: ../plugger.py:1454
+#: ../plugger.py:1537
msgid "Started"
msgstr "Démarré"
-#: ../plugger.py:1451
+#: ../plugger.py:1534
msgid "Starting"
msgstr "Démarrage"
-#: ../plugger.py:1641
+#: ../plugger.py:1724
msgid "Starting PLC (debug mode)\n"
msgstr "Démarrage de l'automate (en mode debug) en cours\n"
-#: ../plugger.py:1830
+#: ../plugger.py:1913
msgid "Stop"
msgstr "Arrêter"
@@ -725,35 +745,39 @@
msgid "Stop PLC"
msgstr "Arrêter l'automate"
-#: ../plugger.py:1832
+#: ../plugger.py:1915
msgid "Stop Running PLC"
msgstr "Arrêter l'automate en cours d'exécution"
-#: ../plugger.py:1457
+#: ../plugger.py:1540
msgid "Stopped"
msgstr "Arrêté"
-#: ../plugger.py:1673
+#: ../plugger.py:1756
msgid "Stopping debug\n"
msgstr "Arrêt du débogage en cours\n"
-#: ../Beremiz.py:370
+#: ../Beremiz.py:492
+msgid "There are changes, do you want to save?"
+msgstr "Le projet a été modifié, voulez-vous l'enregistrer ?"
+
+#: ../Beremiz.py:374
msgid "Topology"
msgstr "Topologie"
-#: ../plugger.py:1839
+#: ../plugger.py:1922
msgid "Transfer"
msgstr "Transférer"
-#: ../plugger.py:1841
+#: ../plugger.py:1924
msgid "Transfer PLC"
msgstr "Transférer l'automate"
-#: ../plugger.py:1797
+#: ../plugger.py:1880
msgid "Transfer completed successfully.\n"
msgstr "Transfert effectué avec succès.\n"
-#: ../plugger.py:1799
+#: ../plugger.py:1882
msgid "Transfer failed\n"
msgstr "Le transfert a échoué\n"
@@ -785,7 +809,7 @@
msgid "WXGLADE GUI"
msgstr "IHM WXGlade"
-#: ../plugger.py:1016
+#: ../plugger.py:1099
msgid "Warnings in ST/IL/SFC code generator :\n"
msgstr "Mises en garde du generateur de code ST/IL/SFC :\n"
@@ -793,21 +817,69 @@
msgid "Wrong URI, please check it !\n"
msgstr "URI inconnue, veuillez vérifier l'adresse !\n"
-#: ../wxPopen.py:134
+#: ../plugins/c_ext/c_ext.py:229
+msgid ""
+"You don't have write permissions.\n"
+"Open CFileEditor anyway ?"
+msgstr ""
+"Vous n'avez pas les permissions d'écriture.\n"
+"Ouvrir CFileEditor tout de même ?"
+
+#: ../plugins/python/modules/svgui/svgui.py:104
+msgid ""
+"You don't have write permissions.\n"
+"Open Inkscape anyway ?"
+msgstr ""
+"Vous n'avez pas les permissions d'écriture.\n"
+"Ouvrir Inkscape tout de même ?"
+
+#: ../plugins/canfestival/canfestival.py:207
+msgid ""
+"You don't have write permissions.\n"
+"Open NetworkEdit anyway ?"
+msgstr ""
+"Vous n'avez pas les permissions d'écriture.\n"
+"Ouvrir NetworkEdit tout de même ?"
+
+#: ../plugins/canfestival/canfestival.py:107
+msgid ""
+"You don't have write permissions.\n"
+"Open ObjDictEdit anyway ?"
+msgstr ""
+"Vous n'avez pas les permissions d'écriture.\n"
+"Ouvrir ObjdictEdit tout de même ?"
+
+#: ../plugins/python/modules/wxglade_hmi/wxglade_hmi.py:106
+msgid ""
+"You don't have write permissions.\n"
+"Open wxGlade anyway ?"
+msgstr ""
+"Vous n'avez pas les permissions d'écriture.\n"
+"Ouvrir wxGlade tout de même ?"
+
+#: ../plugger.py:872
+msgid ""
+"You must have permission to work on the project\n"
+"Work on a project copy ?"
+msgstr ""
+"Vous n'avez pas la permission de travailler sur le projet.\n"
+"Travailler sur une copie du projet ?"
+
+#: ../wxPopen.py:145
#, python-format
msgid "exited with status %s (pid %s)\n"
msgstr "a quitté avec le status %s (pid %s)\n"
-#: ../Beremiz.py:1420
-#: ../Beremiz.py:1422
+#: ../Beremiz.py:1445
+#: ../Beremiz.py:1447
msgid "file : "
msgstr "fichier :"
-#: ../Beremiz.py:1423
+#: ../Beremiz.py:1448
msgid "function : "
msgstr "fonction :"
-#: ../Beremiz.py:1423
+#: ../Beremiz.py:1448
msgid "line : "
msgstr "ligne :"
@@ -902,6 +974,9 @@
msgid "XenoConfig"
msgstr "Config Xenomai"
+#~ msgid "Save changes ?"
+#~ msgstr "Enregistrer les changements ?"
+
#, fuzzy
#~ msgid "Conflict type for location \"%s\""
#~ msgstr "Conflit entre types pour l'adresse \"%s\""
--- a/i18n/app.fil Tue Oct 27 16:32:54 2009 +0100
+++ b/i18n/app.fil Mon Nov 02 15:38:49 2009 +0100
@@ -1,6 +1,5 @@
../Beremiz.py
../plugger.py
-../beremiz_postinst.py
../Beremiz_service.py
../discovery.py
../wxPopen.py
--- a/i18n/messages.pot Tue Oct 27 16:32:54 2009 +0100
+++ b/i18n/messages.pot Mon Nov 02 15:38:49 2009 +0100
@@ -8,7 +8,7 @@
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-10-09 16:27+0200\n"
+"POT-Creation-Date: 2009-11-02 10:40+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -16,28 +16,26 @@
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
-#: ../Beremiz.py:1432
+#: ../Beremiz.py:1457
#, 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"
+"Please be kind enough to send this file to:\n"
+"edouard.tisserant@gmail.com\n"
"\n"
"You should now restart Beremiz.\n"
"\n"
"Traceback:\n"
msgstr ""
-#: ../plugger.py:1370
+#: ../plugger.py:1453
msgid " generation failed !\n"
msgstr ""
-#: ../Beremiz.py:1332
+#: ../Beremiz.py:1357
#, python-format
msgid "\"%s\" folder is not a valid Beremiz project\n"
msgstr ""
@@ -46,45 +44,45 @@
msgid "&Edit"
msgstr ""
-#: ../Beremiz.py:1420 ../Beremiz.py:1422 ../Beremiz.py:1423
+#: ../Beremiz.py:1445 ../Beremiz.py:1447 ../Beremiz.py:1448
msgid ", "
msgstr ""
-#: ../Beremiz.py:1418
+#: ../Beremiz.py:1443
msgid ". "
msgstr ""
-#: ../plugger.py:432
+#: ../plugger.py:443
#, python-format
msgid "A child names \"%s\" already exist -> \"%s\"\n"
msgstr ""
-#: ../plugger.py:464
+#: ../plugger.py:475
#, python-format
msgid "A child with IEC channel %d already exist -> %d\n"
msgstr ""
-#: ../Beremiz.py:329
+#: ../Beremiz.py:332
msgid "About"
msgstr ""
-#: ../Beremiz.py:1369
+#: ../Beremiz.py:1392
msgid "About Beremiz"
msgstr ""
-#: ../Beremiz.py:1391
+#: ../Beremiz.py:1415
msgid "Add Plugin"
msgstr ""
-#: ../Beremiz.py:585 ../Beremiz.py:849
+#: ../Beremiz.py:603 ../Beremiz.py:867
msgid "Add a sub plugin"
msgstr ""
-#: ../plugger.py:1683
+#: ../plugger.py:1766
msgid "Already connected. Please disconnect\n"
msgstr ""
-#: ../Beremiz.py:1088
+#: ../Beremiz.py:1106
msgid "Append "
msgstr ""
@@ -94,62 +92,62 @@
msgid "Bad location size : %s"
msgstr ""
-#: ../Beremiz.py:417
+#: ../Beremiz.py:426
msgid "Beremiz"
msgstr ""
-#: ../Beremiz.py:327
+#: ../Beremiz.py:330
msgid "Beremiz\tF1"
msgstr ""
-#: ../plugger.py:1466
+#: ../plugger.py:1549
msgid "Broken"
msgstr ""
-#: ../plugger.py:1807
+#: ../plugger.py:1890
msgid "Build"
msgstr ""
-#: ../plugger.py:1434
+#: ../plugger.py:1517
msgid "Build directory already clean\n"
msgstr ""
-#: ../plugger.py:1808
+#: ../plugger.py:1891
msgid "Build project into build folder"
msgstr ""
-#: ../plugger.py:1388
+#: ../plugger.py:1471
msgid "C Build crashed !\n"
msgstr ""
-#: ../plugger.py:1385
+#: ../plugger.py:1468
msgid "C Build failed.\n"
msgstr ""
-#: ../plugger.py:1374
+#: ../plugger.py:1457
msgid "C code generated successfully.\n"
msgstr ""
-#: ../targets/toolchain_gcc.py:125
+#: ../targets/toolchain_gcc.py:129
#, python-format
msgid "C compilation of %s failed.\n"
msgstr ""
-#: ../plugger.py:1117
+#: ../plugger.py:1200
#, python-format
msgid "Can't find module for target %s!\n"
msgstr ""
-#: ../plugger.py:1756
+#: ../plugger.py:1839
msgid "Cannot compare latest build to target. Please build.\n"
msgstr ""
-#: ../plugger.py:502
+#: ../plugger.py:513
#, python-format
msgid "Cannot create child %s of type %s "
msgstr ""
-#: ../plugger.py:457
+#: ../plugger.py:468
#, python-format
msgid "Cannot find lower free IEC channel than %d\n"
msgstr ""
@@ -158,7 +156,7 @@
msgid "Cannot get PLC status - connection failed.\n"
msgstr ""
-#: ../plugger.py:1215
+#: ../plugger.py:1298
msgid "Cannot open/parse VARIABLES.csv!\n"
msgstr ""
@@ -187,7 +185,11 @@
msgid "Choose a SVG file"
msgstr ""
-#: ../Beremiz.py:1289 ../Beremiz.py:1314
+#: ../plugger.py:969
+msgid "Choose a directory to save project"
+msgstr ""
+
+#: ../Beremiz.py:1311 ../Beremiz.py:1339
msgid "Choose a project"
msgstr ""
@@ -195,47 +197,47 @@
msgid "Choose a working directory "
msgstr ""
-#: ../plugger.py:882
+#: ../plugger.py:927
msgid "Chosen folder doesn't contain a program. It's not a valid project!"
msgstr ""
-#: ../plugger.py:847
+#: ../plugger.py:892
msgid "Chosen folder isn't empty. You can't use it for a new project!"
msgstr ""
-#: ../plugger.py:1811
+#: ../plugger.py:1894
msgid "Clean"
msgstr ""
-#: ../plugger.py:1813
+#: ../plugger.py:1896
msgid "Clean project build folder"
msgstr ""
-#: ../plugger.py:1431
+#: ../plugger.py:1514
msgid "Cleaning the build directory\n"
msgstr ""
-#: ../Beremiz.py:483 ../Beremiz.py:1341
+#: ../Beremiz.py:504
msgid "Close Application"
msgstr ""
+#: ../Beremiz.py:301 ../Beremiz.py:489
+msgid "Close Project"
+msgstr ""
+
#: ../Beremiz.py:299
-msgid "Close Project"
-msgstr ""
-
-#: ../Beremiz.py:297
msgid "Close Tab\tCTRL+W"
msgstr ""
-#: ../plugger.py:1039
+#: ../plugger.py:1122
msgid "Compiling IEC Program into C code...\n"
msgstr ""
-#: ../plugger.py:1835
+#: ../plugger.py:1918
msgid "Connect"
msgstr ""
-#: ../plugger.py:1836
+#: ../plugger.py:1919
msgid "Connect to the target PLC"
msgstr ""
@@ -244,41 +246,41 @@
msgid "Connecting to URI : %s\n"
msgstr ""
-#: ../plugger.py:1702
+#: ../plugger.py:1785
msgid "Connection canceled!\n"
msgstr ""
-#: ../plugger.py:1719
+#: ../plugger.py:1802
#, python-format
msgid "Connection failed to %s!\n"
msgstr ""
-#: ../plugger.py:625
+#: ../plugger.py:634
#, python-format
msgid ""
"Could not add child \"%s\", type %s :\n"
"%s\n"
msgstr ""
-#: ../plugger.py:602
+#: ../plugger.py:611
#, python-format
msgid ""
"Couldn't load plugin base parameters %s :\n"
" %s"
msgstr ""
-#: ../plugger.py:613
+#: ../plugger.py:622
#, python-format
msgid ""
"Couldn't load plugin parameters %s :\n"
" %s"
msgstr ""
-#: ../plugger.py:1647
+#: ../plugger.py:1730
msgid "Couldn't start PLC debug !\n"
msgstr ""
-#: ../plugger.py:1677
+#: ../plugger.py:1760
msgid "Couldn't stop PLC !\n"
msgstr ""
@@ -286,53 +288,53 @@
msgid "Create HMI"
msgstr ""
-#: ../plugger.py:1821
+#: ../plugger.py:1904
msgid "Debug"
msgstr ""
-#: ../plugger.py:1520
+#: ../plugger.py:1603
#, python-format
msgid "Debug : Unknown variable %s\n"
msgstr ""
-#: ../plugger.py:1632
+#: ../plugger.py:1715
msgid "Debug Thread couldn't be killed"
msgstr ""
-#: ../plugger.py:1616
+#: ../plugger.py:1699
#, python-format
msgid "Debug data not coherent %d != %d\n"
msgstr ""
-#: ../plugger.py:1624
+#: ../plugger.py:1707
msgid "Debugger disabled\n"
msgstr ""
-#: ../Beremiz.py:840
+#: ../Beremiz.py:858
msgid "Delete this plugin"
msgstr ""
-#: ../plugger.py:1463
+#: ../plugger.py:1546
msgid "Dirty"
msgstr ""
-#: ../plugger.py:1844
+#: ../plugger.py:1927
msgid "Disconnect"
msgstr ""
-#: ../plugger.py:1846
+#: ../plugger.py:1929
msgid "Disconnect from PLC"
msgstr ""
-#: ../plugger.py:1469
+#: ../plugger.py:1552
msgid "Disconnected"
msgstr ""
-#: ../plugins/c_ext/c_ext.py:236 ../plugins/c_ext/c_ext.py:237
+#: ../plugins/c_ext/c_ext.py:250 ../plugins/c_ext/c_ext.py:251
msgid "Edit C File"
msgstr ""
-#: ../plugins/canfestival/canfestival.py:217
+#: ../plugins/canfestival/canfestival.py:246
msgid "Edit CanOpen Network with NetworkEdit"
msgstr ""
@@ -340,19 +342,19 @@
msgid "Edit a WxWidgets GUI with WXGlade"
msgstr ""
-#: ../plugins/canfestival/canfestival.py:216
+#: ../plugins/canfestival/canfestival.py:245
msgid "Edit network"
msgstr ""
-#: ../plugger.py:1855
+#: ../plugger.py:1938
msgid "Edit raw IEC code added to code generated by PLCGenerator"
msgstr ""
-#: ../plugger.py:1460
+#: ../plugger.py:1543
msgid "Empty"
msgstr ""
-#: ../Beremiz.py:790
+#: ../Beremiz.py:808
msgid "Enable/Disable this plugin"
msgstr ""
@@ -368,54 +370,54 @@
msgid "Enter the IP of the interface to bind"
msgstr ""
-#: ../Beremiz.py:1446 ../Beremiz.py:1456 ../Beremiz_service.py:268
-#: ../Beremiz_service.py:392
+#: ../Beremiz.py:1469 ../Beremiz.py:1479 ../plugger.py:873
+#: ../Beremiz_service.py:268 ../Beremiz_service.py:392
msgid "Error"
msgstr ""
-#: ../plugger.py:1087
+#: ../plugger.py:1170
msgid "Error : At least one configuration and one resource must be declared in PLC !\n"
msgstr ""
-#: ../plugger.py:1079
+#: ../plugger.py:1162
#, python-format
msgid "Error : IEC to C compiler returned %d\n"
msgstr ""
-#: ../plugger.py:1021
+#: ../plugger.py:1104
#, python-format
msgid ""
"Error in ST/IL/SFC code generator :\n"
"%s\n"
msgstr ""
-#: ../plugger.py:207
+#: ../plugger.py:218
#, python-format
msgid "Error while saving \"%s\"\n"
msgstr ""
-#: ../plugins/canfestival/canfestival.py:208
+#: ../plugins/canfestival/canfestival.py:237
msgid "Error: No Master generated\n"
msgstr ""
-#: ../plugins/canfestival/canfestival.py:203
+#: ../plugins/canfestival/canfestival.py:232
msgid "Error: No PLC built\n"
msgstr ""
-#: ../plugger.py:1713
+#: ../plugger.py:1796
#, python-format
msgid "Exception while connecting %s!\n"
msgstr ""
-#: ../plugger.py:1091
+#: ../plugger.py:1174
msgid "Extracting Located Variables...\n"
msgstr ""
-#: ../plugger.py:1771
+#: ../plugger.py:1854
msgid "Failed : Must build before transfer.\n"
msgstr ""
-#: ../plugger.py:1379
+#: ../plugger.py:1462
msgid "Fatal : cannot get builder.\n"
msgstr ""
@@ -423,15 +425,15 @@
msgid "Force runtime reload\n"
msgstr ""
-#: ../plugger.py:1011
+#: ../plugger.py:1094
msgid "Generating SoftPLC IEC-61131 ST/IL/SFC code...\n"
msgstr ""
-#: ../plugger.py:1329
+#: ../plugger.py:1412
msgid "Generating plugins C code\n"
msgstr ""
-#: ../plugger.py:1321
+#: ../plugger.py:1404
msgid "IEC-61131-3 code generation failed !\n"
msgstr ""
@@ -454,15 +456,15 @@
msgid "Invalid type \"%s\"-> %d != %d for location\"%s\""
msgstr ""
-#: ../plugger.py:1777
+#: ../plugger.py:1860
msgid "Latest build already matches current target. Transfering anyway...\n"
msgstr ""
-#: ../plugger.py:1747
+#: ../plugger.py:1830
msgid "Latest build does not match with target, please transfer.\n"
msgstr ""
-#: ../plugger.py:1751
+#: ../plugger.py:1834
msgid "Latest build matches target, no transfer needed.\n"
msgstr ""
@@ -474,7 +476,7 @@
msgid "Launch a live Python shell"
msgstr ""
-#: ../targets/toolchain_gcc.py:133
+#: ../targets/toolchain_gcc.py:137
msgid "Linking :\n"
msgstr ""
@@ -482,11 +484,11 @@
msgid "Local"
msgstr ""
-#: ../Beremiz.py:376
+#: ../Beremiz.py:380
msgid "Log Console"
msgstr ""
-#: ../plugger.py:512
+#: ../plugger.py:523
#, python-format
msgid "Max count (%d) reached for this plugin of type %s "
msgstr ""
@@ -499,7 +501,7 @@
msgid "New\tCTRL+N"
msgstr ""
-#: ../plugger.py:1801
+#: ../plugger.py:1884
msgid "No PLC to transfer (did build succeed ?)\n"
msgstr ""
@@ -536,28 +538,48 @@
msgid "Open\tCTRL+O"
msgstr ""
-#: ../targets/toolchain_gcc.py:101
+#: ../plugins/c_ext/c_ext.py:230
+msgid "Open CFileEditor"
+msgstr ""
+
+#: ../plugins/python/modules/svgui/svgui.py:105
+msgid "Open Inkscape"
+msgstr ""
+
+#: ../plugins/canfestival/canfestival.py:208
+msgid "Open NetworkEdit"
+msgstr ""
+
+#: ../plugins/canfestival/canfestival.py:108
+msgid "Open ObjDictEdit"
+msgstr ""
+
+#: ../plugins/python/modules/wxglade_hmi/wxglade_hmi.py:107
+msgid "Open wxGlade"
+msgstr ""
+
+#: ../targets/toolchain_gcc.py:105
msgid "PLC :\n"
msgstr ""
-#: ../plugger.py:1489 ../plugger.py:1733
+#: ../plugger.py:1572 ../plugger.py:1816
#, python-format
msgid "PLC is %s\n"
msgstr ""
-#: ../Beremiz.py:302
+#: ../Beremiz.py:304
msgid "Page Setup"
msgstr ""
-#: ../Beremiz.py:1391
+#: ../Beremiz.py:1415
msgid "Please enter a name for plugin:"
msgstr ""
-#: ../targets/toolchain_gcc.py:99
+#: ../targets/toolchain_gcc.py:103
msgid "Plugin : "
msgstr ""
-#: ../plugger.py:1335
+#: ../plugger.py:1418
msgid "Plugins code generation failed !\n"
msgstr ""
@@ -569,28 +591,28 @@
msgid "Port number must be an integer!"
msgstr ""
-#: ../Beremiz.py:304
+#: ../Beremiz.py:306
msgid "Preview"
msgstr ""
-#: ../Beremiz.py:306
+#: ../Beremiz.py:308
msgid "Print"
msgstr ""
-#: ../plugger.py:856
+#: ../plugger.py:901
msgid "Project not created"
msgstr ""
-#: ../plugger.py:540
+#: ../plugger.py:549
#, python-format
msgid "Project tree layout do not match plugin.xml %s!=%s "
msgstr ""
-#: ../Beremiz.py:309
+#: ../Beremiz.py:311
msgid "Properties"
msgstr ""
-#: ../plugins/python/PythonEditor.py:513 ../plugins/python/PythonEditor.py:566
+#: ../plugins/python/PythonEditor.py:513 ../plugins/python/PythonEditor.py:565
msgid "PythonEditor"
msgstr ""
@@ -598,15 +620,15 @@
msgid "Quit"
msgstr ""
-#: ../Beremiz.py:312
+#: ../Beremiz.py:314
msgid "Quit\tCTRL+Q"
msgstr ""
-#: ../plugger.py:1854
+#: ../plugger.py:1937
msgid "Raw IEC code"
msgstr ""
-#: ../Beremiz.py:1400
+#: ../Beremiz.py:1425
msgid "Really delete plugin ?"
msgstr ""
@@ -622,11 +644,11 @@
msgid "Refresh\tCTRL+R"
msgstr ""
-#: ../Beremiz.py:1400
+#: ../Beremiz.py:1425
msgid "Remove plugin"
msgstr ""
-#: ../plugger.py:1816
+#: ../plugger.py:1899
msgid "Run"
msgstr ""
@@ -638,56 +660,56 @@
msgid "Save\tCTRL+S"
msgstr ""
-#: ../Beremiz.py:482 ../Beremiz.py:1340
-msgid "Save changes ?"
+#: ../Beremiz.py:297
+msgid "Save as\tCTRL+SHIFT+S"
msgstr ""
#: ../discovery.py:81
msgid "Services available:"
msgstr ""
-#: ../plugger.py:1851
+#: ../plugger.py:1934
msgid "Show IEC code generated by PLCGenerator"
msgstr ""
-#: ../plugins/canfestival/canfestival.py:220
+#: ../plugins/canfestival/canfestival.py:249
msgid "Show Master"
msgstr ""
-#: ../plugins/canfestival/canfestival.py:221
+#: ../plugins/canfestival/canfestival.py:250
msgid "Show Master generated by config_utils"
msgstr ""
-#: ../plugger.py:1849
+#: ../plugger.py:1932
msgid "Show code"
msgstr ""
-#: ../plugger.py:1818 ../Beremiz_service.py:317
+#: ../plugger.py:1901 ../Beremiz_service.py:317
msgid "Start PLC"
msgstr ""
-#: ../plugger.py:1823
+#: ../plugger.py:1906
msgid "Start PLC (debug mode)"
msgstr ""
-#: ../plugger.py:1313
+#: ../plugger.py:1396
#, python-format
msgid "Start build in %s\n"
msgstr ""
-#: ../plugger.py:1454
+#: ../plugger.py:1537
msgid "Started"
msgstr ""
-#: ../plugger.py:1451
+#: ../plugger.py:1534
msgid "Starting"
msgstr ""
-#: ../plugger.py:1641
+#: ../plugger.py:1724
msgid "Starting PLC (debug mode)\n"
msgstr ""
-#: ../plugger.py:1830
+#: ../plugger.py:1913
msgid "Stop"
msgstr ""
@@ -695,35 +717,39 @@
msgid "Stop PLC"
msgstr ""
-#: ../plugger.py:1832
+#: ../plugger.py:1915
msgid "Stop Running PLC"
msgstr ""
-#: ../plugger.py:1457
+#: ../plugger.py:1540
msgid "Stopped"
msgstr ""
-#: ../plugger.py:1673
+#: ../plugger.py:1756
msgid "Stopping debug\n"
msgstr ""
-#: ../Beremiz.py:370
+#: ../Beremiz.py:492
+msgid "There are changes, do you want to save?"
+msgstr ""
+
+#: ../Beremiz.py:374
msgid "Topology"
msgstr ""
-#: ../plugger.py:1839
+#: ../plugger.py:1922
msgid "Transfer"
msgstr ""
-#: ../plugger.py:1841
+#: ../plugger.py:1924
msgid "Transfer PLC"
msgstr ""
-#: ../plugger.py:1797
+#: ../plugger.py:1880
msgid "Transfer completed successfully.\n"
msgstr ""
-#: ../plugger.py:1799
+#: ../plugger.py:1882
msgid "Transfer failed\n"
msgstr ""
@@ -755,7 +781,7 @@
msgid "WXGLADE GUI"
msgstr ""
-#: ../plugger.py:1016
+#: ../plugger.py:1099
msgid "Warnings in ST/IL/SFC code generator :\n"
msgstr ""
@@ -763,20 +789,56 @@
msgid "Wrong URI, please check it !\n"
msgstr ""
-#: ../wxPopen.py:134
+#: ../plugins/c_ext/c_ext.py:229
+msgid ""
+"You don't have write permissions.\n"
+"Open CFileEditor anyway ?"
+msgstr ""
+
+#: ../plugins/python/modules/svgui/svgui.py:104
+msgid ""
+"You don't have write permissions.\n"
+"Open Inkscape anyway ?"
+msgstr ""
+
+#: ../plugins/canfestival/canfestival.py:207
+msgid ""
+"You don't have write permissions.\n"
+"Open NetworkEdit anyway ?"
+msgstr ""
+
+#: ../plugins/canfestival/canfestival.py:107
+msgid ""
+"You don't have write permissions.\n"
+"Open ObjDictEdit anyway ?"
+msgstr ""
+
+#: ../plugins/python/modules/wxglade_hmi/wxglade_hmi.py:106
+msgid ""
+"You don't have write permissions.\n"
+"Open wxGlade anyway ?"
+msgstr ""
+
+#: ../plugger.py:872
+msgid ""
+"You must have permission to work on the project\n"
+"Work on a project copy ?"
+msgstr ""
+
+#: ../wxPopen.py:145
#, python-format
msgid "exited with status %s (pid %s)\n"
msgstr ""
-#: ../Beremiz.py:1420 ../Beremiz.py:1422
+#: ../Beremiz.py:1445 ../Beremiz.py:1447
msgid "file : "
msgstr ""
-#: ../Beremiz.py:1423
+#: ../Beremiz.py:1448
msgid "function : "
msgstr ""
-#: ../Beremiz.py:1423
+#: ../Beremiz.py:1448
msgid "line : "
msgstr ""
Binary file images/EditCfile.png has changed
Binary file images/HideVars.png has changed
Binary file images/Maximize.png has changed
Binary file images/Minimize.png has changed
Binary file images/ShowIECcode.png has changed
Binary file images/ShowVars.png has changed
Binary file images/editIECrawcode.png has changed
Binary file images/editPYTHONcode.png has changed
Binary file images/editWXGLADE.png has changed
--- a/images/icons.svg Tue Oct 27 16:32:54 2009 +0100
+++ b/images/icons.svg Mon Nov 02 15:38:49 2009 +0100
@@ -29,8 +29,8 @@
</rdf:RDF>
</metadata>
<sodipodi:namedview
- inkscape:window-height="750"
- inkscape:window-width="1255"
+ inkscape:window-height="974"
+ inkscape:window-width="1280"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
guidetolerance="10.0"
@@ -40,13 +40,13 @@
bordercolor="#666666"
pagecolor="#ffffff"
id="base"
- showgrid="true"
- inkscape:zoom="7.9999996"
- inkscape:cx="667.296"
- inkscape:cy="684.08131"
- inkscape:window-x="15"
+ showgrid="false"
+ inkscape:zoom="1.4142135"
+ inkscape:cx="335.487"
+ inkscape:cy="81.26617"
+ inkscape:window-x="0"
inkscape:window-y="25"
- inkscape:current-layer="g46878"
+ inkscape:current-layer="g18993"
showguides="true"
inkscape:guide-bbox="true">
<inkscape:grid
@@ -85166,24 +85166,8 @@
y="1063.0302"
id="tspan16413">2009.0 Beta</tspan></text>
<g
- id="g17729"
- transform="matrix(1.1079964,0,0,1.1079964,-1240.4932,723.37188)">
- <path
- d="M 210.40571,340.85362 L 202.96571,340.85362 C 200.83237,340.88029 199.11237,340.14696 197.80571,338.65362 C 196.49904,337.16029 195.8457,335.34696 195.84571,333.21362 L 195.84571,315.41362 L 203.60571,315.41362 L 203.60571,329.97362 C 203.6057,331.30697 203.73903,332.22697 204.00571,332.73362 C 204.27236,333.2403 204.89903,333.49363 205.88571,333.49362 L 210.40571,333.45362 L 210.40571,340.85362 L 210.40571,340.85362 M 212.92957,331.69362 C 212.92957,329.1603 213.80957,326.9603 215.56957,325.09362 C 217.32956,323.22698 219.50289,322.29364 222.08957,322.29362 C 225.07622,322.29364 227.43622,323.24031 229.16957,325.13362 C 230.92955,327.0003 231.82288,329.06697 231.84957,331.33362 C 231.84955,331.3603 231.84955,331.38697 231.84957,331.41362 C 231.84955,331.41363 231.84955,331.42697 231.84957,331.45362 C 231.84955,334.57363 230.84955,337.00029 228.84957,338.73362 C 226.87622,340.46696 224.70289,341.36029 222.32957,341.41362 C 222.27623,341.41362 222.22289,341.41362 222.16957,341.41362 C 222.14289,341.41362 222.11623,341.41362 222.08957,341.41362 C 221.66289,341.41362 221.20956,341.37362 220.72957,341.29362 C 220.24956,341.21362 219.76956,341.09362 219.28957,340.93362 C 217.68956,340.37362 216.2229,339.33363 214.88957,337.81362 C 213.5829,336.29363 212.92957,334.26696 212.92957,331.73362 L 212.92957,331.69362 M 220.04957,331.69362 C 220.04956,332.4403 220.27623,333.02697 220.72957,333.45362 C 221.20956,333.85363 221.72956,334.06696 222.28957,334.09362 C 222.31623,334.09363 222.32956,334.09363 222.32957,334.09362 C 222.35623,334.09363 222.38289,334.09363 222.40957,334.09362 C 222.96956,334.09363 223.47622,333.89363 223.92957,333.49362 C 224.40956,333.06697 224.64956,332.4803 224.64957,331.73362 C 224.64956,331.09363 224.44956,330.6003 224.04957,330.25362 C 223.67622,329.8803 223.24956,329.65364 222.76957,329.57362 C 222.71623,329.54697 222.64956,329.53364 222.56957,329.53362 C 222.51623,329.53364 222.46289,329.53364 222.40957,329.53362 C 222.38289,329.53364 222.35623,329.53364 222.32957,329.53362 C 222.32956,329.53364 222.31623,329.53364 222.28957,329.53362 C 221.72956,329.5603 221.20956,329.77364 220.72957,330.17362 C 220.27623,330.54697 220.04956,331.06697 220.04957,331.73362 L 220.04957,331.69362"
- style="font-size:40px;font-style:normal;font-variant:normal;font-weight:200;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bauhaus-Heavy-Bold;-inkscape-font-specification:Bauhaus-Heavy-Bold Ultra-Light"
- id="path17724" />
- <path
- d="M 249.67894,340.85362 L 242.23894,340.85362 C 240.1056,340.88029 238.38561,340.14696 237.07894,338.65362 C 235.77228,337.16029 235.11894,335.34696 235.11894,333.21362 L 235.11894,315.41362 L 242.87894,315.41362 L 242.87894,329.97362 C 242.87894,331.30697 243.01227,332.22697 243.27894,332.73362 C 243.5456,333.2403 244.17227,333.49363 245.15894,333.49362 L 249.67894,333.45362 L 249.67894,340.85362 L 249.67894,340.85362 M 251.81535,340.85362 L 251.81535,322.89362 L 259.49535,322.89362 L 259.49535,340.85362 L 251.81535,340.85362 L 251.81535,340.85362 M 251.53535,316.85362 C 251.53535,315.60032 251.96202,314.62698 252.81535,313.93362 C 253.66868,313.21365 254.66868,312.85365 255.81535,312.85362 C 255.94868,312.85365 256.06868,312.86699 256.17535,312.89362 C 256.30868,312.89365 256.42868,312.90699 256.53535,312.93362 C 257.44201,313.06699 258.26868,313.48032 259.01535,314.17362 C 259.76201,314.86698 260.13534,315.77365 260.13535,316.89362 L 260.13535,317.13362 C 260.13534,318.44031 259.70867,319.45365 258.85535,320.17362 C 258.00201,320.86698 257.06868,321.24031 256.05535,321.29362 C 256.00201,321.29364 255.94868,321.29364 255.89535,321.29362 C 255.86868,321.29364 255.84201,321.29364 255.81535,321.29362 C 254.74868,321.29364 253.76201,320.93364 252.85535,320.21362 C 251.97535,319.46698 251.53535,318.36031 251.53535,316.89362 L 251.53535,316.85362"
- style="font-size:40px;font-style:normal;font-variant:normal;font-weight:200;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#5759ce;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.34643704px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bauhaus-Heavy-Bold;-inkscape-font-specification:Bauhaus-Heavy-Bold Ultra-Light"
- id="path17718" />
- <path
- d="M 266.90448,340.85362 L 266.90448,322.53362 L 262.62448,322.53362 L 262.62448,315.41362 L 279.18448,315.41362 L 279.18448,322.53362 L 274.94448,322.53362 L 274.94448,340.85362 L 266.90448,340.85362 L 266.90448,340.85362 M 297.09281,329.13362 L 287.93281,334.33362 L 285.85281,330.57362 L 289.33281,328.57362 C 289.1728,328.4403 288.98613,328.30697 288.77281,328.17362 C 288.58613,328.0403 288.38613,327.94697 288.17281,327.89362 C 288.0928,327.86697 288.0128,327.85364 287.93281,327.85362 C 287.8528,327.82697 287.7728,327.81364 287.69281,327.81362 C 287.63946,327.81364 287.5728,327.82697 287.49281,327.85362 C 287.43947,327.85364 287.3728,327.85364 287.29281,327.85362 C 286.6528,327.98697 286.06613,328.4003 285.53281,329.09362 C 284.99947,329.7603 284.7328,330.54697 284.73281,331.45362 C 284.7328,332.6803 285.06613,333.65363 285.73281,334.37362 C 286.42613,335.06696 287.26613,335.41363 288.25281,335.41362 C 288.62613,335.41363 289.02613,335.3603 289.45281,335.25362 C 289.87946,335.1203 290.30613,334.94696 290.73281,334.73362 C 291.13279,334.5203 291.51946,334.26696 291.89281,333.97362 C 292.29279,333.6803 292.66613,333.33363 293.01281,332.93362 L 297.09281,336.89362 C 296.18612,338.22696 294.97279,339.28029 293.45281,340.05362 C 291.93279,340.82696 290.34613,341.29362 288.69281,341.45362 C 288.50613,341.45362 288.31946,341.45362 288.13281,341.45362 C 287.9728,341.48029 287.79946,341.49362 287.61281,341.49362 C 285.31947,341.49362 283.19947,340.77362 281.25281,339.33362 C 279.33281,337.89363 278.30614,335.57363 278.17281,332.37362 C 278.17281,332.34697 278.15947,332.3203 278.13281,332.29362 C 278.13281,332.2403 278.13281,332.18697 278.13281,332.13362 C 278.13281,332.0803 278.11947,332.0403 278.09281,332.01362 C 278.09281,331.9603 278.09281,331.9203 278.09281,331.89362 C 278.09281,329.14697 278.85281,327.0003 280.37281,325.45362 C 281.8928,323.90697 283.55947,322.93364 285.37281,322.53362 C 285.6928,322.45364 286.0128,322.40031 286.33281,322.37362 C 286.67947,322.32031 287.0128,322.29364 287.33281,322.29362 C 290.18613,322.29364 292.34613,322.98698 293.81281,324.37362 C 295.27946,325.73364 296.37279,327.33364 297.09281,329.17362 L 297.09281,329.13362 M 311.8195,340.85362 L 308.4195,340.85362 C 305.11282,340.88029 302.61949,339.94696 300.9395,338.05362 C 299.28616,336.1603 298.4595,334.0803 298.4595,331.81362 C 298.4595,331.73363 298.4595,331.66697 298.4595,331.61362 C 298.4595,331.53363 298.4595,331.45363 298.4595,331.37362 C 298.56616,329.10697 299.47283,327.02697 301.1795,325.13362 C 302.91282,323.24031 305.41949,322.29364 308.6995,322.29362 L 311.8195,322.25362 L 311.8195,328.85362 L 308.4195,328.85362 C 307.69949,328.8803 307.11282,329.1603 306.6595,329.69362 C 306.20615,330.22697 305.93949,330.8003 305.8595,331.41362 C 305.85949,331.46697 305.85949,331.5203 305.8595,331.57362 C 305.85949,331.62697 305.85949,331.6803 305.8595,331.73362 C 305.85949,331.7603 305.85949,331.8003 305.8595,331.85362 C 305.85949,331.8803 305.85949,331.90697 305.8595,331.93362 C 305.91282,332.54697 306.15282,333.10697 306.5795,333.61362 C 307.03282,334.1203 307.64615,334.37363 308.4195,334.37362 L 311.8195,334.33362 L 311.8195,340.85362 L 311.8195,340.85362 M 314.36637,340.85362 L 314.36637,315.41362 L 321.76637,315.41362 L 321.76637,323.73362 C 322.2997,323.36031 322.87303,323.06698 323.48637,322.85362 C 324.09969,322.61364 324.71303,322.46698 325.32637,322.41362 C 325.43303,322.38698 325.52636,322.37364 325.60637,322.37362 C 325.71303,322.37364 325.80636,322.37364 325.88637,322.37362 C 327.45969,322.37364 328.88636,322.97364 330.16637,324.17362 C 331.47302,325.34697 332.12635,327.10697 332.12637,329.45362 L 332.12637,340.85362 L 324.64637,340.85362 L 324.64637,330.29362 C 324.64636,329.86697 324.52636,329.5203 324.28637,329.25362 C 324.04636,328.98697 323.79303,328.82697 323.52637,328.77362 C 323.47303,328.74697 323.41969,328.73364 323.36637,328.73362 C 323.33969,328.73364 323.29969,328.73364 323.24637,328.73362 C 323.21969,328.73364 323.19303,328.73364 323.16637,328.73362 C 323.16636,328.73364 323.15303,328.73364 323.12637,328.73362 C 322.7797,328.7603 322.4597,328.9203 322.16637,329.21362 C 321.8997,329.4803 321.76636,329.85364 321.76637,330.33362 L 321.76637,340.85362 L 314.36637,340.85362 L 314.36637,340.85362"
- style="font-size:40px;font-style:normal;font-variant:normal;font-weight:200;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#939393;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.34643704px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bauhaus-Heavy-Bold;-inkscape-font-specification:Bauhaus-Heavy-Bold Ultra-Light"
- id="path17712" />
- </g>
- <g
id="g2414"
- transform="matrix(0.5511608,0,0,0.5511608,-864.43103,996.99467)">
+ transform="matrix(0.5511608,0,0,0.5511608,-977.19352,996.99467)">
<path
d="M 120.87354,163.01839 L 128.91354,163.01839 L 128.91354,179.93839 C 128.91353,180.60507 129.0602,181.0984 129.35354,181.41839 C 129.67353,181.7384 130.00687,181.8984 130.35354,181.89839 C 130.3802,181.8984 130.39353,181.8984 130.39354,181.89839 C 130.4202,181.8984 130.44687,181.8984 130.47354,181.89839 C 130.79353,181.87173 131.08687,181.6984 131.35354,181.37839 C 131.6202,181.0584 131.75353,180.59173 131.75354,179.97839 L 131.75354,163.01839 L 139.79354,163.01839 L 139.79354,179.65839 C 139.79352,180.3784 139.95352,180.9384 140.27354,181.33839 C 140.59352,181.71173 140.95352,181.8984 141.35354,181.89839 C 141.40685,181.8984 141.44685,181.8984 141.47354,181.89839 C 141.52685,181.8984 141.58019,181.88506 141.63354,181.85839 C 141.95352,181.7784 142.24685,181.5784 142.51354,181.25839 C 142.78019,180.9384 142.91352,180.51173 142.91354,179.97839 L 142.91354,163.01839 L 150.95354,163.01839 L 150.95354,180.77839 C 150.95351,183.12506 150.14018,185.00506 148.51354,186.41839 C 146.88685,187.80506 145.10018,188.63172 143.15354,188.89839 C 142.91352,188.95172 142.67352,188.97839 142.43354,188.97839 C 142.19352,189.00506 141.95352,189.01839 141.71354,189.01839 C 140.56686,189.01839 139.48686,188.81839 138.47354,188.41839 C 137.48686,187.99172 136.67353,187.35173 136.03354,186.49839 C 135.31353,187.32506 134.4202,187.93839 133.35354,188.33839 C 132.28686,188.71172 131.1802,188.89839 130.03354,188.89839 C 129.87353,188.89839 129.71353,188.88506 129.55354,188.85839 C 129.4202,188.85839 129.27353,188.85839 129.11354,188.85839 C 127.0602,188.67172 125.16687,187.87173 123.43354,186.45839 C 121.72687,185.01839 120.87354,183.04506 120.87354,180.53839 L 120.87354,163.01839 L 120.87354,163.01839 M 172.95104,176.73839 L 163.79104,181.93839 L 161.71104,178.17839 L 165.19104,176.17839 C 165.03103,176.04507 164.84436,175.91174 164.63104,175.77839 C 164.44437,175.64507 164.24437,175.55174 164.03104,175.49839 C 163.95103,175.47174 163.87103,175.4584 163.79104,175.45839 C 163.71103,175.43174 163.63103,175.4184 163.55104,175.41839 C 163.4977,175.4184 163.43103,175.43174 163.35104,175.45839 C 163.2977,175.4584 163.23103,175.4584 163.15104,175.45839 C 162.51103,175.59174 161.92437,176.00507 161.39104,176.69839 C 160.8577,177.36507 160.59104,178.15173 160.59104,179.05839 C 160.59104,180.28507 160.92437,181.2584 161.59104,181.97839 C 162.28437,182.67173 163.12437,183.0184 164.11104,183.01839 C 164.48437,183.0184 164.88436,182.96506 165.31104,182.85839 C 165.7377,182.72506 166.16436,182.55173 166.59104,182.33839 C 166.99103,182.12506 167.3777,181.87173 167.75104,181.57839 C 168.15103,181.28507 168.52436,180.9384 168.87104,180.53839 L 172.95104,184.49839 C 172.04436,185.83173 170.83103,186.88506 169.31104,187.65839 C 167.79103,188.43172 166.20436,188.89839 164.55104,189.05839 C 164.36437,189.05839 164.1777,189.05839 163.99104,189.05839 C 163.83103,189.08506 163.6577,189.09839 163.47104,189.09839 C 161.1777,189.09839 159.0577,188.37839 157.11104,186.93839 C 155.19104,185.49839 154.16438,183.1784 154.03104,179.97839 C 154.03104,179.95173 154.01771,179.92507 153.99104,179.89839 C 153.99104,179.84507 153.99104,179.79173 153.99104,179.73839 C 153.99104,179.68507 153.97771,179.64507 153.95104,179.61839 C 153.95104,179.56507 153.95104,179.52507 153.95104,179.49839 C 153.95104,176.75174 154.71104,174.60507 156.23104,173.05839 C 157.75104,171.51174 159.4177,170.53841 161.23104,170.13839 C 161.55103,170.05841 161.87103,170.00508 162.19104,169.97839 C 162.5377,169.92508 162.87103,169.89841 163.19104,169.89839 C 166.04436,169.89841 168.20436,170.59174 169.67104,171.97839 C 171.13769,173.33841 172.23102,174.9384 172.95104,176.77839 L 172.95104,176.73839"
style="font-size:40px;font-style:normal;font-variant:normal;font-weight:200;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bauhaus-Heavy-Bold;-inkscape-font-specification:Bauhaus-Heavy-Bold Ultra-Light"
Binary file images/splash.png has changed
Binary file locale/fr_FR/LC_MESSAGES/Beremiz.mo has changed
--- a/plugger.py Tue Oct 27 16:32:54 2009 +0100
+++ b/plugger.py Mon Nov 02 15:38:49 2009 +0100
@@ -74,7 +74,17 @@
# helper func to get path to images
def opjimg(imgname):
return os.path.join("images",imgname)
-
+
+# helper func to check path write permission
+def CheckPathPerm(path):
+ if path is None or not os.path.isdir(path):
+ return False
+ for root, dirs, files in os.walk(path):
+ for name in files:
+ if os.access(root, os.W_OK) is not True or os.access(os.path.join(root, name), os.W_OK) is not True:
+ return False
+ return True
+
class PlugTemplate:
"""
This class is the one that define plugins.
@@ -181,38 +191,39 @@
os.mkdir(self.PlugPath())
def PlugRequestSave(self):
- # If plugin do not have corresponding directory
- plugpath = self.PlugPath()
- if not os.path.isdir(plugpath):
- # Create it
- os.mkdir(plugpath)
-
- # generate XML for base XML parameters controller of the plugin
- if self.MandatoryParams:
- BaseXMLFile = open(self.PluginBaseXmlFilePath(),'w')
- BaseXMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
- BaseXMLFile.write(self.MandatoryParams[1].generateXMLText(self.MandatoryParams[0], 0))
- BaseXMLFile.close()
-
- # generate XML for XML parameters controller of the plugin
- if self.PlugParams:
- XMLFile = open(self.PluginXmlFilePath(),'w')
- XMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
- XMLFile.write(self.PlugParams[1].generateXMLText(self.PlugParams[0], 0))
- XMLFile.close()
-
- # Call the plugin specific OnPlugSave method
- result = self.OnPlugSave()
- if not result:
- return _("Error while saving \"%s\"\n")%self.PlugPath()
-
- # mark plugin as saved
- self.ChangesToSave = False
- # go through all childs and do the same
- for PlugChild in self.IterChilds():
- result = PlugChild.PlugRequestSave()
- if result:
- return result
+ if self.GetPlugRoot().CheckProjectPathPerm(False):
+ # If plugin do not have corresponding directory
+ plugpath = self.PlugPath()
+ if not os.path.isdir(plugpath):
+ # Create it
+ os.mkdir(plugpath)
+
+ # generate XML for base XML parameters controller of the plugin
+ if self.MandatoryParams:
+ BaseXMLFile = open(self.PluginBaseXmlFilePath(),'w')
+ BaseXMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
+ BaseXMLFile.write(self.MandatoryParams[1].generateXMLText(self.MandatoryParams[0], 0).encode("utf-8"))
+ BaseXMLFile.close()
+
+ # generate XML for XML parameters controller of the plugin
+ if self.PlugParams:
+ XMLFile = open(self.PluginXmlFilePath(),'w')
+ XMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
+ XMLFile.write(self.PlugParams[1].generateXMLText(self.PlugParams[0], 0).encode("utf-8"))
+ XMLFile.close()
+
+ # Call the plugin specific OnPlugSave method
+ result = self.OnPlugSave()
+ if not result:
+ return _("Error while saving \"%s\"\n")%self.PlugPath()
+
+ # mark plugin as saved
+ self.ChangesToSave = False
+ # go through all childs and do the same
+ for PlugChild in self.IterChilds():
+ result = PlugChild.PlugRequestSave()
+ if result:
+ return result
return None
def PlugImport(self, src_PlugPath):
@@ -690,7 +701,7 @@
"LREAL" : 8,
}
-import re
+import re, tempfile
import targets
import connectors
from discovery import DiscoveryDialog
@@ -764,7 +775,7 @@
self.PlugType = "Beremiz"
# After __init__ root plugin is not valid
self.ProjectPath = None
- self.BuildPath = None
+ self._setBuildPath(None)
self.DebugThread = None
self.debug_break = False
self.previous_plcstate = None
@@ -852,6 +863,23 @@
if path.startswith("BeremizRoot.TargetType.") and self.BeremizRoot.getTargetType().getcontent() is None:
self.BeremizRoot.setTargetType(self.GetDefaultTarget())
return PlugTemplate.SetParamsAttribute(self, path, value)
+
+ # helper func to check project path write permission
+ def CheckProjectPathPerm(self, dosave=True):
+ if CheckPathPerm(self.ProjectPath):
+ return True
+ dialog = wx.MessageDialog(self.AppFrame,
+ _('You must have permission to work on the project\nWork on a project copy ?'),
+ _('Error'),
+ wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
+ answer = dialog.ShowModal()
+ dialog.Destroy()
+ if answer == wx.ID_YES:
+ if self.SaveProjectAs():
+ self.AppFrame.RefreshAll()
+ self.AppFrame.RefreshTitle()
+ return True
+ return False
def NewProject(self, ProjectPath, BuildPath=None):
"""
@@ -879,7 +907,7 @@
self.PluggedChilds = {}
# Keep track of the root plugin (i.e. project path)
self.ProjectPath = ProjectPath
- self.BuildPath = BuildPath
+ self._setBuildPath(BuildPath)
# get plugins bloclist (is that usefull at project creation?)
self.RefreshPluginsBlockLists()
# this will create files base XML files
@@ -906,7 +934,7 @@
self.PluggedChilds = {}
# Keep track of the root plugin (i.e. project path)
self.ProjectPath = ProjectPath
- self.BuildPath = BuildPath
+ self._setBuildPath(BuildPath)
# If dir have already be made, and file exist
if os.path.isdir(self.PlugPath()) and os.path.isfile(self.PluginXmlFilePath()):
#Load the plugin.xml file into parameters members
@@ -930,11 +958,26 @@
self.ResetAppFrame(None)
def SaveProject(self):
- if not self.SaveXMLFile():
+ if self.CheckProjectPathPerm(False):
self.SaveXMLFile(os.path.join(self.ProjectPath, 'plc.xml'))
- result = self.PlugRequestSave()
- if result:
- self.logger.write_error(result)
+ result = self.PlugRequestSave()
+ if result:
+ self.logger.write_error(result)
+
+ def SaveProjectAs(self, dosave=True):
+ # Ask user to choose a path with write permissions
+ dirdialog = wx.DirDialog(self.AppFrame , _("Choose a directory to save project"), os.getenv("HOME"), wx.DD_NEW_DIR_BUTTON)
+ answer = dirdialog.ShowModal()
+ dirdialog.Destroy()
+ if answer == wx.ID_OK:
+ newprojectpath = dirdialog.GetPath()
+ if os.path.isdir(newprojectpath):
+ self.ProjectPath = newprojectpath
+ if dosave:
+ self.SaveProject()
+ self._setBuildPath(self.BuildPath)
+ return True
+ return False
# Update PLCOpenEditor Plugin Block types from loaded plugins
def RefreshPluginsBlockLists(self):
@@ -971,10 +1014,33 @@
def ParentsBlockTypesFactory(self):
return self.BlockTypesFactory()
+ def _setBuildPath(self, buildpath):
+ if CheckPathPerm(buildpath):
+ self.BuildPath = buildpath
+ else:
+ self.BuildPath = None
+ self.BuildPath = buildpath
+ self.DefaultBuildPath = None
+ if self._builder is not None:
+ self._builder.SetBuildPath(self._getBuildPath())
+
def _getBuildPath(self):
- if self.BuildPath is None:
- return os.path.join(self.ProjectPath, "build")
- return self.BuildPath
+ # BuildPath is defined by user
+ if self.BuildPath is not None:
+ return self.BuildPath
+ # BuildPath isn't defined by user but already created by default
+ if self.DefaultBuildPath is not None:
+ return self.DefaultBuildPath
+ # Create a build path in project folder if user has permissions
+ if CheckPathPerm(self.ProjectPath):
+ self.DefaultBuildPath = os.path.join(self.ProjectPath, "build")
+ # Create a build path in temp folder
+ else:
+ self.DefaultBuildPath = os.path.join(tempfile.mkdtemp(), os.path.basename(self.ProjectPath), "build")
+
+ if not os.path.exists(self.DefaultBuildPath):
+ os.makedirs(self.DefaultBuildPath)
+ return self.DefaultBuildPath
def _getExtraFilesPath(self):
return os.path.join(self._getBuildPath(), "extra_files")
@@ -1287,7 +1353,7 @@
"__publish_%s();"%locstrs[i-1] for i in xrange(len(locstrs), 0, -1)]),
"init_calls":"\n ".join([
"init_level=%d; "%(i+1)+
- "if(res = __init_%s(argc,argv)){"%locstr +
+ "if((res = __init_%s(argc,argv))){"%locstr +
#"printf(\"%s\"); "%locstr + #for debug
"return res;}" for i,locstr in enumerate(locstrs)]),
"cleanup_calls":"\n ".join([
--- a/plugins/c_ext/CFileEditor.py Tue Oct 27 16:32:54 2009 +0100
+++ b/plugins/c_ext/CFileEditor.py Mon Nov 02 15:38:49 2009 +0100
@@ -908,14 +908,12 @@
selected = self.PartsOpened.GetSelection()
if selected >= 0:
self.PartsOpened.DeletePage(selected)
- event.Skip()
def OnSaveMenu(self, event):
if getattr(self, "_onsave", None) != None:
self._onsave()
self.RefreshTitle()
self.RefreshEditMenu()
- event.Skip()
#-------------------------------------------------------------------------------
# Notebook Unified Functions
@@ -957,7 +955,6 @@
if selected != -1:
window = self.PartsOpened.GetPage(selected)
window.RefreshView()
- event.Skip()
def OnUndoMenu(self, event):
self.Controler.LoadPrevious()
@@ -967,7 +964,6 @@
window.RefreshView()
self.RefreshTitle()
self.RefreshEditMenu()
- event.Skip()
def OnRedoMenu(self, event):
self.Controler.LoadNext()
@@ -977,7 +973,6 @@
window.RefreshView()
self.RefreshTitle()
self.RefreshEditMenu()
- event.Skip()
#-------------------------------------------------------------------------------
# CFile Editor Panels Management Functions
--- a/plugins/c_ext/c_ext.py Tue Oct 27 16:32:54 2009 +0100
+++ b/plugins/c_ext/c_ext.py Mon Nov 02 15:38:49 2009 +0100
@@ -222,14 +222,28 @@
_View = None
def _OpenView(self):
if not self._View:
- def _onclose():
- self._View = None
- def _onsave():
- self.GetPlugRoot().SaveProject()
- self._View = CFileEditor(self.GetPlugRoot().AppFrame, self)
- self._View._onclose = _onclose
- self._View._onsave = _onsave
- self._View.Show()
+ open_cfileeditor = True
+ has_permissions = self.GetPlugRoot().CheckProjectPathPerm()
+ if not has_permissions:
+ dialog = wx.MessageDialog(self.GetPlugRoot().AppFrame,
+ _("You don't have write permissions.\nOpen CFileEditor anyway ?"),
+ _("Open CFileEditor"),
+ wx.YES_NO|wx.ICON_QUESTION)
+ open_cfileeditor = dialog.ShowModal() == wx.ID_YES
+ dialog.Destroy()
+ if open_cfileeditor:
+ def _onclose():
+ self._View = None
+ if has_permissions:
+ def _onsave():
+ self.GetPlugRoot().SaveProject()
+ else:
+ def _onsave():
+ pass
+ self._View = CFileEditor(self.GetPlugRoot().AppFrame, self)
+ self._View._onclose = _onclose
+ self._View._onsave = _onsave
+ self._View.Show()
PluginMethods = [
{"bitmap" : os.path.join("images", "EditCfile"),
@@ -248,7 +262,7 @@
text += self.CFile.generateXMLText("CFile", 0, extras)
xmlfile = open(filepath,"w")
- xmlfile.write(text)
+ xmlfile.write(text.encode("utf-8"))
xmlfile.close()
self.CFileBuffer.CurrentSaved()
--- a/plugins/canfestival/canfestival.py Tue Oct 27 16:32:54 2009 +0100
+++ b/plugins/canfestival/canfestival.py Mon Nov 02 15:38:49 2009 +0100
@@ -100,16 +100,31 @@
_View = None
def _OpenView(self):
if not self._View:
- def _onclose():
- self._View = None
- def _onsave():
- self.GetPlugRoot().SaveProject()
- self._View = objdictedit(self.GetPlugRoot().AppFrame, self)
- # TODO redefine BusId when IEC channel change
- self._View.SetBusId(self.GetCurrentLocation())
- self._View._onclose = _onclose
- self._View._onsave = _onsave
- self._View.Show()
+ open_objdictedit = True
+ has_permissions = self.GetPlugRoot().CheckProjectPathPerm()
+ if not has_permissions:
+ dialog = wx.MessageDialog(self.GetPlugRoot().AppFrame,
+ _("You don't have write permissions.\nOpen ObjDictEdit anyway ?"),
+ _("Open ObjDictEdit"),
+ wx.YES_NO|wx.ICON_QUESTION)
+ open_objdictedit = dialog.ShowModal() == wx.ID_YES
+ dialog.Destroy()
+ if open_objdictedit:
+ def _onclose():
+ self._View = None
+ if has_permissions:
+ def _onsave():
+ self.GetPlugRoot().SaveProject()
+ else:
+ def _onsave():
+ pass
+
+ self._View = objdictedit(self.GetPlugRoot().AppFrame, self)
+ # TODO redefine BusId when IEC channel change
+ self._View.SetBusId(self.GetCurrentLocation())
+ self._View._onclose = _onclose
+ self._View._onsave = _onsave
+ self._View.Show()
PluginMethods = [
{"bitmap" : os.path.join("images", "NetworkEdit"),
@@ -185,16 +200,30 @@
_View = None
def _OpenView(self):
if not self._View:
- def _onclose():
- self._View = None
- def _onsave():
- self.GetPlugRoot().SaveProject()
- self._View = networkedit(self.GetPlugRoot().AppFrame, self)
- # TODO redefine BusId when IEC channel change
- self._View.SetBusId(self.GetCurrentLocation())
- self._View._onclose = _onclose
- self._View._onsave = _onsave
- self._View.Show()
+ open_networkedit = True
+ has_permissions = self.GetPlugRoot().CheckProjectPathPerm()
+ if not has_permissions:
+ dialog = wx.MessageDialog(self.GetPlugRoot().AppFrame,
+ _("You don't have write permissions.\nOpen NetworkEdit anyway ?"),
+ _("Open NetworkEdit"),
+ wx.YES_NO|wx.ICON_QUESTION)
+ open_networkedit = dialog.ShowModal() == wx.ID_YES
+ dialog.Destroy()
+ if open_networkedit:
+ def _onclose():
+ self._View = None
+ if has_permissions:
+ def _onsave():
+ self.GetPlugRoot().SaveProject()
+ else:
+ def _onsave():
+ pass
+ self._View = networkedit(self.GetPlugRoot().AppFrame, self)
+ # TODO redefine BusId when IEC channel change
+ self._View.SetBusId(self.GetCurrentLocation())
+ self._View._onclose = _onclose
+ self._View._onsave = _onsave
+ self._View.Show()
def _ShowMasterGenerated(self):
buildpath = self._getBuildPath()
--- a/plugins/python/PythonEditor.py Tue Oct 27 16:32:54 2009 +0100
+++ b/plugins/python/PythonEditor.py Mon Nov 02 15:38:49 2009 +0100
@@ -560,7 +560,6 @@
self._onsave()
self.RefreshTitle()
self.RefreshEditMenu()
- event.Skip()
def RefreshTitle(self):
title = _("PythonEditor")
@@ -577,19 +576,17 @@
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()
-
+
+
--- a/plugins/python/modules/svgui/pous.xml Tue Oct 27 16:32:54 2009 +0100
+++ b/plugins/python/modules/svgui/pous.xml Mon Nov 02 15:38:49 2009 +0100
@@ -3,7 +3,7 @@
xmlns="http://www.plcopen.org/xml/tc6.xsd"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xsi:schemaLocation="http://www.plcopen.org/xml/tc6.xsd">
- <fileHeader companyName="LOLITECH"
+ <fileHeader companyName="Beremiz"
productName="Beremiz"
productVersion="0.0"
creationDateTime="2008-12-14T16:53:26"/>
--- a/plugins/python/modules/svgui/svgui.py Tue Oct 27 16:32:54 2009 +0100
+++ b/plugins/python/modules/svgui/svgui.py Mon Nov 02 15:38:49 2009 +0100
@@ -98,6 +98,15 @@
def _StartInkscape(self):
svgfile = self._getSVGpath()
- if not os.path.isfile(svgfile):
- svgfile = None
- open_svg(svgfile)
+ open_inkscape = True
+ if not self.GetPlugRoot().CheckProjectPathPerm():
+ dialog = wx.MessageDialog(self.GetPlugRoot().AppFrame,
+ _("You don't have write permissions.\nOpen Inkscape anyway ?"),
+ _("Open Inkscape"),
+ wx.YES_NO|wx.ICON_QUESTION)
+ open_inkscape = dialog.ShowModal() == wx.ID_YES
+ dialog.Destroy()
+ if open_inkscape:
+ if not os.path.isfile(svgfile):
+ svgfile = None
+ open_svg(svgfile)
--- a/plugins/python/modules/wxglade_hmi/wxglade_hmi.py Tue Oct 27 16:32:54 2009 +0100
+++ b/plugins/python/modules/wxglade_hmi/wxglade_hmi.py Mon Nov 02 15:38:49 2009 +0100
@@ -100,16 +100,25 @@
def _editWXGLADE(self):
wxg_filename = self._getWXGLADEpath()
- if not os.path.exists(wxg_filename):
- hmi_name = self.BaseParams.getName()
- open(wxg_filename,"w").write("""<?xml version="1.0"?>
-<application path="" name="" class="" option="0" language="python" top_window="%(name)s" encoding="UTF-8" use_gettext="0" overwrite="0" use_new_namespace="1" for_version="2.8" is_template="0">
- <object class="%(class)s" name="%(name)s" base="EditFrame">
- <style>wxDEFAULT_FRAME_STYLE</style>
- <title>frame_1</title>
- </object>
-</application>
-""" % {"name": hmi_name, "class": "Class_%s" % hmi_name})
- if wx.Platform == '__WXMSW__':
- wxg_filename = "\"%s\""%wxg_filename
- self.launch_wxglade([wxg_filename])
+ open_wxglade = True
+ if not self.GetPlugRoot().CheckProjectPathPerm():
+ dialog = wx.MessageDialog(self.GetPlugRoot().AppFrame,
+ _("You don't have write permissions.\nOpen wxGlade anyway ?"),
+ _("Open wxGlade"),
+ wx.YES_NO|wx.ICON_QUESTION)
+ open_wxglade = dialog.ShowModal() == wx.ID_YES
+ dialog.Destroy()
+ if open_wxglade:
+ if not os.path.exists(wxg_filename):
+ hmi_name = self.BaseParams.getName()
+ open(wxg_filename,"w").write("""<?xml version="1.0"?>
+ <application path="" name="" class="" option="0" language="python" top_window="%(name)s" encoding="UTF-8" use_gettext="0" overwrite="0" use_new_namespace="1" for_version="2.8" is_template="0">
+ <object class="%(class)s" name="%(name)s" base="EditFrame">
+ <style>wxDEFAULT_FRAME_STYLE</style>
+ <title>frame_1</title>
+ </object>
+ </application>
+ """ % {"name": hmi_name, "class": "Class_%s" % hmi_name})
+ if wx.Platform == '__WXMSW__':
+ wxg_filename = "\"%s\""%wxg_filename
+ self.launch_wxglade([wxg_filename])
--- a/plugins/python/pous.xml Tue Oct 27 16:32:54 2009 +0100
+++ b/plugins/python/pous.xml Mon Nov 02 15:38:49 2009 +0100
@@ -3,7 +3,7 @@
xmlns="http://www.plcopen.org/xml/tc6.xsd"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xsi:schemaLocation="http://www.plcopen.org/xml/tc6.xsd">
- <fileHeader companyName="LOLITECH"
+ <fileHeader companyName="Beremiz"
productName="Beremiz"
productVersion="0.0"
creationDateTime="2008-12-14T16:53:26"/>
--- a/plugins/python/python.py Tue Oct 27 16:32:54 2009 +0100
+++ b/plugins/python/python.py Mon Nov 02 15:38:49 2009 +0100
@@ -141,14 +141,28 @@
_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()
+ open_pyeditor = True
+ has_permissions = self.GetPlugRoot().CheckProjectPathPerm()
+ if not has_permissions:
+ dialog = wx.MessageDialog(self.GetPlugRoot().AppFrame,
+ _("You don't have write permissions.\nOpen PythonEditor anyway ?"),
+ _("Open PythonEditor"),
+ wx.YES_NO|wx.ICON_QUESTION)
+ open_pyeditor = dialog.ShowModal() == wx.ID_YES
+ dialog.Destroy()
+ if open_pyeditor:
+ def _onclose():
+ self._View = None
+ if has_permissions:
+ def _onsave():
+ self.GetPlugRoot().SaveProject()
+ else:
+ def _onsave():
+ pass
+ self._View = PythonEditorFrame(self.GetPlugRoot().AppFrame, self)
+ self._View._onclose = _onclose
+ self._View._onsave = _onsave
+ self._View.Show()
def OnPlugSave(self):
filepath = self.PythonFileName()
@@ -160,7 +174,7 @@
text += self.PythonCode.generateXMLText("Python", 0, extras)
xmlfile = open(filepath,"w")
- xmlfile.write(text)
+ xmlfile.write(text.encode("utf-8"))
xmlfile.close()
self.PythonBuffer.CurrentSaved()
--- a/setup.py Tue Oct 27 16:32:54 2009 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-import os,sys,glob
-from distutils.core import setup
-
-
-install_dir=os.path.join("LOLITech","beremiz")
-
-data_files=[]
-os.getcwd()
-os.chdir(os.getcwd())
-
-def generate(base_dir):
- listfile=[]
- if base_dir == "":
- directory = "."
- else:
- directory = base_dir
- data_files.append((os.path.join(install_dir, base_dir), listfile))
-
- for element in os.listdir(directory):
- element_path=os.path.join(base_dir, element)
- if os.path.isdir(element_path):
- generate(element_path)
- elif os.path.isfile(element_path):
- listfile.append(element_path)
-
-generate("")
-
-
-setup(name='Beremiz',
- version='0.1',
- description='Open Source framework for automation',
- author='Edouard Tisserant, Laurent Bessard',
- author_email='edouard.tisserant@lolitech.fr,laurent.bessard@lolitech.fr,gregory.trelat@lolitech.fr',
- url='http://www.beremiz.org',
- license='GPL',
- windows=["Beremiz.py"],
- scripts=['beremiz_postinst.py'],
- data_files=data_files, # Add files to install
-)
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/Makefile/XSD Mon Nov 02 15:38:49 2009 +0100
@@ -0,0 +1,6 @@
+
+ <xsd:element name="Makefile">
+ <xsd:complexType>
+ %(toolchain_makefile)s
+ </xsd:complexType>
+ </xsd:element>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/Makefile/__init__.py Mon Nov 02 15:38:49 2009 +0100
@@ -0,0 +1,7 @@
+from .. import toolchain_makefile
+
+class Makefile_target(toolchain_makefile):
+ extension = ".ld"
+ DebugEnabled = False
+ def getBuilderLDFLAGS(self):
+ return toolchain_makefile.getBuilderLDFLAGS(self)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/Makefile/plc_Makefile_main.c Mon Nov 02 15:38:49 2009 +0100
@@ -0,0 +1,93 @@
+/**
+ * Yagarto specific code
+ **/
+
+//#include <stdio.h>
+
+/* provided by POUS.C */
+extern int common_ticktime__;
+
+void Target_GetTime(IEC_TIME*);
+
+long AtomicCompareExchange(long* atomicvar,long compared, long exchange)
+{
+ return 0;
+}
+
+void PLC_GetTime(IEC_TIME *CURRENT_TIME)
+{
+ /* Call target GetTime function */
+ Target_GetTime(CURRENT_TIME);
+}
+
+void PLC_SetTimer(long long next, long long period)
+{
+}
+
+int startPLC(int argc,char **argv)
+{
+ if(__init(argc,argv) == 0)
+ return 0;
+ else
+ return 1;
+}
+
+int TryEnterDebugSection(void)
+{
+ return 0;
+}
+
+void LeaveDebugSection(void)
+{
+}
+
+int stopPLC(void)
+{
+ __cleanup();
+ return 0;
+}
+
+extern unsigned long __tick;
+/* from plc_debugger.c */
+int WaitDebugData(void)
+{
+ return 0;
+}
+
+/* Called by PLC thread when debug_publish finished
+ * This is supposed to unlock debugger thread in WaitDebugData*/
+void InitiateDebugTransfer(void)
+{
+}
+
+void suspendDebug(void)
+{
+}
+
+void resumeDebug(void)
+{
+}
+
+/* from plc_python.c */
+int WaitPythonCommands(void)
+{
+ return 0;
+}
+
+/* Called by PLC thread on each new python command*/
+void UnBlockPythonCommands(void)
+{
+}
+
+int TryLockPython(void)
+{
+ return 0;
+}
+
+void UnLockPython(void)
+{
+}
+
+void LockPython(void)
+{
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/XSD_toolchain_makefile Mon Nov 02 15:38:49 2009 +0100
@@ -0,0 +1,6 @@
+
+ <xsd:attribute name="BuildPath" type="xsd:string" use="optional" default=""/>
+ <xsd:attribute name="Command" type="xsd:string" use="optional" default="make -C"/>
+ <xsd:attribute name="Arguments" type="xsd:string" use="optional" default="BEREMIZSRC=%(src)s BEREMIZCFLAGS=%(cflags)s USE_BEREMIZ=1 --quiet"/>
+ <xsd:attribute name="Rule" type="xsd:string" use="optional" default="all"/>
+
--- a/targets/__init__.py Tue Oct 27 16:32:54 2009 +0100
+++ b/targets/__init__.py Mon Nov 02 15:38:49 2009 +0100
@@ -74,4 +74,5 @@
filename = path.join(path.split(__file__)[0],name + ".c")
return open(filename).read()
-from toolchain_gcc import toolchain_gcc
\ No newline at end of file
+from toolchain_gcc import toolchain_gcc
+from toolchain_makefile import toolchain_makefile
\ No newline at end of file
--- a/targets/plc_common_main.c Tue Oct 27 16:32:54 2009 +0100
+++ b/targets/plc_common_main.c Mon Nov 02 15:38:49 2009 +0100
@@ -41,7 +41,7 @@
/*
* Retrieve input variables, run PLC and publish output variables
**/
-void __run()
+void __run(void)
{
__tick++;
if (greatest_tick_count__)
@@ -66,6 +66,7 @@
int __init(int argc,char **argv)
{
int res = 0;
+ init_level = 0;
setlocale(LC_NUMERIC, "C");
config_init__();
__init_debug();
@@ -75,7 +76,7 @@
/*
* Calls plugin cleanup proc.
**/
-void __cleanup()
+void __cleanup(void)
{
%(cleanup_calls)s
__cleanup_debug();
--- a/targets/plc_debug.c Tue Oct 27 16:32:54 2009 +0100
+++ b/targets/plc_debug.c Mon Nov 02 15:38:49 2009 +0100
@@ -51,17 +51,17 @@
struct_plcvar variable_table[%(variables_pointer_type_table_count)d];
-void __init_debug()
+void __init_debug(void)
{
%(variables_pointer_type_table_initializer)s
buffer_state = BUFFER_FREE;
}
-void __cleanup_debug()
+void __cleanup_debug(void)
{
}
-void __retrieve_debug()
+void __retrieve_debug(void)
{
}
@@ -71,7 +71,7 @@
extern void InitiateDebugTransfer(void);
extern unsigned long __tick;
-void __publish_debug()
+void __publish_debug(void)
{
/* Check there is no running debugger re-configuration */
if(TryEnterDebugSection()){
@@ -143,10 +143,11 @@
latest_subscription = subscription_table;
}
-void FreeDebugData()
+void FreeDebugData(void)
{
/* atomically mark buffer as free */
- long latest_state = AtomicCompareExchange(
+ long latest_state;
+ latest_state = AtomicCompareExchange(
&buffer_state,
BUFFER_BUSY,
BUFFER_FREE);
@@ -169,8 +170,8 @@
{
return old_cursor;
}else{
- printf("%%d > %%d\n", old_cursor - debug_buffer, BUFFER_SIZE);
- return NULL;
+ //printf("%%d > %%d\n", old_cursor - debug_buffer, BUFFER_SIZE);
+ return NULL;
}
}
*idx = -1;
--- a/targets/toolchain_gcc.py Tue Oct 27 16:32:54 2009 +0100
+++ b/targets/toolchain_gcc.py Mon Nov 02 15:38:49 2009 +0100
@@ -12,11 +12,8 @@
"""
def __init__(self, PluginsRootInstance):
self.PluginsRootInstance = PluginsRootInstance
- self.exe = PluginsRootInstance.GetProjectName() + self.extension
- self.buildpath = PluginsRootInstance._getBuildPath()
- self.exe_path = os.path.join(self.buildpath, self.exe)
- self.md5key = None
- self.srcmd5 = {}
+ self.buildpath = None
+ self.SetBuildPath(self.PluginsRootInstance._getBuildPath())
def getTarget(self):
target = self.PluginsRootInstance.BeremizRoot.getTargetType()
@@ -54,7 +51,15 @@
return open(self._GetMD5FileName(), "r").read()
except Exception, e:
return None
-
+
+ def SetBuildPath(self, buildpath):
+ if self.buildpath != buildpath:
+ self.buildpath = buildpath
+ self.exe = self.PluginsRootInstance.GetProjectName() + self.extension
+ self.exe_path = os.path.join(self.buildpath, self.exe)
+ self.md5key = None
+ self.srcmd5 = {}
+
def check_and_update_hash_and_deps(self, bn):
# Get latest computed hash and deps
oldhash, deps = self.srcmd5.get(bn,(None,[]))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/toolchain_makefile.py Mon Nov 02 15:38:49 2009 +0100
@@ -0,0 +1,42 @@
+import os, re, operator
+from wxPopen import ProcessLogger
+import hashlib, shutil
+from toolchain_gcc import toolchain_gcc
+
+includes_re = re.compile('\s*#include\s*["<]([^">]*)[">].*')
+
+class toolchain_makefile(toolchain_gcc):
+ """
+ This abstract class contains GCC specific code.
+ It cannot be used as this and should be inherited in a target specific
+ class such as target_linux or target_win32
+ """
+
+ def build(self):
+ srcfiles= []
+ cflags = []
+ for Location, CFilesAndCFLAGS, DoCalls in self.PluginsRootInstance.LocationCFilesAndCFLAGS:
+ # Get CFiles list to give it to makefile
+ for CFile, CFLAGS in CFilesAndCFLAGS:
+ CFileName = os.path.basename(CFile)
+ srcfiles.append(CFileName)
+ if CFLAGS not in cflags:
+ cflags.append(CFLAGS)
+
+ beremizcommand = {"src": ' '.join(srcfiles),
+ "cflags": ' '.join(cflags)
+ }
+
+ target = self.getTarget().getcontent()["value"]
+ command = target.getCommand().split(' ') +\
+ [target.getBuildPath()] +\
+ [arg % beremizcommand for arg in target.getArguments().split(' ')] +\
+ target.getRule().split(' ')
+
+ # Call Makefile to build PLC code and link it with target specific code
+ status, result, err_result = ProcessLogger(self.PluginsRootInstance.logger,
+ command).spin()
+ if status :
+ self.PluginsRootInstance.logger.write_error(_("C compilation of %s failed.\n"))
+ return False
+ return True
--- a/wxPopen.py Tue Oct 27 16:32:54 2009 +0100
+++ b/wxPopen.py Mon Nov 02 15:38:49 2009 +0100
@@ -69,16 +69,20 @@
class ProcessLogger:
def __init__(self, logger, Command, finish_callback=None, no_stdout=False, no_stderr=False, no_gui=True):
self.logger = logger
- self.Command_str = Command
- self.Command = []
- for i,word in enumerate(Command.replace("'",'"').split('"')):
- if i % 2 == 0:
- word = word.strip()
- if len(word) > 0:
- self.Command.extend(word.split())
- else:
- self.Command.append(word)
-
+ if not isinstance(Command, list):
+ self.Command_str = Command
+ self.Command = []
+ for i,word in enumerate(Command.replace("'",'"').split('"')):
+ if i % 2 == 0:
+ word = word.strip()
+ if len(word) > 0:
+ self.Command.extend(word.split())
+ else:
+ self.Command.append(word)
+ else:
+ self.Command = Command
+ self.Command_str = subprocess.list2cmdline(self.Command)
+
self.finish_callback = finish_callback
self.no_stdout = no_stdout
self.no_stderr = no_stderr
@@ -95,6 +99,7 @@
"stdin":subprocess.PIPE,
"stdout":subprocess.PIPE,
"stderr":subprocess.PIPE}
+
if no_gui == True and wx.Platform == '__WXMSW__':
self.startupinfo = subprocess.STARTUPINFO()
self.startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW