# HG changeset patch # User edouard # Date 1257172729 -3600 # Node ID 75fe735972737ae06e1f48f60ec0c99674395e2d # Parent fcd344deae84e07960c432986239c1a3da7cf1cc# Parent 092060fd8afb1d950fe467724ce0209bddc48716 Merge with 092060fd8afb1d950fe467724ce0209bddc48716 diff -r fcd344deae84 -r 75fe73597273 Beremiz.py --- 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. diff -r fcd344deae84 -r 75fe73597273 TextCtrlAutoComplete.py --- 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) + diff -r fcd344deae84 -r 75fe73597273 beremiz_postinst.py --- 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() diff -r fcd344deae84 -r 75fe73597273 debian/Beremiz.directory --- /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 diff -r fcd344deae84 -r 75fe73597273 debian/Beremiz_demos.directory --- /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= diff -r fcd344deae84 -r 75fe73597273 debian/Beremiz_docs.directory --- /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= diff -r fcd344deae84 -r 75fe73597273 debian/README.Debian --- 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 diff -r fcd344deae84 -r 75fe73597273 debian/beremiz.desktop --- 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 diff -r fcd344deae84 -r 75fe73597273 debian/beremiz.menu --- /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 --> diff -r fcd344deae84 -r 75fe73597273 debian/beremiz_doc.desktop --- /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 diff -r fcd344deae84 -r 75fe73597273 debian/beremiz_svgui.desktop --- /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 + diff -r fcd344deae84 -r 75fe73597273 debian/beremiz_wxglade.desktop --- /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 + diff -r fcd344deae84 -r 75fe73597273 debian/changelog --- 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 diff -r fcd344deae84 -r 75fe73597273 debian/control --- 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. diff -r fcd344deae84 -r 75fe73597273 debian/rules --- 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 diff -r fcd344deae84 -r 75fe73597273 doc/about.html --- 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> diff -r fcd344deae84 -r 75fe73597273 i18n/Beremiz_fr_FR.po --- 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\"" diff -r fcd344deae84 -r 75fe73597273 i18n/app.fil --- 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 diff -r fcd344deae84 -r 75fe73597273 i18n/messages.pot --- 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 "" diff -r fcd344deae84 -r 75fe73597273 images/EditCfile.png Binary file images/EditCfile.png has changed diff -r fcd344deae84 -r 75fe73597273 images/HideVars.png Binary file images/HideVars.png has changed diff -r fcd344deae84 -r 75fe73597273 images/Maximize.png Binary file images/Maximize.png has changed diff -r fcd344deae84 -r 75fe73597273 images/Minimize.png Binary file images/Minimize.png has changed diff -r fcd344deae84 -r 75fe73597273 images/ShowIECcode.png Binary file images/ShowIECcode.png has changed diff -r fcd344deae84 -r 75fe73597273 images/ShowVars.png Binary file images/ShowVars.png has changed diff -r fcd344deae84 -r 75fe73597273 images/editIECrawcode.png Binary file images/editIECrawcode.png has changed diff -r fcd344deae84 -r 75fe73597273 images/editPYTHONcode.png Binary file images/editPYTHONcode.png has changed diff -r fcd344deae84 -r 75fe73597273 images/editWXGLADE.png Binary file images/editWXGLADE.png has changed diff -r fcd344deae84 -r 75fe73597273 images/icons.svg --- 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" diff -r fcd344deae84 -r 75fe73597273 images/splash.png Binary file images/splash.png has changed diff -r fcd344deae84 -r 75fe73597273 locale/fr_FR/LC_MESSAGES/Beremiz.mo Binary file locale/fr_FR/LC_MESSAGES/Beremiz.mo has changed diff -r fcd344deae84 -r 75fe73597273 plugger.py --- 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([ diff -r fcd344deae84 -r 75fe73597273 plugins/c_ext/CFileEditor.py --- 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 diff -r fcd344deae84 -r 75fe73597273 plugins/c_ext/c_ext.py --- 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() diff -r fcd344deae84 -r 75fe73597273 plugins/canfestival/canfestival.py --- 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() diff -r fcd344deae84 -r 75fe73597273 plugins/python/PythonEditor.py --- 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() - + + diff -r fcd344deae84 -r 75fe73597273 plugins/python/modules/svgui/pous.xml --- 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"/> diff -r fcd344deae84 -r 75fe73597273 plugins/python/modules/svgui/svgui.py --- 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) diff -r fcd344deae84 -r 75fe73597273 plugins/python/modules/wxglade_hmi/wxglade_hmi.py --- 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]) diff -r fcd344deae84 -r 75fe73597273 plugins/python/pous.xml --- 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"/> diff -r fcd344deae84 -r 75fe73597273 plugins/python/python.py --- 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() diff -r fcd344deae84 -r 75fe73597273 setup.py --- 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 diff -r fcd344deae84 -r 75fe73597273 targets/Makefile/XSD --- /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 diff -r fcd344deae84 -r 75fe73597273 targets/Makefile/__init__.py --- /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) diff -r fcd344deae84 -r 75fe73597273 targets/Makefile/plc_Makefile_main.c --- /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) +{ +} diff -r fcd344deae84 -r 75fe73597273 targets/XSD_toolchain_makefile --- /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"/> + diff -r fcd344deae84 -r 75fe73597273 targets/__init__.py --- 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 diff -r fcd344deae84 -r 75fe73597273 targets/plc_common_main.c --- 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(); diff -r fcd344deae84 -r 75fe73597273 targets/plc_debug.c --- 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; diff -r fcd344deae84 -r 75fe73597273 targets/toolchain_gcc.py --- 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,[])) diff -r fcd344deae84 -r 75fe73597273 targets/toolchain_makefile.py --- /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 diff -r fcd344deae84 -r 75fe73597273 wxPopen.py --- 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