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@82: if wx.VERSION >= (2, 8, 0): lbessard@82: import wx.lib.customtreectrl as CT 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@72: CWD = os.path.split(os.path.realpath(__file__))[0] lbessard@72: 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@89: if p.pid: etisserant@89: 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@67: def _init_coll_RightGridSizer_Items(self, parent): lbessard@67: parent.AddSizer(self.MenuSizer, 0, border=0, flag=wx.GROW) lbessard@71: if wx.VERSION < (2, 8, 0): lbessard@71: parent.AddWindow(self.SecondSplitter, 0, border=0, flag=wx.GROW) lbessard@71: else: lbessard@71: parent.AddWindow(self.ParamsPanel, 0, border=0, flag=wx.GROW) lbessard@67: lbessard@67: def _init_coll_RightGridSizer_Growables(self, parent): lbessard@67: parent.AddGrowableCol(0) lbessard@67: parent.AddGrowableRow(1) lbessard@67: lbessard@17: def _init_coll_ButtonGridSizer_Items(self, parent): lbessard@17: parent.AddWindow(self.PluginChilds, 0, border=0, flag=wx.GROW) lbessard@82: 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@82: self.LeftGridSizer = wx.FlexGridSizer(cols=1, hgap=2, rows=1, vgap=2) lbessard@82: self.ButtonGridSizer = wx.FlexGridSizer(cols=3, hgap=2, rows=1, vgap=2) lbessard@67: self.RightGridSizer = wx.FlexGridSizer(cols=1, hgap=2, rows=2, vgap=2) lbessard@76: self.MenuSizer = wx.BoxSizer(wx.VERTICAL) 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@82: self._init_coll_ButtonGridSizer_Growables(self.ButtonGridSizer) lbessard@82: self._init_coll_ButtonGridSizer_Items(self.ButtonGridSizer) lbessard@67: self._init_coll_RightGridSizer_Growables(self.RightGridSizer) lbessard@67: self._init_coll_RightGridSizer_Items(self.RightGridSizer) lbessard@17: lbessard@17: self.LeftPanel.SetSizer(self.LeftGridSizer) lbessard@67: self.RightPanel.SetSizer(self.RightGridSizer) 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@71: if wx.VERSION < (2, 8, 0): lbessard@71: self.MainSplitter = wx.SplitterWindow(id=ID_BEREMIZMAINSPLITTER, lbessard@71: name='MainSplitter', parent=self, point=wx.Point(0, 0), lbessard@71: size=wx.Size(0, 0), style=wx.SP_3D) lbessard@71: self.MainSplitter.SetNeedUpdating(True) lbessard@71: self.MainSplitter.SetMinimumPaneSize(1) lbessard@71: lbessard@71: self.LeftPanel = wx.Panel(id=ID_BEREMIZLEFTPANEL, lbessard@71: name='LeftPanel', parent=self.MainSplitter, pos=wx.Point(0, 0), lbessard@71: size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) lbessard@82: lbessard@82: self.PluginTree = wx.TreeCtrl(id=ID_BEREMIZPLUGINTREE, lbessard@82: name='PluginTree', parent=self.LeftPanel, pos=wx.Point(0, 0), lbessard@82: size=wx.Size(-1, -1), style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER) lbessard@82: self.PluginTree.Bind(wx.EVT_RIGHT_UP, self.OnPluginTreeRightUp) lbessard@82: self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnPluginTreeItemSelected, lbessard@82: id=ID_BEREMIZPLUGINTREE) lbessard@82: lbessard@82: self.PluginChilds = wx.Choice(id=ID_BEREMIZPLUGINCHILDS, lbessard@82: name='PluginChilds', parent=self.LeftPanel, pos=wx.Point(0, 0), lbessard@82: size=wx.Size(-1, -1), style=0) lbessard@82: lbessard@82: self.AddButton = wx.lib.buttons.GenBitmapButton(ID=ID_BEREMIZADDBUTTON, bitmap=wx.Bitmap(os.path.join(CWD, 'images', 'Add32x32.png')), lbessard@68: name='AddBusButton', parent=self.LeftPanel, pos=wx.Point(0, 0), lbessard@68: size=wx.Size(32, 32), style=wx.NO_BORDER) lbessard@82: self.AddButton.SetToolTipString("Add a plugin of the type selected") lbessard@82: self.AddButton.Bind(wx.EVT_BUTTON, self.OnAddButton, lbessard@82: id=ID_BEREMIZADDBUTTON) lbessard@82: self.DeleteButton = wx.lib.buttons.GenBitmapButton(ID=ID_BEREMIZDELETEBUTTON, bitmap=wx.Bitmap(os.path.join(CWD, 'images', 'Delete32x32.png')), lbessard@68: name='DeleteBusButton', parent=self.LeftPanel, pos=wx.Point(0, 0), lbessard@68: size=wx.Size(32, 32), style=wx.NO_BORDER) lbessard@82: self.DeleteButton.SetToolTipString("Delete the current selected plugin") lbessard@82: self.DeleteButton.Bind(wx.EVT_BUTTON, self.OnDeleteButton, lbessard@82: id=ID_BEREMIZDELETEBUTTON) lbessard@82: lbessard@71: self.RightPanel = wx.Panel(id=ID_BEREMIZLEFTPANEL, lbessard@71: name='RightPanel', parent=self.MainSplitter, pos=wx.Point(0, 0), lbessard@71: size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) lbessard@71: lbessard@71: self.SecondSplitter = wx.SplitterWindow(id=ID_BEREMIZSECONDSPLITTER, lbessard@71: name='SecondSplitter', parent=self.RightPanel, point=wx.Point(0, 0), lbessard@71: size=wx.Size(0, 0), style=wx.SP_3D) lbessard@71: self.SecondSplitter.SetNeedUpdating(True) lbessard@71: self.SecondSplitter.SetMinimumPaneSize(1) lbessard@71: lbessard@71: self.MainSplitter.SplitVertically(self.LeftPanel, self.RightPanel, lbessard@71: 300) lbessard@71: lbessard@71: self.ParamsPanel = wx.ScrolledWindow(id=ID_BEREMIZPARAMSPANEL, lbessard@71: name='ParamsPanel', parent=self.SecondSplitter, pos=wx.Point(0, 0), lbessard@71: size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) lbessard@71: self.ParamsPanel.SetScrollbars(10, 10, 0, 0, 0, 0) lbessard@71: lbessard@71: self.LogConsole = wx.TextCtrl(id=ID_BEREMIZLOGCONSOLE, value='', lbessard@71: name='LogConsole', parent=self.SecondSplitter, pos=wx.Point(0, 0), lbessard@71: size=wx.Size(0, 0), style=wx.TE_MULTILINE|wx.TE_RICH2) lbessard@71: lbessard@71: self.SecondSplitter.SplitHorizontally(self.ParamsPanel, self.LogConsole, lbessard@71: -250) lbessard@82: lbessard@82: self._init_sizers() lbessard@71: else: lbessard@82: self.AUIManager = wx.aui.AuiManager(self) lbessard@82: self.AUIManager.SetDockSizeConstraint(0.5, 0.5) lbessard@83: self.Panes = {} lbessard@82: lbessard@82: self.PluginTree = CT.CustomTreeCtrl(id=ID_BEREMIZPLUGINTREE, lbessard@82: name='PluginTree', parent=self, pos=wx.Point(0, 0), etisserant@93: size=wx.Size(-1, -1), style=CT.TR_HAS_BUTTONS|CT.TR_EDIT_LABELS|CT.TR_HAS_VARIABLE_ROW_HEIGHT|wx.TR_SINGLE|wx.SUNKEN_BORDER) lbessard@82: self.PluginTree.Bind(wx.EVT_RIGHT_UP, self.OnPluginTreeRightUp) etisserant@89: self.PluginTree.Bind(wx.EVT_IDLE, self.OnPluginTreeIdle) lbessard@82: self.Bind(CT.EVT_TREE_SEL_CHANGED, self.OnPluginTreeItemSelected, lbessard@82: id=ID_BEREMIZPLUGINTREE) lbessard@82: self.Bind(CT.EVT_TREE_ITEM_CHECKED, self.OnPluginTreeItemChecked, lbessard@82: id=ID_BEREMIZPLUGINTREE) lbessard@84: self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnPluginTreeItemBeginEdit, lbessard@84: id=ID_BEREMIZPLUGINTREE) lbessard@82: self.Bind(CT.EVT_TREE_END_LABEL_EDIT, self.OnPluginTreeItemEndEdit, lbessard@82: id=ID_BEREMIZPLUGINTREE) lbessard@82: self.Bind(CT.EVT_TREE_ITEM_EXPANDED, self.OnPluginTreeItemExpanded, lbessard@82: id=ID_BEREMIZPLUGINTREE) lbessard@82: self.Bind(CT.EVT_TREE_ITEM_COLLAPSED, self.OnPluginTreeItemCollapsed, lbessard@82: id=ID_BEREMIZPLUGINTREE) lbessard@82: lbessard@82: self.AUIManager.AddPane(self.PluginTree, wx.aui.AuiPaneInfo().CenterPane()) lbessard@71: lbessard@71: self.LogConsole = wx.TextCtrl(id=ID_BEREMIZLOGCONSOLE, value='', lbessard@71: name='LogConsole', parent=self, pos=wx.Point(0, 0), lbessard@71: size=wx.Size(0, 0), style=wx.TE_MULTILINE|wx.TE_RICH2) lbessard@82: self.AUIManager.AddPane(self.LogConsole, wx.aui.AuiPaneInfo().Caption("Log Console").Bottom().Layer(1).BestSize(wx.Size(800, 200)).CloseButton(False)) lbessard@82: lbessard@71: self.AUIManager.Update() 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@82: self.DisableEvents = False lbessard@17: lbessard@17: if projectOpen: etisserant@24: self.PluginRoot.LoadProject(projectOpen, self.Log) lbessard@17: self.RefreshPluginTree() etisserant@89: self.RefreshPluginToolBar() etisserant@49: self.PluginTree.SelectItem(self.PluginTree.GetRootItem()) lbessard@17: lbessard@82: if wx.VERSION < (2, 8, 0): lbessard@82: self.RefreshPluginParams() lbessard@82: self.RefreshButtons() lbessard@82: 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@82: if wx.VERSION < (2, 8, 0): lbessard@82: if self.PluginRoot.HasProjectOpened(): lbessard@82: self.PluginChilds.Enable(True) lbessard@82: self.AddButton.Enable(True) lbessard@82: self.DeleteButton.Enable(True) lbessard@82: else: lbessard@82: self.PluginChilds.Enable(False) lbessard@82: self.AddButton.Enable(False) lbessard@82: 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@82: self.DisableEvents = True lbessard@17: infos = self.PluginRoot.GetPlugInfos() lbessard@17: root = self.PluginTree.GetRootItem() lbessard@82: if root is None or 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@82: lbessard@82: if wx.VERSION < (2, 8, 0): lbessard@82: self.RefreshPluginParams() lbessard@82: lbessard@82: self.DisableEvents = False etisserant@89: self.MustRecalTreeSizes = True lbessard@17: etisserant@33: def SelectedPluginByName(self, root, name): lbessard@46: if name: lbessard@82: toks = name.split('.', 1) lbessard@46: item, root_cookie = self.PluginTree.GetFirstChild(root) lbessard@82: while item is not None and 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@82: lbessard@82: if wx.VERSION >= (2, 8, 0): lbessard@82: plugin = self.GetSelectedPlugin(root) lbessard@82: if plugin is not None: lbessard@82: old_window = self.PluginTree.GetItemWindow(root) lbessard@82: if old_window is not None: lbessard@82: old_window.GetSizer().Clear(True) lbessard@82: old_window.Destroy() lbessard@82: etisserant@89: outside = wx.Panel(self.PluginTree, -1, size=wx.Size(-1, -1)) etisserant@89: outside.SetBackgroundColour(wx.WHITE) etisserant@89: etisserant@93: insidesizer = wx.FlexGridSizer(cols=2,rows=1) etisserant@93: insidesizer.AddGrowableCol(1) etisserant@89: etisserant@89: outside.SetSizer(insidesizer) etisserant@93: etisserant@93: insidesizer.AddSpacer(-1) etisserant@89: etisserant@89: window = wx.Panel(outside, -1, size=wx.Size(-1, -1)) etisserant@89: window.SetBackgroundColour(wx.Colour(250,250,255)) etisserant@89: insidesizer.AddWindow(window, border=1, flag=wx.GROW|wx.ALL) etisserant@89: etisserant@89: tcsizer = wx.FlexGridSizer(cols=3, hgap=0, rows=1, vgap=0) etisserant@89: lbessard@82: if "channel" in infos: lbessard@82: sc = wx.SpinCtrl(window, -1, size=wx.Size(50, 25)) lbessard@82: sc.SetValue(infos["channel"]) lbessard@82: sc.Bind(wx.EVT_SPINCTRL, self.GetItemChannelChangedFunction(root)) lbessard@82: tcsizer.AddWindow(sc, 0, border=5, flag=wx.LEFT|wx.TOP|wx.BOTTOM|wx.ALIGN_CENTER) etisserant@89: etisserant@89: bsizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@82: lbessard@82: if "parent" in infos or plugin == self.PluginRoot: lbessard@82: addbutton_id = wx.NewId() lbessard@82: addbutton = wx.lib.buttons.GenBitmapButton(id=addbutton_id, bitmap=wx.Bitmap(os.path.join(CWD, 'images', 'Add24x24.png')), lbessard@82: name='AddBusButton', parent=window, pos=wx.Point(0, 0), lbessard@82: size=wx.Size(24, 24), style=wx.NO_BORDER) lbessard@82: addbutton.SetToolTipString("Add a plugin to this one") lbessard@87: addbutton.Bind(wx.EVT_BUTTON, self.GetAddButtonFunction(root, window), id=addbutton_id) etisserant@89: bsizer.AddWindow(addbutton, 0, border=5, flag=wx.LEFT|wx.RIGHT|wx.TOP|wx.BOTTOM|wx.ALIGN_CENTER) lbessard@82: lbessard@82: if plugin != self.PluginRoot: lbessard@82: deletebutton_id = wx.NewId() lbessard@82: deletebutton = wx.lib.buttons.GenBitmapButton(id=deletebutton_id, bitmap=wx.Bitmap(os.path.join(CWD, 'images', 'Delete24x24.png')), lbessard@82: name='DeleteBusButton', parent=window, pos=wx.Point(0, 0), lbessard@82: size=wx.Size(24, 24), style=wx.NO_BORDER) lbessard@82: deletebutton.SetToolTipString("Delete this plugin") lbessard@82: deletebutton.Bind(wx.EVT_BUTTON, self.GetDeleteButtonFunction(root), id=deletebutton_id) etisserant@89: bsizer.AddWindow(deletebutton, 0, border=5, flag=wx.RIGHT|wx.TOP|wx.BOTTOM|wx.ALIGN_CENTER) lbessard@82: etisserant@89: plugin_infos = plugin.GetParamsAttributes() etisserant@89: lbessard@82: psizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@94: self.RefreshSizerElement(window, psizer, plugin, plugin_infos, None, True, root) etisserant@89: etisserant@89: msizer = wx.BoxSizer(wx.VERTICAL) etisserant@89: msizer.AddSizer(bsizer, 0, border=0, flag=wx.GROW) etisserant@90: if len(plugin.PluginMethods) > 0: #and plugin != self.PluginRoot lbessard@82: for plugin_method in plugin.PluginMethods: lbessard@82: if "method" in plugin_method: lbessard@82: id = wx.NewId() etisserant@90: button = wx.lib.buttons.GenBitmapTextButton(id=id, parent=window, etisserant@93: bitmap=wx.Bitmap(os.path.join(CWD, "%s24x24.png"%plugin_method.get("bitmap", os.path.join("images", "Unknown")))), label=plugin_method["name"], etisserant@90: name=plugin_method["name"], pos=wx.DefaultPosition, style=wx.NO_BORDER) lbessard@82: button.SetToolTipString(plugin_method["tooltip"]) lbessard@82: button.Bind(wx.EVT_BUTTON, self.GetButtonCallBackFunction(plugin, plugin_method["method"]), id=id) etisserant@90: #hack to force size to mini etisserant@90: gen_mini_GetLabelSize = lambda obj:lambda:(wx.lib.buttons.GenBitmapTextButton._GetLabelSize(obj)[:-1] + (False,)) etisserant@90: button._GetLabelSize = gen_mini_GetLabelSize(button) etisserant@90: #button._GetLabelSize = lambda :(-1,-1,False) etisserant@90: msizer.AddWindow(button, 0, border=5, flag=0) etisserant@89: tcsizer.AddSizer(msizer, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL) etisserant@89: tcsizer.AddSizer(psizer, 0, border=0, flag=wx.GROW) etisserant@89: if plugin == self.PluginRoot: etisserant@89: tcsizer.AddGrowableCol(0) etisserant@89: else: etisserant@89: tcsizer.AddGrowableCol(1) etisserant@89: lbessard@82: window.SetSizer(tcsizer) etisserant@89: insidesizer.Fit(outside) etisserant@89: self.PluginTree.SetItemWindow(root, outside) lbessard@82: if "enabled" in infos: lbessard@82: self.PluginTree.CheckItem(root, infos["enabled"]) lbessard@82: self.PluginTree.SetItemWindowEnabled(root, infos["enabled"]) lbessard@82: lbessard@17: item, root_cookie = self.PluginTree.GetFirstChild(root) etisserant@90: for values in infos["values"]: lbessard@82: if item is None or not item.IsOk(): etisserant@89: item = self.PluginTree.AppendItem(root, "") etisserant@89: # 2.6.x returns bad item on gtk lbessard@83: if wx.Platform != '__WXMSW__' or wx.VERSION >= (2, 8, 0): 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@82: while item is not None and 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@89: MustRecalTreeSizes = False etisserant@89: def OnPluginTreeIdle(self,event): etisserant@89: if self.MustRecalTreeSizes: etisserant@93: self.ResizePluginTreeWindow() etisserant@89: event.RequestMore() etisserant@89: event.Skip() etisserant@89: etisserant@89: def ResizePluginTreeWindow(self): etisserant@89: if getattr(self, "PluginRoot", None): etisserant@89: root = self.PluginTree.GetRootItem() etisserant@89: if root is not None and root.IsOk(): etisserant@90: minimalsz = wx.Size(-1,-1) etisserant@93: minimalpos = wx.Point(-1,-1) etisserant@93: itemswindows = self.ResizePluginTreeWindow_r(root, minimalsz, minimalpos) etisserant@90: for window, posx in itemswindows: etisserant@93: spacer_width = minimalpos.x - posx etisserant@93: window.GetSizer().GetItem(0).SetSpacer(wx.Size(spacer_width,-1)) etisserant@93: window.SetSize(wx.Size(spacer_width + minimalsz.x, -1)) etisserant@93: window.GetSizer().Layout() etisserant@93: #wx.MessageBox(str(itemswindows) + "\n" + str(minimalpos) + "\n" + str(minimalsz) + "\n" + str(window.GetSizer().GetItem(0).GetSpacer())) etisserant@93: self.MustRecalTreeSizes = False etisserant@93: etisserant@93: def ResizePluginTreeWindow_r(self, root, sz, pt): etisserant@89: window = self.PluginTree.GetItemWindow(root) etisserant@90: posx = window.GetPosition().x etisserant@90: res = [(window,posx)] etisserant@93: window.GetSizer().GetItem(0).SetSpacer(wx.Size(0,0)) etisserant@90: bestsz = window.GetBestSize() etisserant@93: pt.x = max(pt.x, posx) etisserant@93: sz.x = max(sz.x, bestsz.x) etisserant@93: if root.IsExpanded(): etisserant@93: item, root_cookie = self.PluginTree.GetFirstChild(root) etisserant@93: while item is not None and item.IsOk() : etisserant@93: res.extend(self.ResizePluginTreeWindow_r(item, sz, pt)) etisserant@93: item, root_cookie = self.PluginTree.GetNextChild(root, root_cookie) etisserant@90: return res etisserant@89: lbessard@82: def GetSelectedPluginName(self, selected = None): lbessard@82: if selected is None: lbessard@82: selected = self.PluginTree.GetSelection() lbessard@82: if selected is None or 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: lbessard@82: def GetSelectedPlugin(self, selected = None): lbessard@82: name = self.GetSelectedPluginName(selected) 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@82: if wx.VERSION < (2, 8, 0): lbessard@82: wx.CallAfter(self.RefreshPluginParams) lbessard@82: event.Skip() lbessard@82: lbessard@82: def OnPluginTreeItemChecked(self, event): lbessard@82: if not self.DisableEvents: lbessard@82: item = event.GetItem() lbessard@82: plugin = self.GetSelectedPlugin(item) lbessard@82: if plugin: lbessard@82: res, StructChanged = plugin.SetParamsAttribute("BaseParams.Enabled", self.PluginTree.IsItemChecked(item), self.Log) lbessard@82: wx.CallAfter(self.RefreshPluginTree) lbessard@82: event.Skip() lbessard@82: lbessard@84: def OnPluginTreeItemBeginEdit(self, event): lbessard@84: if event.GetItem() == self.PluginTree.GetRootItem(): lbessard@84: event.Veto() lbessard@84: else: lbessard@84: event.Skip() lbessard@84: lbessard@82: def OnPluginTreeItemEndEdit(self, event): lbessard@82: if event.GetLabel() == "": lbessard@82: event.Veto() lbessard@82: elif not self.DisableEvents: lbessard@82: plugin = self.GetSelectedPlugin() lbessard@82: if plugin: lbessard@82: res, StructChanged = plugin.SetParamsAttribute("BaseParams.Name", event.GetLabel(), self.Log) lbessard@82: wx.CallAfter(self.RefreshPluginTree) lbessard@82: event.Skip() lbessard@82: lbessard@84: def ShowChildrenWindows(self, root, show = True): lbessard@84: item, root_cookie = self.PluginTree.GetFirstChild(root) lbessard@84: while item is not None and item.IsOk(): lbessard@84: window = self.PluginTree.GetItemWindow(item) lbessard@84: if show: lbessard@84: window.Show() lbessard@84: else: lbessard@84: window.Hide() lbessard@84: if self.PluginTree.IsExpanded(item): lbessard@84: self.ShowChildrenWindows(item, show) lbessard@84: item, root_cookie = self.PluginTree.GetNextChild(root, root_cookie) lbessard@84: lbessard@84: def OnPluginTreeItemExpanded(self, event): lbessard@84: self.ShowChildrenWindows(event.GetItem(), True) etisserant@89: self.MustRecalTreeSizes = True lbessard@84: event.Skip() lbessard@84: lbessard@84: def OnPluginTreeItemCollapsed(self, event): lbessard@84: self.ShowChildrenWindows(event.GetItem(), False) lbessard@84: event.Skip() lbessard@84: lbessard@82: def GetItemChannelChangedFunction(self, item): lbessard@82: def OnPluginTreeItemChannelChanged(event): lbessard@82: if not self.DisableEvents: lbessard@82: plugin = self.GetSelectedPlugin(item) lbessard@82: if plugin: lbessard@82: res, StructChanged = plugin.SetParamsAttribute("BaseParams.IEC_Channel", event.GetInt(), self.Log) lbessard@82: wx.CallAfter(self.RefreshPluginTree) lbessard@82: event.Skip() lbessard@82: return OnPluginTreeItemChannelChanged lbessard@82: lbessard@82: def _GetAddPluginFunction(self, name, selected = None): lbessard@17: def OnPluginMenu(event): lbessard@82: self.AddPlugin(name, selected) 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@82: for name, XSDClass in plugin.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@82: pos_x, pos_y = event.GetPosition() lbessard@82: self.PluginTree.PopupMenuXY(main_menu, pos_x, pos_y) lbessard@82: event.Skip() lbessard@82: lbessard@82: def RefreshPluginToolBar(self): lbessard@82: if wx.VERSION < (2, 8, 0): lbessard@82: self.ClearSizer(self.MenuSizer) lbessard@83: else: etisserant@90: # toolbar temporarely disabled. etisserant@90: return lbessard@83: if "ToolBar" in self.Panes: lbessard@83: self.AUIManager.DetachPane(self.Panes["ToolBar"]) lbessard@83: self.Panes["ToolBar"].Destroy() lbessard@82: if self.PluginRoot.HasOpenedProject() and len(self.PluginRoot.PluginMethods) > 0: lbessard@82: if wx.VERSION > (2, 8, 0): lbessard@82: toolbar = wx.ToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize, lbessard@82: wx.TB_FLAT | wx.TB_NODIVIDER | wx.NO_BORDER | wx.TB_TEXT) lbessard@83: toolbar.SetToolBitmapSize(wx.Size(48, 48)) lbessard@82: else: lbessard@82: boxsizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@87: width = 0 lbessard@82: for plugin_infos in self.PluginRoot.PluginMethods: lbessard@82: if "method" in plugin_infos: lbessard@82: id = wx.NewId() lbessard@82: if "bitmap" in plugin_infos: lbessard@82: if wx.VERSION < (2, 8, 0): lbessard@82: button = wx.lib.buttons.GenBitmapTextButton(ID=id, parent=self.RightPanel, lbessard@82: bitmap=wx.Bitmap(os.path.join(CWD, "%s32x32.png"%plugin_infos["bitmap"])), label=plugin_infos["name"], lbessard@82: name=plugin_infos["name"], pos=wx.Point(0, 0), style=wx.BU_EXACTFIT|wx.NO_BORDER) lbessard@82: else: lbessard@82: button = wx.lib.buttons.GenBitmapTextButton(id=id, parent=toolbar, lbessard@82: bitmap=wx.Bitmap(os.path.join(CWD, "%s32x32.png"%plugin_infos["bitmap"])), label=plugin_infos["name"], lbessard@82: name=plugin_infos["name"], pos=wx.Point(0, 0), style=wx.BU_EXACTFIT|wx.NO_BORDER) lbessard@82: button.SetSize(button.GetBestSize()) lbessard@82: else: lbessard@82: if wx.VERSION < (2, 8, 0): lbessard@82: button = wx.Button(id=id, label=plugin_infos["name"], lbessard@82: name=plugin_infos["name"], parent=self.RightPanel, lbessard@82: pos=wx.Point(0, 0), style=wx.BU_EXACTFIT) lbessard@82: else: lbessard@82: button = wx.Button(id=id, label=plugin_infos["name"], lbessard@82: name=plugin_infos["name"], parent=toolbar, lbessard@82: pos=wx.Point(0, 0), size=(-1, 48), style=wx.BU_EXACTFIT) lbessard@82: button.SetToolTipString(plugin_infos["tooltip"]) lbessard@82: button.Bind(wx.EVT_BUTTON, self.GetButtonCallBackFunction(self.PluginRoot, plugin_infos["method"]), id=id) lbessard@87: width += button.GetSize()[0] lbessard@82: if wx.VERSION < (2, 8, 0): lbessard@82: boxsizer.AddWindow(button, 0, border=5, flag=wx.GROW|wx.RIGHT) lbessard@82: else: lbessard@82: toolbar.AddControl(button) lbessard@82: if wx.VERSION < (2, 8, 0): lbessard@82: self.MenuSizer.AddSizer(boxsizer, 0, border=5, flag=wx.GROW|wx.ALL) lbessard@82: self.RightGridSizer.Layout() lbessard@82: else: lbessard@82: toolbar.Realize() lbessard@83: self.Panes["ToolBar"] = toolbar lbessard@82: self.AUIManager.AddPane(toolbar, wx.aui.AuiPaneInfo(). lbessard@82: Name("ToolBar").Caption("Toolbar"). lbessard@82: ToolbarPane().Top(). lbessard@82: LeftDockable(False).RightDockable(False)) lbessard@87: if wx.Platform == '__WXMSW__': lbessard@88: self.AUIManager.GetPane("ToolBar").BestSize(wx.Size(width + 3, 55)) lbessard@82: self.AUIManager.Update() 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@82: if len(self.MenuSizer.GetChildren()) > 1: lbessard@82: self.ClearSizer(self.MenuSizer.GetChildren()[1].GetSizer()) lbessard@82: self.MenuSizer.Remove(1) lbessard@82: self.ClearSizer(self.ParamsPanelMainSizer) lbessard@94: self.RefreshSizerElement(self.ParamsPanel, self.ParamsPanelMainSizer, plugin, infos, None, False) lbessard@25: if plugin != self.PluginRoot and len(plugin.PluginMethods) > 0: lbessard@21: boxsizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@67: self.MenuSizer.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@82: button = wx.lib.buttons.GenBitmapTextButton(ID=id, parent=self.RightPanel, lbessard@82: bitmap=wx.Bitmap(os.path.join(CWD, "%s32x32.png"%plugin_infos["bitmap"])), label=plugin_infos["name"], lbessard@82: 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@67: name=plugin_infos["name"], parent=self.RightPanel, 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@82: self.RightGridSizer.Layout() 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@94: def GetChoiceCallBackFunction(self, choicectrl, plugin, path, selected=None): lbessard@19: def OnChoiceChanged(event): 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@94: def GetChoiceContentCallBackFunction(self, choicectrl, staticboxsizer, plugin, path, selected=None): lbessard@19: def OnChoiceContentChanged(event): 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@82: if wx.VERSION < (2, 8, 0): lbessard@82: self.ParamsPanel.Freeze() lbessard@94: self.RefreshSizerElement(self.ParamsPanel, staticboxsizer, plugin, infos["children"], "%s.%s"%(path, infos["name"]), selected=selected) lbessard@82: self.ParamsPanelMainSizer.Layout() lbessard@82: self.ParamsPanel.Thaw() lbessard@82: self.ParamsPanel.Refresh() lbessard@82: else: lbessard@82: wx.CallAfter(self.RefreshPluginTree) lbessard@19: event.Skip() lbessard@19: return OnChoiceContentChanged lbessard@19: lbessard@94: def GetTextCtrlCallBackFunction(self, textctrl, plugin, path, selected=None): lbessard@19: def OnTextCtrlChanged(event): 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: lbessard@94: def GetCheckBoxCallBackFunction(self, chkbx, plugin, path, selected=None): lbessard@19: def OnCheckBoxChanged(event): 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@94: def RefreshSizerElement(self, parent, sizer, plugin, elements, path, clean = True, selected = None): 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@82: name="%s_bitmap"%element_infos["name"], parent=parent, 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@82: name="%s_label"%element_infos["name"], parent=parent, lbessard@19: pos=wx.Point(0, 0), size=wx.Size(100, 17), style=0) lbessard@67: boxsizer.AddWindow(statictext, 0, border=4, flag=wx.TOP) lbessard@19: id = wx.NewId() lbessard@82: choicectrl = wx.Choice(id=id, name=element_infos["name"], parent=parent, 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@82: name='%s_staticbox'%element_infos["name"], parent=parent, lbessard@19: pos=wx.Point(0, 0), size=wx.Size(0, 0), style=0) lbessard@19: staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL) lbessard@82: sizer.AddSizer(staticboxsizer, 0, border=5, flag=wx.GROW|wx.BOTTOM) lbessard@94: self.RefreshSizerElement(parent, staticboxsizer, plugin, element_infos["children"], element_path, selected) lbessard@94: callback = self.GetChoiceContentCallBackFunction(choicectrl, staticboxsizer, plugin, element_path, selected) lbessard@19: else: lbessard@19: for choice in element_infos["type"]: lbessard@19: choicectrl.Append(choice) lbessard@94: callback = self.GetChoiceCallBackFunction(choicectrl, plugin, element_path, selected) 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@82: name="%s_bitmap"%element_infos["name"], parent=parent, 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@82: name="%s_label"%element_infos["name"], parent=parent, lbessard@19: pos=wx.Point(0, 0), size=wx.Size(100, 17), style=0) lbessard@67: boxsizer.AddWindow(statictext, 0, border=4, flag=wx.TOP) 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@82: spinctrl = wx.SpinCtrl(id=id, name=element_infos["name"], parent=parent, 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@94: spinctrl.Bind(wx.EVT_SPINCTRL, self.GetTextCtrlCallBackFunction(spinctrl, plugin, element_path, selected), id=id) lbessard@19: elif element_infos["type"] == "element": lbessard@19: staticbox = wx.StaticBox(id=-1, label=element_infos["name"], lbessard@82: name='%s_staticbox'%element_infos["name"], parent=parent, 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@94: self.RefreshSizerElement(parent, staticboxsizer, plugin, element_infos["children"], element_path, False, selected) 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@82: name="%s_bitmap"%element_infos["name"], parent=parent, 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@82: name="%s_label"%element_infos["name"], parent=parent, lbessard@19: pos=wx.Point(0, 0), size=wx.Size(100, 17), style=0) lbessard@67: boxsizer.AddWindow(statictext, 0, border=4, flag=wx.TOP) lbessard@19: id = wx.NewId() lbessard@19: if element_infos["type"] == "boolean": lbessard@82: checkbox = wx.CheckBox(id=id, name=element_infos["name"], parent=parent, 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@94: checkbox.Bind(wx.EVT_CHECKBOX, self.GetCheckBoxCallBackFunction(checkbox, plugin, element_path, selected), 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@82: spinctrl = wx.SpinCtrl(id=id, name=element_infos["name"], parent=parent, 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@94: spinctrl.Bind(wx.EVT_SPINCTRL, self.GetTextCtrlCallBackFunction(spinctrl, plugin, element_path, selected), id=id) lbessard@19: else: lbessard@82: textctrl = wx.TextCtrl(id=id, name=element_infos["name"], parent=parent, 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"])) lbessard@94: textctrl.Bind(wx.EVT_TEXT_ENTER, self.GetTextCtrlCallBackFunction(textctrl, plugin, element_path, selected), id=id) lbessard@94: textctrl.Bind(wx.EVT_KILL_FOCUS, self.GetTextCtrlCallBackFunction(textctrl, plugin, element_path, selected)) 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 : lbessard@84: self.RefreshPluginToolBar() 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@84: self.RefreshPluginToolBar() lbessard@17: self.RefreshPluginTree() lbessard@46: self.PluginTree.SelectItem(self.PluginTree.GetRootItem()) lbessard@17: self.RefreshButtons() lbessard@17: self.RefreshMainMenu() lbessard@84: self.PluginTree.ScrollWindow(0, self.PluginTree.GetClientSize()[1]) 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@84: self.RefreshPluginToolBar() lbessard@82: self.RefreshPluginTree() 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@87: def GetAddButtonFunction(self, item, window): lbessard@82: def AddButtonFunction(event): lbessard@82: plugin = self.GetSelectedPlugin(item) lbessard@82: if plugin and len(plugin.PlugChildsTypes) > 0: lbessard@82: plugin_menu = wx.Menu(title='') lbessard@82: for name, XSDClass in plugin.PlugChildsTypes: lbessard@82: new_id = wx.NewId() lbessard@82: plugin_menu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=name) lbessard@82: self.Bind(wx.EVT_MENU, self._GetAddPluginFunction(name, item), id=new_id) lbessard@87: window_pos = window.GetPosition() etisserant@93: wx.CallAfter(self.PluginTree.PopupMenu, plugin_menu) lbessard@82: event.Skip() lbessard@82: return AddButtonFunction lbessard@82: lbessard@82: def GetDeleteButtonFunction(self, item): lbessard@82: def DeleteButtonFunction(event): lbessard@82: wx.CallAfter(self.DeletePlugin, item) lbessard@82: event.Skip() lbessard@82: return DeleteButtonFunction lbessard@82: lbessard@82: def AddPlugin(self, PluginType, selected = None): 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@82: plugin = self.GetSelectedPlugin(selected) etisserant@28: plugin.PlugAddChild(PluginName, PluginType, self.Log) lbessard@17: self.RefreshPluginTree() lbessard@0: dialog.Destroy() lbessard@0: lbessard@82: def DeletePlugin(self, selected = None): lbessard@72: dialog = wx.MessageDialog(self, "Really delete plugin ?", "Remove plugin", wx.YES_NO|wx.NO_DEFAULT) etisserant@50: if dialog.ShowModal() == wx.ID_YES: lbessard@82: plugin = self.GetSelectedPlugin(selected) 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()