lbessard@0: #!/usr/bin/env python lbessard@0: # -*- coding: utf-8 -*- lbessard@0: lbessard@3: #This file is part of Beremiz, a Integrated Development Environment for lbessard@3: #programming IEC 61131-3 automates supporting plcopen standard and CanFestival. lbessard@0: # lbessard@3: #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD lbessard@0: # lbessard@0: #See COPYING file for copyrights details. lbessard@0: # lbessard@0: #This library is free software; you can redistribute it and/or lbessard@0: #modify it under the terms of the GNU General Public lbessard@0: #License as published by the Free Software Foundation; either lbessard@0: #version 2.1 of the License, or (at your option) any later version. lbessard@0: # lbessard@0: #This library is distributed in the hope that it will be useful, lbessard@0: #but WITHOUT ANY WARRANTY; without even the implied warranty of lbessard@0: #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU lbessard@3: #General Public License for more details. lbessard@0: # lbessard@0: #You should have received a copy of the GNU General Public lbessard@0: #License along with this library; if not, write to the Free Software lbessard@0: #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA lbessard@0: etisserant@13: __version__ = "$Revision$" etisserant@13: lbessard@0: import wx lbessard@65: import wx.lib.buttons lbessard@5: lbessard@17: import types lbessard@0: etisserant@48: import time etisserant@48: lbessard@1: import os, re, platform, sys, time, traceback, getopt, commands etisserant@20: lbessard@17: from plugger import PluginsRoot lbessard@0: etisserant@48: from wxPopen import wxPopen3 etisserant@48: lbessard@1: class LogPseudoFile: lbessard@1: """ Base class for file like objects to facilitate StdOut for the Shell.""" lbessard@1: def __init__(self, output = None): etisserant@7: self.red_white = wx.TextAttr("RED", "WHITE") etisserant@7: self.red_yellow = wx.TextAttr("RED", "YELLOW") etisserant@7: self.black_white = wx.TextAttr("BLACK", "WHITE") etisserant@7: self.default_style = None lbessard@1: self.output = output lbessard@1: lbessard@1: def writelines(self, l): lbessard@1: map(self.write, l) lbessard@1: etisserant@22: def write(self, s, style = None): etisserant@22: if not style : style=self.black_white etisserant@22: if self.default_style != style: etisserant@22: self.output.SetDefaultStyle(style) etisserant@22: self.default_style = style etisserant@7: self.output.AppendText(s) etisserant@7: etisserant@7: def write_warning(self, s): etisserant@22: self.write(s,self.red_white) etisserant@7: etisserant@7: def write_error(self, s): etisserant@22: self.write(s,self.red_yellow) lbessard@1: lbessard@1: def flush(self): lbessard@1: self.output.SetValue("") lbessard@1: lbessard@1: def isatty(self): lbessard@1: return false lbessard@1: etisserant@48: def LogCommand(self, Command, sz_limit = 100, no_stdout=False): etisserant@48: self.errlen = 0 etisserant@48: self.exitcode = None etisserant@48: self.outdata = "" etisserant@48: self.errdata = "" etisserant@48: etisserant@48: def output(v): etisserant@48: self.outdata += v etisserant@48: if not no_stdout: etisserant@48: self.write(v) etisserant@48: etisserant@48: def errors(v): etisserant@48: self.errdata += v etisserant@48: self.errlen += 1 etisserant@48: if self.errlen > sz_limit: etisserant@48: p.kill() etisserant@48: self.write_warning(v) etisserant@48: etisserant@48: def fin(pid,ecode): etisserant@48: self.exitcode = ecode etisserant@48: if self.exitcode != 0: etisserant@49: self.write(Command + "\n") etisserant@49: self.write_warning("exited with status %d (pid %d)\n"%(ecode,pid)) etisserant@48: etisserant@48: def spin(p): etisserant@48: while not p.finished: etisserant@48: wx.Yield() etisserant@48: time.sleep(0.01) etisserant@48: etisserant@48: input = [] etisserant@48: p = wxPopen3(Command, input, output, errors, fin, self.output) etisserant@48: spin(p) etisserant@48: etisserant@48: return (self.exitcode, self.outdata, self.errdata) etisserant@20: lbessard@17: [ID_BEREMIZ, ID_BEREMIZMAINSPLITTER, lbessard@17: ID_BEREMIZSECONDSPLITTER, ID_BEREMIZLEFTPANEL, lbessard@17: ID_BEREMIZPARAMSPANEL, ID_BEREMIZLOGCONSOLE, lbessard@17: ID_BEREMIZPLUGINTREE, ID_BEREMIZPLUGINCHILDS, lbessard@17: ID_BEREMIZADDBUTTON, ID_BEREMIZDELETEBUTTON, lbessard@17: ID_BEREMIZPARAMSSTATICBOX, ID_BEREMIZPARAMSENABLE, lbessard@17: ID_BEREMIZPARAMSTARGETTYPE, ID_BEREMIZPARAMSIECCHANNEL, lbessard@17: ID_BEREMIZPARAMSSTATICTEXT1, ID_BEREMIZPARAMSSTATICTEXT2, lbessard@17: ID_BEREMIZPARAMSATTRIBUTESGRID, lbessard@17: ] = [wx.NewId() for _init_ctrls in range(17)] lbessard@0: lbessard@4: [ID_BEREMIZFILEMENUITEMS0, ID_BEREMIZFILEMENUITEMS1, lbessard@4: ID_BEREMIZFILEMENUITEMS2, ID_BEREMIZFILEMENUITEMS3, lbessard@4: ID_BEREMIZFILEMENUITEMS5, ID_BEREMIZFILEMENUITEMS7, lbessard@0: ] = [wx.NewId() for _init_coll_FileMenu_Items in range(6)] lbessard@0: lbessard@4: [ID_BEREMIZEDITMENUITEMS0, ID_BEREMIZEDITMENUITEMS2, lbessard@4: ID_BEREMIZEDITMENUITEMS3, lbessard@0: ] = [wx.NewId() for _init_coll_EditMenu_Items in range(3)] lbessard@0: lbessard@4: [ID_BEREMIZRUNMENUITEMS0, ID_BEREMIZRUNMENUITEMS2, lbessard@4: ID_BEREMIZRUNMENUITEMS3, ID_BEREMIZRUNMENUITEMS5, lbessard@0: ] = [wx.NewId() for _init_coll_EditMenu_Items in range(4)] lbessard@0: lbessard@4: [ID_BEREMIZHELPMENUITEMS0, ID_BEREMIZHELPMENUITEMS1, lbessard@0: ] = [wx.NewId() for _init_coll_HelpMenu_Items in range(2)] lbessard@0: lbessard@0: class Beremiz(wx.Frame): lbessard@0: lbessard@0: def _init_coll_FileMenu_Items(self, parent): lbessard@4: parent.Append(help='', id=ID_BEREMIZFILEMENUITEMS0, lbessard@0: kind=wx.ITEM_NORMAL, text=u'New\tCTRL+N') lbessard@4: parent.Append(help='', id=ID_BEREMIZFILEMENUITEMS1, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Open\tCTRL+O') lbessard@4: parent.Append(help='', id=ID_BEREMIZFILEMENUITEMS2, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Save\tCTRL+S') lbessard@4: parent.Append(help='', id=ID_BEREMIZFILEMENUITEMS3, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Close Project') lbessard@0: parent.AppendSeparator() lbessard@4: parent.Append(help='', id=ID_BEREMIZFILEMENUITEMS5, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Properties') lbessard@0: parent.AppendSeparator() lbessard@4: parent.Append(help='', id=ID_BEREMIZFILEMENUITEMS7, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Quit\tCTRL+Q') lbessard@0: self.Bind(wx.EVT_MENU, self.OnNewProjectMenu, lbessard@4: id=ID_BEREMIZFILEMENUITEMS0) lbessard@0: self.Bind(wx.EVT_MENU, self.OnOpenProjectMenu, lbessard@4: id=ID_BEREMIZFILEMENUITEMS1) lbessard@0: self.Bind(wx.EVT_MENU, self.OnSaveProjectMenu, lbessard@4: id=ID_BEREMIZFILEMENUITEMS2) lbessard@0: self.Bind(wx.EVT_MENU, self.OnCloseProjectMenu, lbessard@4: id=ID_BEREMIZFILEMENUITEMS3) lbessard@0: self.Bind(wx.EVT_MENU, self.OnPropertiesMenu, lbessard@4: id=ID_BEREMIZFILEMENUITEMS5) lbessard@0: self.Bind(wx.EVT_MENU, self.OnQuitMenu, lbessard@4: id=ID_BEREMIZFILEMENUITEMS7) lbessard@0: lbessard@0: def _init_coll_EditMenu_Items(self, parent): lbessard@4: parent.Append(help='', id=ID_BEREMIZEDITMENUITEMS0, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Edit PLC\tCTRL+R') lbessard@0: parent.AppendSeparator() lbessard@4: parent.Append(help='', id=ID_BEREMIZEDITMENUITEMS2, lbessard@17: kind=wx.ITEM_NORMAL, text=u'Add Plugin') lbessard@4: parent.Append(help='', id=ID_BEREMIZEDITMENUITEMS3, lbessard@17: kind=wx.ITEM_NORMAL, text=u'Delete Plugin') lbessard@0: self.Bind(wx.EVT_MENU, self.OnEditPLCMenu, lbessard@4: id=ID_BEREMIZEDITMENUITEMS0) lbessard@17: self.Bind(wx.EVT_MENU, self.OnAddMenu, lbessard@4: id=ID_BEREMIZEDITMENUITEMS2) lbessard@17: self.Bind(wx.EVT_MENU, self.OnDeleteMenu, lbessard@4: id=ID_BEREMIZEDITMENUITEMS3) lbessard@0: lbessard@0: def _init_coll_RunMenu_Items(self, parent): lbessard@4: parent.Append(help='', id=ID_BEREMIZRUNMENUITEMS0, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Build\tCTRL+R') lbessard@0: parent.AppendSeparator() lbessard@4: parent.Append(help='', id=ID_BEREMIZRUNMENUITEMS2, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Simulate') lbessard@4: parent.Append(help='', id=ID_BEREMIZRUNMENUITEMS3, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Run') lbessard@0: parent.AppendSeparator() lbessard@4: parent.Append(help='', id=ID_BEREMIZRUNMENUITEMS5, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Save Log') lbessard@1: self.Bind(wx.EVT_MENU, self.OnBuildMenu, lbessard@4: id=ID_BEREMIZRUNMENUITEMS0) lbessard@0: self.Bind(wx.EVT_MENU, self.OnSimulateMenu, lbessard@4: id=ID_BEREMIZRUNMENUITEMS2) lbessard@0: self.Bind(wx.EVT_MENU, self.OnRunMenu, lbessard@4: id=ID_BEREMIZRUNMENUITEMS3) lbessard@0: self.Bind(wx.EVT_MENU, self.OnSaveLogMenu, lbessard@4: id=ID_BEREMIZRUNMENUITEMS5) lbessard@0: lbessard@0: def _init_coll_HelpMenu_Items(self, parent): lbessard@4: parent.Append(help='', id=ID_BEREMIZHELPMENUITEMS0, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Beremiz\tF1') lbessard@4: parent.Append(help='', id=ID_BEREMIZHELPMENUITEMS1, lbessard@0: kind=wx.ITEM_NORMAL, text=u'About') lbessard@0: self.Bind(wx.EVT_MENU, self.OnBeremizMenu, lbessard@4: id=ID_BEREMIZHELPMENUITEMS0) lbessard@0: self.Bind(wx.EVT_MENU, self.OnAboutMenu, lbessard@4: id=ID_BEREMIZHELPMENUITEMS1) lbessard@0: lbessard@0: def _init_coll_menuBar1_Menus(self, parent): lbessard@0: parent.Append(menu=self.FileMenu, title=u'File') etisserant@28: #parent.Append(menu=self.EditMenu, title=u'Edit') etisserant@28: #parent.Append(menu=self.RunMenu, title=u'Run') lbessard@0: parent.Append(menu=self.HelpMenu, title=u'Help') lbessard@0: lbessard@0: def _init_utils(self): lbessard@0: self.menuBar1 = wx.MenuBar() lbessard@0: self.FileMenu = wx.Menu(title=u'') etisserant@28: #self.EditMenu = wx.Menu(title=u'') etisserant@28: #self.RunMenu = wx.Menu(title=u'') lbessard@0: self.HelpMenu = wx.Menu(title=u'') lbessard@0: lbessard@0: self._init_coll_menuBar1_Menus(self.menuBar1) lbessard@0: self._init_coll_FileMenu_Items(self.FileMenu) etisserant@28: #self._init_coll_EditMenu_Items(self.EditMenu) etisserant@28: #self._init_coll_RunMenu_Items(self.RunMenu) lbessard@0: self._init_coll_HelpMenu_Items(self.HelpMenu) lbessard@0: lbessard@17: def _init_coll_LeftGridSizer_Items(self, parent): lbessard@17: parent.AddWindow(self.PluginTree, 0, border=0, flag=wx.GROW) lbessard@17: parent.AddSizer(self.ButtonGridSizer, 0, border=0, flag=wx.GROW) lbessard@17: lbessard@17: def _init_coll_LeftGridSizer_Growables(self, parent): lbessard@0: parent.AddGrowableCol(0) lbessard@0: parent.AddGrowableRow(0) lbessard@0: lbessard@17: def _init_coll_ButtonGridSizer_Items(self, parent): lbessard@17: parent.AddWindow(self.PluginChilds, 0, border=0, flag=wx.GROW) lbessard@17: parent.AddWindow(self.AddButton, 0, border=0, flag=0) lbessard@17: parent.AddWindow(self.DeleteButton, 0, border=0, flag=0) lbessard@17: lbessard@17: def _init_coll_ButtonGridSizer_Growables(self, parent): lbessard@17: parent.AddGrowableCol(0) lbessard@17: parent.AddGrowableRow(0) lbessard@0: lbessard@0: def _init_sizers(self): lbessard@17: self.LeftGridSizer = wx.FlexGridSizer(cols=1, hgap=2, rows=2, vgap=2) lbessard@17: self.ButtonGridSizer = wx.FlexGridSizer(cols=3, hgap=2, rows=1, vgap=2) lbessard@19: self.ParamsPanelMainSizer = wx.BoxSizer(wx.VERTICAL) lbessard@17: lbessard@17: self._init_coll_LeftGridSizer_Growables(self.LeftGridSizer) lbessard@17: self._init_coll_LeftGridSizer_Items(self.LeftGridSizer) lbessard@17: self._init_coll_ButtonGridSizer_Growables(self.ButtonGridSizer) lbessard@17: self._init_coll_ButtonGridSizer_Items(self.ButtonGridSizer) lbessard@17: lbessard@17: self.LeftPanel.SetSizer(self.LeftGridSizer) lbessard@17: self.ParamsPanel.SetSizer(self.ParamsPanelMainSizer) lbessard@0: lbessard@0: def _init_ctrls(self, prnt): lbessard@4: wx.Frame.__init__(self, id=ID_BEREMIZ, name=u'Beremiz', lbessard@17: parent=prnt, pos=wx.Point(0, 0), size=wx.Size(1000, 600), lbessard@25: style=wx.DEFAULT_FRAME_STYLE|wx.CLIP_CHILDREN, title=u'Beremiz') lbessard@0: self._init_utils() lbessard@17: self.SetClientSize(wx.Size(1000, 600)) lbessard@0: self.SetMenuBar(self.menuBar1) lbessard@62: self.Bind(wx.EVT_ACTIVATE, self.OnFrameActivated) lbessard@0: lbessard@17: self.MainSplitter = wx.SplitterWindow(id=ID_BEREMIZMAINSPLITTER, lbessard@17: name='MainSplitter', parent=self, point=wx.Point(0, 0), lbessard@17: size=wx.Size(0, 0), style=wx.SP_3D) lbessard@17: self.MainSplitter.SetNeedUpdating(True) lbessard@17: self.MainSplitter.SetMinimumPaneSize(1) lbessard@17: lbessard@17: self.LeftPanel = wx.Panel(id=ID_BEREMIZLEFTPANEL, lbessard@17: name='LeftPanel', parent=self.MainSplitter, pos=wx.Point(0, 0), lbessard@17: size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) lbessard@17: lbessard@17: self.PluginTree = wx.TreeCtrl(id=ID_BEREMIZPLUGINTREE, lbessard@17: name='PluginTree', parent=self.LeftPanel, pos=wx.Point(0, 0), lbessard@17: size=wx.Size(-1, -1), style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER) lbessard@17: self.PluginTree.Bind(wx.EVT_RIGHT_UP, self.OnPluginTreeRightUp) lbessard@17: self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnPluginTreeItemSelected, lbessard@17: id=ID_BEREMIZPLUGINTREE) lbessard@17: lbessard@17: self.PluginChilds = wx.Choice(id=ID_BEREMIZPLUGINCHILDS, lbessard@17: name='PluginChilds', parent=self.LeftPanel, pos=wx.Point(0, 0), lbessard@17: size=wx.Size(-1, -1), style=0) lbessard@17: lbessard@65: self.AddButton = wx.lib.buttons.GenBitmapButton(ID=ID_BEREMIZADDBUTTON, bitmap=wx.Bitmap(os.path.join('images', 'Add.png')), lbessard@17: name='AddBusButton', parent=self.LeftPanel, pos=wx.Point(0, 0), lbessard@65: size=wx.Size(32, 32), style=wx.NO_BORDER) lbessard@65: self.AddButton.SetToolTipString("Add a plugin of the type selected") lbessard@17: self.AddButton.Bind(wx.EVT_BUTTON, self.OnAddButton, lbessard@17: id=ID_BEREMIZADDBUTTON) lbessard@17: lbessard@65: self.DeleteButton = wx.lib.buttons.GenBitmapButton(ID=ID_BEREMIZDELETEBUTTON, bitmap=wx.Bitmap(os.path.join('images', 'Delete.png')), lbessard@17: name='DeleteBusButton', parent=self.LeftPanel, pos=wx.Point(0, 0), lbessard@65: size=wx.Size(32, 32), style=wx.NO_BORDER) lbessard@65: self.DeleteButton.SetToolTipString("Delete the current selected plugin") lbessard@17: self.DeleteButton.Bind(wx.EVT_BUTTON, self.OnDeleteButton, lbessard@17: id=ID_BEREMIZDELETEBUTTON) lbessard@17: lbessard@17: self.SecondSplitter = wx.SplitterWindow(id=ID_BEREMIZSECONDSPLITTER, lbessard@17: name='SecondSplitter', parent=self.MainSplitter, point=wx.Point(0, 0), lbessard@17: size=wx.Size(0, 0), style=wx.SP_3D) lbessard@17: self.SecondSplitter.SetNeedUpdating(True) lbessard@17: self.SecondSplitter.SetMinimumPaneSize(1) lbessard@17: lbessard@17: self.MainSplitter.SplitVertically(self.LeftPanel, self.SecondSplitter, lbessard@17: 300) lbessard@17: lbessard@19: self.ParamsPanel = wx.ScrolledWindow(id=ID_BEREMIZPARAMSPANEL, lbessard@17: name='ParamsPanel', parent=self.SecondSplitter, pos=wx.Point(0, 0), lbessard@21: size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) lbessard@21: self.ParamsPanel.SetScrollbars(10, 10, 0, 0, 0, 0) lbessard@19: lbessard@4: self.LogConsole = wx.TextCtrl(id=ID_BEREMIZLOGCONSOLE, value='', lbessard@17: name='LogConsole', parent=self.SecondSplitter, pos=wx.Point(0, 0), etisserant@7: size=wx.Size(0, 0), style=wx.TE_MULTILINE|wx.TE_RICH2) lbessard@4: lbessard@17: self.SecondSplitter.SplitHorizontally(self.ParamsPanel, self.LogConsole, lbessard@17: -250) lbessard@0: lbessard@0: self._init_sizers() etisserant@13: etisserant@13: def __init__(self, parent, projectOpen): lbessard@0: self._init_ctrls(parent) lbessard@0: lbessard@17: self.Log = LogPseudoFile(self.LogConsole) lbessard@17: etisserant@20: self.PluginRoot = PluginsRoot(self) lbessard@17: lbessard@17: if projectOpen: etisserant@24: self.PluginRoot.LoadProject(projectOpen, self.Log) lbessard@17: self.RefreshPluginTree() etisserant@49: self.PluginTree.SelectItem(self.PluginTree.GetRootItem()) lbessard@17: lbessard@17: self.RefreshPluginParams() lbessard@0: self.RefreshButtons() lbessard@0: self.RefreshMainMenu() lbessard@62: lbessard@62: def OnFrameActivated(self, event): lbessard@62: if not event.GetActive(): lbessard@62: self.PluginRoot.RefreshPluginsBlockLists() lbessard@62: lbessard@0: def RefreshButtons(self): lbessard@17: if self.PluginRoot.HasProjectOpened(): lbessard@17: self.PluginChilds.Enable(True) lbessard@17: self.AddButton.Enable(True) lbessard@17: self.DeleteButton.Enable(True) lbessard@0: else: lbessard@17: self.PluginChilds.Enable(False) lbessard@17: self.AddButton.Enable(False) lbessard@17: self.DeleteButton.Enable(False) lbessard@17: lbessard@0: def RefreshMainMenu(self): lbessard@0: if self.menuBar1: lbessard@17: if self.PluginRoot.HasProjectOpened(): lbessard@42: ## self.menuBar1.EnableTop(1, True) lbessard@42: ## self.menuBar1.EnableTop(2, True) lbessard@17: self.FileMenu.Enable(ID_BEREMIZFILEMENUITEMS2, True) lbessard@17: self.FileMenu.Enable(ID_BEREMIZFILEMENUITEMS3, True) lbessard@17: self.FileMenu.Enable(ID_BEREMIZFILEMENUITEMS5, True) lbessard@17: else: lbessard@42: ## self.menuBar1.EnableTop(1, False) lbessard@42: ## self.menuBar1.EnableTop(2, False) lbessard@4: self.FileMenu.Enable(ID_BEREMIZFILEMENUITEMS2, False) lbessard@4: self.FileMenu.Enable(ID_BEREMIZFILEMENUITEMS3, False) lbessard@4: self.FileMenu.Enable(ID_BEREMIZFILEMENUITEMS5, False) lbessard@17: lbessard@17: def RefreshPluginTree(self): lbessard@17: infos = self.PluginRoot.GetPlugInfos() lbessard@17: root = self.PluginTree.GetRootItem() lbessard@21: if not root.IsOk(): lbessard@21: root = self.PluginTree.AddRoot(infos["name"]) etisserant@33: last_selected = self.GetSelectedPluginName() lbessard@21: self.GenerateTreeBranch(root, infos, True) lbessard@17: self.PluginTree.Expand(self.PluginTree.GetRootItem()) lbessard@46: self.SelectedPluginByName(root, last_selected) lbessard@17: self.RefreshPluginParams() lbessard@17: etisserant@33: def SelectedPluginByName(self, root, name): lbessard@46: if name: lbessard@46: toks = name.split('.',1) lbessard@46: item, root_cookie = self.PluginTree.GetFirstChild(root) lbessard@46: while item.IsOk(): lbessard@46: if self.PluginTree.GetPyData(item) == toks[0]: lbessard@46: if len(toks)>1: lbessard@46: return self.SelectedPluginByName(item, toks[1]) lbessard@46: else: lbessard@46: self.PluginTree.SelectItem(item, True) lbessard@46: return True lbessard@46: item, root_cookie = self.PluginTree.GetNextChild(root, root_cookie) etisserant@33: return False etisserant@33: lbessard@21: def GenerateTreeBranch(self, root, infos, first = False): lbessard@17: to_delete = [] lbessard@21: self.PluginTree.SetItemText(root, infos["name"]) lbessard@17: self.PluginTree.SetPyData(root, infos["type"]) lbessard@17: item, root_cookie = self.PluginTree.GetFirstChild(root) lbessard@21: for values in infos["values"]: lbessard@21: if not item.IsOk(): lbessard@21: item = self.PluginTree.AppendItem(root, "") lbessard@60: if wx.Platform != '__WXMSW__': lbessard@17: item, root_cookie = self.PluginTree.GetNextChild(root, root_cookie) lbessard@21: self.GenerateTreeBranch(item, values) lbessard@21: item, root_cookie = self.PluginTree.GetNextChild(root, root_cookie) lbessard@17: while item.IsOk(): lbessard@17: to_delete.append(item) lbessard@17: item, root_cookie = self.PluginTree.GetNextChild(root, root_cookie) lbessard@17: for item in to_delete: lbessard@17: self.PluginTree.Delete(item) lbessard@17: etisserant@33: def GetSelectedPluginName(self): lbessard@17: selected = self.PluginTree.GetSelection() lbessard@17: if not selected.IsOk(): lbessard@17: return None lbessard@17: if selected == self.PluginTree.GetRootItem(): etisserant@33: return "" etisserant@33: else: etisserant@33: name = self.PluginTree.GetPyData(selected) etisserant@33: item = self.PluginTree.GetItemParent(selected) etisserant@33: while item.IsOk() and item != self.PluginTree.GetRootItem(): etisserant@33: name = "%s.%s"%(self.PluginTree.GetPyData(item), name) etisserant@33: item = self.PluginTree.GetItemParent(item) etisserant@33: return name etisserant@33: etisserant@33: def GetSelectedPlugin(self): etisserant@33: name = self.GetSelectedPluginName() etisserant@36: if name is None: etisserant@33: return None etisserant@33: elif name == "": lbessard@17: return self.PluginRoot lbessard@17: else: lbessard@17: return self.PluginRoot.GetChildByName(name) lbessard@17: lbessard@17: def OnPluginTreeItemSelected(self, event): lbessard@17: wx.CallAfter(self.RefreshPluginParams) lbessard@17: event.Skip() lbessard@17: lbessard@17: def _GetAddPluginFunction(self, name): lbessard@17: def OnPluginMenu(event): lbessard@17: self.AddPlugin(name) lbessard@17: event.Skip() lbessard@17: return OnPluginMenu lbessard@17: lbessard@17: def OnPluginTreeRightUp(self, event): lbessard@17: plugin = self.GetSelectedPlugin() lbessard@17: if plugin: lbessard@17: main_menu = wx.Menu(title='') lbessard@17: if len(plugin.PlugChildsTypes) > 0: lbessard@17: plugin_menu = wx.Menu(title='') lbessard@17: for name, XSDClass in self.GetSelectedPlugin().PlugChildsTypes: lbessard@17: new_id = wx.NewId() lbessard@17: plugin_menu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=name) lbessard@17: self.Bind(wx.EVT_MENU, self._GetAddPluginFunction(name), id=new_id) lbessard@17: main_menu.AppendMenu(-1, "Add", plugin_menu, '') lbessard@17: new_id = wx.NewId() lbessard@17: main_menu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text="Delete") lbessard@17: self.Bind(wx.EVT_MENU, self.OnDeleteButton, id=new_id) lbessard@17: rect = self.PluginTree.GetBoundingRect(self.PluginTree.GetSelection()) lbessard@17: self.PluginTree.PopupMenuXY(main_menu, rect.x + rect.width, rect.y) lbessard@17: event.Skip() lbessard@17: lbessard@17: def RefreshPluginParams(self): lbessard@17: plugin = self.GetSelectedPlugin() lbessard@17: if not plugin: lbessard@17: # Refresh ParamsPanel lbessard@17: self.ParamsPanel.Hide() lbessard@17: lbessard@17: # Refresh PluginChilds lbessard@17: self.PluginChilds.Clear() lbessard@17: self.PluginChilds.Enable(False) lbessard@17: self.AddButton.Enable(False) lbessard@17: self.DeleteButton.Enable(False) lbessard@17: else: lbessard@17: # Refresh ParamsPanel lbessard@17: self.ParamsPanel.Show() lbessard@19: infos = plugin.GetParamsAttributes() lbessard@25: if wx.VERSION >= (2, 7, 0): lbessard@25: self.ParamsPanelMainSizer.Clear(True) lbessard@25: else: lbessard@25: self.ClearSizer(self.ParamsPanelMainSizer) lbessard@25: if len(self.PluginRoot.PluginMethods) > 0: lbessard@25: boxsizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@25: self.ParamsPanelMainSizer.AddSizer(boxsizer, 0, border=5, flag=wx.GROW|wx.ALL) lbessard@65: for plugin_infos in self.PluginRoot.PluginMethods: lbessard@65: if "method" in plugin_infos: lbessard@25: id = wx.NewId() lbessard@65: if "bitmap" in plugin_infos: lbessard@65: button = wx.lib.buttons.GenBitmapTextButton(ID=id, parent=self.ParamsPanel, lbessard@65: bitmap=wx.Bitmap(plugin_infos["bitmap"]), label=plugin_infos["name"], lbessard@65: name=plugin_infos["name"], pos=wx.Point(0, 0), style=wx.BU_EXACTFIT|wx.NO_BORDER) lbessard@65: else: lbessard@65: button = wx.Button(id=id, label=plugin_infos["name"], lbessard@65: name=plugin_infos["name"], parent=self.ParamsPanel, lbessard@65: pos=wx.Point(0, 0), style=wx.BU_EXACTFIT) lbessard@65: button.SetToolTipString(plugin_infos["tooltip"]) lbessard@65: button.Bind(wx.EVT_BUTTON, self.GetButtonCallBackFunction(self.PluginRoot, plugin_infos["method"]), id=id) lbessard@25: boxsizer.AddWindow(button, 0, border=5, flag=wx.GROW|wx.RIGHT) lbessard@25: self.RefreshSizerElement(self.ParamsPanelMainSizer, infos, None, False) lbessard@25: if plugin != self.PluginRoot and len(plugin.PluginMethods) > 0: lbessard@21: boxsizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@21: self.ParamsPanelMainSizer.AddSizer(boxsizer, 0, border=5, flag=wx.GROW|wx.ALL) lbessard@65: for plugin_infos in plugin.PluginMethods: lbessard@65: if "method" in plugin_infos: lbessard@21: id = wx.NewId() lbessard@65: if "bitmap" in plugin_infos: lbessard@65: button = wx.lib.buttons.GenBitmapTextButton(ID=id, parent=self.ParamsPanel, lbessard@65: bitmap=wx.Bitmap(plugin_infos["bitmap"]), label=plugin_infos["name"], lbessard@65: name=plugin_infos["name"], pos=wx.Point(0, 0), style=wx.BU_EXACTFIT|wx.NO_BORDER) lbessard@65: else: lbessard@65: button = wx.Button(id=id, label=plugin_infos["name"], lbessard@65: name=plugin_infos["name"], parent=self.ParamsPanel, lbessard@65: pos=wx.Point(0, 0), style=wx.BU_EXACTFIT) lbessard@65: button.SetToolTipString(plugin_infos["tooltip"]) lbessard@65: button.Bind(wx.EVT_BUTTON, self.GetButtonCallBackFunction(plugin, plugin_infos["method"]), id=id) lbessard@21: boxsizer.AddWindow(button, 0, border=5, flag=wx.GROW|wx.RIGHT) lbessard@17: self.ParamsPanelMainSizer.Layout() lbessard@62: self.ParamsPanel.SetClientSize(self.ParamsPanel.GetClientSize()) lbessard@17: lbessard@17: # Refresh PluginChilds lbessard@17: self.PluginChilds.Clear() lbessard@17: if len(plugin.PlugChildsTypes) > 0: lbessard@17: self.PluginChilds.Append("") lbessard@17: for name, XSDClass in plugin.PlugChildsTypes: lbessard@17: self.PluginChilds.Append(name) lbessard@17: self.PluginChilds.Enable(True) lbessard@17: self.AddButton.Enable(True) lbessard@17: else: lbessard@17: self.PluginChilds.Enable(False) lbessard@17: self.AddButton.Enable(False) lbessard@17: self.DeleteButton.Enable(True) lbessard@17: lbessard@21: def GetButtonCallBackFunction(self, plugin, method): lbessard@21: def OnButtonClick(event): lbessard@21: method(plugin, self.Log) lbessard@21: event.Skip() lbessard@21: return OnButtonClick lbessard@21: lbessard@19: def GetChoiceCallBackFunction(self, choicectrl, path): lbessard@19: def OnChoiceChanged(event): lbessard@19: plugin = self.GetSelectedPlugin() lbessard@19: if plugin: etisserant@28: res, StructChanged = plugin.SetParamsAttribute(path, choicectrl.GetStringSelection(), self.Log) etisserant@28: if StructChanged: wx.CallAfter(self.RefreshPluginTree) etisserant@28: choicectrl.SetStringSelection(res) lbessard@19: event.Skip() lbessard@19: return OnChoiceChanged lbessard@19: lbessard@19: def GetChoiceContentCallBackFunction(self, choicectrl, staticboxsizer, path): lbessard@19: def OnChoiceContentChanged(event): lbessard@19: plugin = self.GetSelectedPlugin() lbessard@19: if plugin: etisserant@28: res, StructChanged = plugin.SetParamsAttribute(path, choicectrl.GetStringSelection(), self.Log) etisserant@28: if StructChanged: wx.CallAfter(self.RefreshPluginTree) etisserant@28: choicectrl.SetStringSelection(res) lbessard@19: infos = self.PluginRoot.GetParamsAttributes(path) lbessard@19: staticbox = staticboxsizer.GetStaticBox() lbessard@19: staticbox.SetLabel("%(name)s - %(value)s"%infos) lbessard@21: self.ParamsPanel.Freeze() lbessard@19: self.RefreshSizerElement(staticboxsizer, infos["children"], "%s.%s"%(path, infos["name"])) lbessard@19: self.ParamsPanelMainSizer.Layout() lbessard@21: self.ParamsPanel.Thaw() lbessard@21: self.ParamsPanel.Refresh() lbessard@19: event.Skip() lbessard@19: return OnChoiceContentChanged lbessard@19: lbessard@19: def GetTextCtrlCallBackFunction(self, textctrl, path): lbessard@19: def OnTextCtrlChanged(event): lbessard@19: plugin = self.GetSelectedPlugin() lbessard@19: if plugin: etisserant@28: res, StructChanged = plugin.SetParamsAttribute(path, textctrl.GetValue(), self.Log) etisserant@28: if StructChanged: wx.CallAfter(self.RefreshPluginTree) etisserant@28: textctrl.SetValue(res) lbessard@19: event.Skip() lbessard@19: return OnTextCtrlChanged lbessard@19: etisserant@28: def GetCheckBoxCallBackFunction(self, chkbx, path): lbessard@19: def OnCheckBoxChanged(event): lbessard@19: plugin = self.GetSelectedPlugin() lbessard@19: if plugin: etisserant@28: res, StructChanged = plugin.SetParamsAttribute(path, chkbx.IsChecked(), self.Log) etisserant@28: if StructChanged: wx.CallAfter(self.RefreshPluginTree) etisserant@28: chkbx.SetValue(res) lbessard@19: event.Skip() lbessard@19: return OnCheckBoxChanged lbessard@19: lbessard@19: def ClearSizer(self, sizer): lbessard@19: staticboxes = [] lbessard@19: for item in sizer.GetChildren(): lbessard@19: if item.IsSizer(): lbessard@19: item_sizer = item.GetSizer() lbessard@19: self.ClearSizer(item_sizer) lbessard@19: if isinstance(item_sizer, wx.StaticBoxSizer): lbessard@19: staticboxes.append(item_sizer.GetStaticBox()) lbessard@19: sizer.Clear(True) lbessard@19: for staticbox in staticboxes: lbessard@19: staticbox.Destroy() lbessard@19: lbessard@25: def RefreshSizerElement(self, sizer, elements, path, clean = True): lbessard@25: if clean: lbessard@62: sizer.Clear(True) lbessard@19: first = True lbessard@19: for element_infos in elements: lbessard@19: if path: lbessard@19: element_path = "%s.%s"%(path, element_infos["name"]) lbessard@19: else: lbessard@19: element_path = element_infos["name"] lbessard@19: if isinstance(element_infos["type"], types.ListType): lbessard@19: boxsizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@19: if first: lbessard@19: sizer.AddSizer(boxsizer, 0, border=5, flag=wx.GROW|wx.ALL) lbessard@19: else: lbessard@19: sizer.AddSizer(boxsizer, 0, border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM) lbessard@65: bitmappath = os.path.join("images", "%s.png"%element_infos["name"]) lbessard@65: if os.path.isfile(bitmappath): lbessard@65: staticbitmap = wx.StaticBitmap(id=-1, bitmap=wx.Bitmap(bitmappath), lbessard@65: name="%s_bitmap"%element_infos["name"], parent=self.ParamsPanel, lbessard@65: pos=wx.Point(0, 0), size=wx.Size(24, 24), style=0) lbessard@65: boxsizer.AddWindow(staticbitmap, 0, border=5, flag=wx.RIGHT) lbessard@19: statictext = wx.StaticText(id=-1, label="%s:"%element_infos["name"], lbessard@19: name="%s_label"%element_infos["name"], parent=self.ParamsPanel, lbessard@19: pos=wx.Point(0, 0), size=wx.Size(100, 17), style=0) lbessard@19: boxsizer.AddWindow(statictext, 0, border=0, flag=0) lbessard@19: id = wx.NewId() lbessard@19: choicectrl = wx.Choice(id=id, name=element_infos["name"], parent=self.ParamsPanel, lbessard@19: pos=wx.Point(0, 0), size=wx.Size(150, 25), style=0) lbessard@19: boxsizer.AddWindow(choicectrl, 0, border=0, flag=0) lbessard@19: choicectrl.Append("") lbessard@19: if len(element_infos["type"]) > 0 and isinstance(element_infos["type"][0], types.TupleType): lbessard@19: for choice, xsdclass in element_infos["type"]: lbessard@19: choicectrl.Append(choice) lbessard@19: staticbox = wx.StaticBox(id=-1, label="%(name)s - %(value)s"%element_infos, lbessard@19: name='%s_staticbox'%element_infos["name"], parent=self.ParamsPanel, lbessard@19: pos=wx.Point(0, 0), size=wx.Size(0, 0), style=0) lbessard@19: staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL) lbessard@19: sizer.AddSizer(staticboxsizer, 0, border=0, flag=wx.GROW) lbessard@19: self.RefreshSizerElement(staticboxsizer, element_infos["children"], element_path) lbessard@19: callback = self.GetChoiceContentCallBackFunction(choicectrl, staticboxsizer, element_path) lbessard@19: else: lbessard@19: for choice in element_infos["type"]: lbessard@19: choicectrl.Append(choice) lbessard@19: callback = self.GetChoiceCallBackFunction(choicectrl, element_path) etisserant@22: if element_infos["value"]: etisserant@22: choicectrl.SetStringSelection(element_infos["value"]) etisserant@28: choicectrl.Bind(wx.EVT_CHOICE, callback, id=id) lbessard@19: elif isinstance(element_infos["type"], types.DictType): lbessard@19: boxsizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@19: if first: lbessard@19: sizer.AddSizer(boxsizer, 0, border=5, flag=wx.GROW|wx.ALL) lbessard@19: else: lbessard@19: sizer.AddSizer(boxsizer, 0, border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM) lbessard@65: bitmappath = os.path.join("images", "%s.png"%element_infos["name"]) lbessard@65: if os.path.isfile(bitmappath): lbessard@65: staticbitmap = wx.StaticBitmap(id=-1, bitmap=wx.Bitmap(bitmappath), lbessard@65: name="%s_bitmap"%element_infos["name"], parent=self.ParamsPanel, lbessard@65: pos=wx.Point(0, 0), size=wx.Size(24, 24), style=0) lbessard@65: boxsizer.AddWindow(staticbitmap, 0, border=5, flag=wx.RIGHT) lbessard@19: statictext = wx.StaticText(id=-1, label="%s:"%element_infos["name"], lbessard@19: name="%s_label"%element_infos["name"], parent=self.ParamsPanel, lbessard@19: pos=wx.Point(0, 0), size=wx.Size(100, 17), style=0) lbessard@19: boxsizer.AddWindow(statictext, 0, border=0, flag=wx.TOP|wx.LEFT|wx.BOTTOM) lbessard@19: id = wx.NewId() etisserant@23: scmin = -(2**31) etisserant@23: scmax = 2**31-1 lbessard@19: if "min" in element_infos["type"]: etisserant@23: scmin = element_infos["type"]["min"] lbessard@19: if "max" in element_infos["type"]: etisserant@23: scmax = element_infos["type"]["max"] lbessard@19: spinctrl = wx.SpinCtrl(id=id, name=element_infos["name"], parent=self.ParamsPanel, etisserant@23: pos=wx.Point(0, 0), size=wx.Size(150, 25), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT) etisserant@23: spinctrl.SetRange(scmin,scmax) lbessard@19: boxsizer.AddWindow(spinctrl, 0, border=0, flag=0) etisserant@28: spinctrl.SetValue(element_infos["value"]) lbessard@19: spinctrl.Bind(wx.EVT_SPINCTRL, self.GetTextCtrlCallBackFunction(spinctrl, element_path), id=id) lbessard@19: elif element_infos["type"] == "element": lbessard@19: staticbox = wx.StaticBox(id=-1, label=element_infos["name"], lbessard@19: name='%s_staticbox'%element_infos["name"], parent=self.ParamsPanel, lbessard@19: pos=wx.Point(0, 0), size=wx.Size(0, 0), style=0) lbessard@19: staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL) lbessard@19: if first: lbessard@19: sizer.AddSizer(staticboxsizer, 0, border=0, flag=wx.GROW|wx.TOP) lbessard@19: else: lbessard@19: sizer.AddSizer(staticboxsizer, 0, border=0, flag=wx.GROW) lbessard@19: self.RefreshSizerElement(staticboxsizer, element_infos["children"], element_path) lbessard@19: else: lbessard@19: boxsizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@19: if first: lbessard@19: sizer.AddSizer(boxsizer, 0, border=5, flag=wx.GROW|wx.ALL) lbessard@19: else: lbessard@19: sizer.AddSizer(boxsizer, 0, border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM) lbessard@65: bitmappath = os.path.join("images", "%s.png"%element_infos["name"]) lbessard@65: if os.path.isfile(bitmappath): lbessard@65: staticbitmap = wx.StaticBitmap(id=-1, bitmap=wx.Bitmap(bitmappath), lbessard@65: name="%s_bitmap"%element_infos["name"], parent=self.ParamsPanel, lbessard@65: pos=wx.Point(0, 0), size=wx.Size(24, 24), style=0) lbessard@65: boxsizer.AddWindow(staticbitmap, 0, border=5, flag=wx.RIGHT) lbessard@19: statictext = wx.StaticText(id=-1, label="%s:"%element_infos["name"], lbessard@19: name="%s_label"%element_infos["name"], parent=self.ParamsPanel, lbessard@19: pos=wx.Point(0, 0), size=wx.Size(100, 17), style=0) lbessard@19: boxsizer.AddWindow(statictext, 0, border=0, flag=0) lbessard@19: id = wx.NewId() lbessard@19: if element_infos["type"] == "boolean": lbessard@19: checkbox = wx.CheckBox(id=id, name=element_infos["name"], parent=self.ParamsPanel, lbessard@19: pos=wx.Point(0, 0), size=wx.Size(17, 25), style=0) lbessard@19: boxsizer.AddWindow(checkbox, 0, border=0, flag=0) etisserant@28: checkbox.SetValue(element_infos["value"]) lbessard@19: checkbox.Bind(wx.EVT_CHECKBOX, self.GetCheckBoxCallBackFunction(checkbox, element_path), id=id) lbessard@19: elif element_infos["type"] in ["unsignedLong", "long","integer"]: etisserant@23: if element_infos["type"].startswith("unsigned"): etisserant@23: scmin = 0 etisserant@23: else: etisserant@23: scmin = -(2**31) etisserant@23: scmax = 2**31-1 lbessard@19: spinctrl = wx.SpinCtrl(id=id, name=element_infos["name"], parent=self.ParamsPanel, lbessard@19: pos=wx.Point(0, 0), size=wx.Size(150, 25), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT) etisserant@23: spinctrl.SetRange(scmin, scmax) lbessard@19: boxsizer.AddWindow(spinctrl, 0, border=0, flag=0) etisserant@28: spinctrl.SetValue(element_infos["value"]) lbessard@19: spinctrl.Bind(wx.EVT_SPINCTRL, self.GetTextCtrlCallBackFunction(spinctrl, element_path), id=id) lbessard@19: else: lbessard@19: textctrl = wx.TextCtrl(id=id, name=element_infos["name"], parent=self.ParamsPanel, etisserant@28: pos=wx.Point(0, 0), size=wx.Size(150, 25), style=wx.TE_PROCESS_ENTER) lbessard@19: boxsizer.AddWindow(textctrl, 0, border=0, flag=0) lbessard@19: textctrl.SetValue(str(element_infos["value"])) etisserant@28: textctrl.Bind(wx.EVT_TEXT_ENTER, self.GetTextCtrlCallBackFunction(textctrl, element_path), id=id) etisserant@28: textctrl.Bind(wx.EVT_KILL_FOCUS, self.GetTextCtrlCallBackFunction(textctrl, element_path)) lbessard@19: first = False lbessard@19: lbessard@0: def OnNewProjectMenu(self, event): lbessard@17: defaultpath = self.PluginRoot.GetProjectPath() etisserant@22: if not defaultpath: lbessard@0: defaultpath = os.getcwd() lbessard@4: dialog = wx.DirDialog(self , "Choose a project", defaultpath, wx.DD_NEW_DIR_BUTTON) lbessard@4: if dialog.ShowModal() == wx.ID_OK: lbessard@0: projectpath = dialog.GetPath() lbessard@0: dialog.Destroy() etisserant@20: res = self.PluginRoot.NewProject(projectpath) etisserant@20: if not res : etisserant@20: self.RefreshPluginTree() etisserant@20: self.RefreshButtons() etisserant@20: self.RefreshMainMenu() lbessard@0: else: etisserant@20: message = wx.MessageDialog(self, res, "ERROR", wx.OK|wx.ICON_ERROR) lbessard@0: message.ShowModal() lbessard@0: message.Destroy() lbessard@0: event.Skip() lbessard@0: lbessard@0: def OnOpenProjectMenu(self, event): lbessard@17: defaultpath = self.PluginRoot.GetProjectPath() etisserant@20: if not defaultpath: lbessard@0: defaultpath = os.getcwd() lbessard@4: dialog = wx.DirDialog(self , "Choose a project", defaultpath, wx.DD_NEW_DIR_BUTTON) lbessard@4: if dialog.ShowModal() == wx.ID_OK: lbessard@17: projectpath = dialog.GetPath() lbessard@17: if os.path.isdir(projectpath): etisserant@24: result = self.PluginRoot.LoadProject(projectpath, self.Log) lbessard@17: if not result: lbessard@17: self.RefreshPluginTree() lbessard@46: self.PluginTree.SelectItem(self.PluginTree.GetRootItem()) lbessard@17: self.RefreshButtons() lbessard@17: self.RefreshMainMenu() lbessard@17: else: lbessard@17: message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR) lbessard@17: message.ShowModal() lbessard@17: message.Destroy() lbessard@17: else: lbessard@17: message = wx.MessageDialog(self, "\"%s\" folder is not a valid Beremiz project\n"%projectpath, "Error", wx.OK|wx.ICON_ERROR) lbessard@17: message.ShowModal() lbessard@17: message.Destroy() lbessard@0: dialog.Destroy() lbessard@0: event.Skip() lbessard@0: lbessard@0: def OnCloseProjectMenu(self, event): lbessard@0: self.PLCManager = None lbessard@0: self.CurrentProjectPath = projectpath lbessard@0: self.RefreshButtons() lbessard@0: self.RefreshMainMenu() lbessard@0: event.Skip() lbessard@0: lbessard@0: def OnSaveProjectMenu(self, event): lbessard@17: if self.PluginRoot.HasProjectOpened(): lbessard@17: self.PluginRoot.SaveProject() lbessard@0: event.Skip() lbessard@0: lbessard@0: def OnPropertiesMenu(self, event): lbessard@0: event.Skip() lbessard@0: lbessard@0: def OnQuitMenu(self, event): lbessard@0: self.Close() lbessard@0: event.Skip() lbessard@0: lbessard@0: def OnEditPLCMenu(self, event): lbessard@0: self.EditPLC() lbessard@0: event.Skip() lbessard@0: lbessard@17: def OnAddMenu(self, event): lbessard@17: self.AddPlugin() lbessard@17: event.Skip() lbessard@17: lbessard@17: def OnDeleteMenu(self, event): lbessard@17: self.DeletePlugin() lbessard@0: event.Skip() lbessard@0: lbessard@1: def OnBuildMenu(self, event): etisserant@20: #self.BuildAutom() lbessard@1: event.Skip() lbessard@1: lbessard@0: def OnSimulateMenu(self, event): lbessard@0: event.Skip() lbessard@0: lbessard@0: def OnRunMenu(self, event): lbessard@0: event.Skip() lbessard@0: lbessard@0: def OnSaveLogMenu(self, event): lbessard@0: event.Skip() lbessard@0: lbessard@0: def OnBeremizMenu(self, event): lbessard@0: event.Skip() lbessard@0: lbessard@0: def OnAboutMenu(self, event): lbessard@0: event.Skip() lbessard@17: lbessard@17: def OnAddButton(self, event): lbessard@17: PluginType = self.PluginChilds.GetStringSelection() lbessard@17: if PluginType != "": lbessard@17: self.AddPlugin(PluginType) lbessard@17: event.Skip() lbessard@17: lbessard@17: def OnDeleteButton(self, event): lbessard@17: self.DeletePlugin() lbessard@0: event.Skip() lbessard@0: lbessard@0: def CloseEditor(self, bus_id): lbessard@0: if self.BusManagers.get(bus_id, None) != None: lbessard@0: self.BusManagers[bus_id]["Editor"] = None lbessard@0: lbessard@17: def AddPlugin(self, PluginType): lbessard@17: dialog = wx.TextEntryDialog(self, "Please enter a name for plugin:", "Add Plugin", "", wx.OK|wx.CANCEL) lbessard@4: if dialog.ShowModal() == wx.ID_OK: lbessard@17: PluginName = dialog.GetValue() lbessard@17: plugin = self.GetSelectedPlugin() etisserant@28: plugin.PlugAddChild(PluginName, PluginType, self.Log) lbessard@17: self.RefreshPluginTree() lbessard@0: dialog.Destroy() lbessard@0: lbessard@17: def DeletePlugin(self): etisserant@50: dialog = wx.MessageDialog(self,"Really delete plugin ?", "Remove plugin",wx.YES_NO|wx.NO_DEFAULT) etisserant@50: if dialog.ShowModal() == wx.ID_YES: etisserant@50: plugin = self.GetSelectedPlugin() etisserant@50: plugin.PlugRemove() etisserant@50: del plugin etisserant@50: self.RefreshPluginTree() etisserant@50: dialog.Destroy() etisserant@7: lbessard@0: #------------------------------------------------------------------------------- lbessard@0: # Exception Handler lbessard@0: #------------------------------------------------------------------------------- lbessard@0: lbessard@0: Max_Traceback_List_Size = 20 lbessard@0: lbessard@0: def Display_Exception_Dialog(e_type,e_value,e_tb): lbessard@0: trcbck_lst = [] lbessard@0: for i,line in enumerate(traceback.extract_tb(e_tb)): lbessard@0: trcbck = " " + str(i+1) + ". " lbessard@0: if line[0].find(os.getcwd()) == -1: lbessard@0: trcbck += "file : " + str(line[0]) + ", " lbessard@0: else: lbessard@0: trcbck += "file : " + str(line[0][len(os.getcwd()):]) + ", " lbessard@0: trcbck += "line : " + str(line[1]) + ", " + "function : " + str(line[2]) lbessard@0: trcbck_lst.append(trcbck) lbessard@0: lbessard@0: # Allow clicking.... lbessard@0: cap = wx.Window_GetCapture() lbessard@0: if cap: lbessard@0: cap.ReleaseMouse() lbessard@0: lbessard@0: dlg = wx.SingleChoiceDialog(None, lbessard@0: """ lbessard@0: An error happens. lbessard@0: lbessard@0: Click on OK for saving an error report. lbessard@0: lbessard@0: Please contact LOLITech at: lbessard@0: +33 (0)3 29 52 95 67 lbessard@0: bugs_Beremiz@lolitech.fr lbessard@0: lbessard@0: lbessard@0: Error: lbessard@0: """ + lbessard@0: str(e_type) + " : " + str(e_value), lbessard@0: "Error", lbessard@0: trcbck_lst) lbessard@0: try: lbessard@0: res = (dlg.ShowModal() == wx.ID_OK) lbessard@0: finally: lbessard@0: dlg.Destroy() lbessard@0: lbessard@0: return res lbessard@0: lbessard@0: def Display_Error_Dialog(e_value): lbessard@0: message = wxMessageDialog(None, str(e_value), "Error", wxOK|wxICON_ERROR) lbessard@0: message.ShowModal() lbessard@0: message.Destroy() lbessard@0: lbessard@0: def get_last_traceback(tb): lbessard@0: while tb.tb_next: lbessard@0: tb = tb.tb_next lbessard@0: return tb lbessard@0: lbessard@0: lbessard@0: def format_namespace(d, indent=' '): lbessard@0: return '\n'.join(['%s%s: %s' % (indent, k, repr(v)[:10000]) for k, v in d.iteritems()]) lbessard@0: lbessard@0: lbessard@0: ignored_exceptions = [] # a problem with a line in a module is only reported once per session lbessard@0: lbessard@5: def AddExceptHook(path, app_version='[No version]'):#, ignored_exceptions=[]): lbessard@0: lbessard@0: def handle_exception(e_type, e_value, e_traceback): lbessard@0: traceback.print_exception(e_type, e_value, e_traceback) # this is very helpful when there's an exception in the rest of this func lbessard@0: last_tb = get_last_traceback(e_traceback) lbessard@0: ex = (last_tb.tb_frame.f_code.co_filename, last_tb.tb_frame.f_lineno) lbessard@0: if str(e_value).startswith("!!!"): lbessard@0: Display_Error_Dialog(e_value) lbessard@0: elif ex not in ignored_exceptions: lbessard@0: result = Display_Exception_Dialog(e_type,e_value,e_traceback) lbessard@0: if result: lbessard@0: ignored_exceptions.append(ex) lbessard@0: info = { lbessard@0: 'app-title' : wx.GetApp().GetAppName(), # app_title lbessard@0: 'app-version' : app_version, lbessard@0: 'wx-version' : wx.VERSION_STRING, lbessard@0: 'wx-platform' : wx.Platform, lbessard@0: 'python-version' : platform.python_version(), #sys.version.split()[0], lbessard@0: 'platform' : platform.platform(), lbessard@0: 'e-type' : e_type, lbessard@0: 'e-value' : e_value, lbessard@0: 'date' : time.ctime(), lbessard@0: 'cwd' : os.getcwd(), lbessard@0: } lbessard@0: if e_traceback: lbessard@0: info['traceback'] = ''.join(traceback.format_tb(e_traceback)) + '%s: %s' % (e_type, e_value) lbessard@0: last_tb = get_last_traceback(e_traceback) lbessard@0: exception_locals = last_tb.tb_frame.f_locals # the locals at the level of the stack trace where the exception actually occurred lbessard@0: info['locals'] = format_namespace(exception_locals) lbessard@0: if 'self' in exception_locals: lbessard@0: info['self'] = format_namespace(exception_locals['self'].__dict__) lbessard@0: lbessard@0: output = open(path+os.sep+"bug_report_"+info['date'].replace(':','-').replace(' ','_')+".txt",'w') lbessard@0: lst = info.keys() lbessard@0: lst.sort() lbessard@0: for a in lst: lbessard@0: output.write(a+":\n"+str(info[a])+"\n\n") lbessard@0: lbessard@0: #sys.excepthook = lambda *args: wx.CallAfter(handle_exception, *args) lbessard@0: sys.excepthook = handle_exception lbessard@0: lbessard@0: if __name__ == '__main__': etisserant@13: def usage(): etisserant@13: print "\nUsage of Beremiz.py :" etisserant@13: print "\n %s [Projectpath]\n"%sys.argv[0] etisserant@13: etisserant@13: try: etisserant@13: opts, args = getopt.getopt(sys.argv[1:], "h", ["help"]) etisserant@13: except getopt.GetoptError: etisserant@13: # print help information and exit: etisserant@13: usage() etisserant@13: sys.exit(2) etisserant@13: etisserant@13: for o, a in opts: etisserant@13: if o in ("-h", "--help"): etisserant@13: usage() etisserant@13: sys.exit() etisserant@13: etisserant@13: if len(args) > 1: etisserant@13: usage() etisserant@13: sys.exit() etisserant@13: elif len(args) == 1: etisserant@13: projectOpen = args[0] etisserant@13: else: etisserant@13: projectOpen = None etisserant@13: lbessard@5: app = wx.PySimpleApp() lbessard@5: wx.InitAllImageHandlers() lbessard@0: lbessard@0: # Install a exception handle for bug reports lbessard@5: AddExceptHook(os.getcwd(),__version__) lbessard@0: etisserant@13: frame = Beremiz(None, projectOpen) lbessard@0: lbessard@0: frame.Show() lbessard@0: app.MainLoop()