]> rtime.felk.cvut.cz Git - CanFestival-3.git/blob - objdictgen/objdictedit.py
Adding program for network management
[CanFestival-3.git] / objdictgen / objdictedit.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 #This file is part of CanFestival, a library implementing CanOpen Stack. 
5 #
6 #Copyright (C): Edouard TISSERANT, Francis DUPIN and Laurent BESSARD
7 #
8 #See COPYING file for copyrights details.
9 #
10 #This library is free software; you can redistribute it and/or
11 #modify it under the terms of the GNU Lesser General Public
12 #License as published by the Free Software Foundation; either
13 #version 2.1 of the License, or (at your option) any later version.
14 #
15 #This library is distributed in the hope that it will be useful,
16 #but WITHOUT ANY WARRANTY; without even the implied warranty of
17 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 #Lesser General Public License for more details.
19 #
20 #You should have received a copy of the GNU Lesser General Public
21 #License along with this library; if not, write to the Free Software
22 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
24 from wxPython.wx import *
25 from wxPython.grid import *
26 import wx
27 import wx.grid
28
29 from types import *
30 import os, re, platform, sys, time, traceback, getopt
31
32 __version__ = "$Revision: 1.18 $"
33
34 from nodemanager import *
35 from subindextable import *
36 from commondialogs import *
37 from doc_index.DS301_index import *
38
39 try:
40     from wxPython.html import *
41
42     wxEVT_HTML_URL_CLICK = wxNewId()
43
44     def EVT_HTML_URL_CLICK(win, func):
45         win.Connect(-1, -1, wxEVT_HTML_URL_CLICK, func)
46
47     class wxHtmlWindowUrlClick(wxPyEvent):
48         def __init__(self, linkinfo):
49             wxPyEvent.__init__(self)
50             self.SetEventType(wxEVT_HTML_URL_CLICK)
51             self.linkinfo = (linkinfo.GetHref(), linkinfo.GetTarget())
52
53     class wxUrlClickHtmlWindow(wxHtmlWindow):
54         """ HTML window that generates and OnLinkClicked event.
55
56         Use this to avoid having to override HTMLWindow
57         """
58         def OnLinkClicked(self, linkinfo):
59             wxPostEvent(self, wxHtmlWindowUrlClick(linkinfo))
60     
61 #-------------------------------------------------------------------------------
62 #                                Html Frame
63 #-------------------------------------------------------------------------------
64
65     [wxID_HTMLFRAME, wxID_HTMLFRAMEHTMLCONTENT] = [wx.NewId() for _init_ctrls in range(2)]
66
67     class HtmlFrame(wx.Frame):
68         def _init_ctrls(self, prnt):
69             # generated method, don't edit
70             wx.Frame.__init__(self, id=wxID_HTMLFRAME, name='HtmlFrame',
71                   parent=prnt, pos=wx.Point(320, 231), size=wx.Size(853, 616),
72                   style=wx.DEFAULT_FRAME_STYLE, title='')
73             self.Bind(wx.EVT_CLOSE, self.OnCloseFrame, id=wxID_HTMLFRAME)
74             
75             self.HtmlContent = wxUrlClickHtmlWindow(id=wxID_HTMLFRAMEHTMLCONTENT,
76                   name='HtmlContent', parent=self, pos=wx.Point(0, 0),
77                   size=wx.Size(-1, -1), style=wxHW_SCROLLBAR_AUTO|wxHW_NO_SELECTION)
78             EVT_HTML_URL_CLICK(self.HtmlContent, self.OnLinkClick)
79
80         def __init__(self, parent, opened):
81             self._init_ctrls(parent)
82             self.HtmlFrameOpened = opened
83         
84         def SetHtmlCode(self, htmlcode):
85             self.HtmlContent.SetPage(htmlcode)
86             
87         def SetHtmlPage(self, htmlpage):
88             self.HtmlContent.LoadPage(htmlpage)
89             
90         def OnCloseFrame(self, event):
91             self.HtmlFrameOpened.remove(self.GetTitle())
92             event.Skip()
93         
94         def OnLinkClick(self, event):
95             url = event.linkinfo[0]
96             try:
97                 import webbrowser
98             except ImportError:
99                 wxMessageBox('Please point your browser at: %s' % url)
100             else:
101                 webbrowser.open(url)
102     
103     Html_Window = True
104 except:
105     Html_Window = False
106
107 def create(parent):
108     return objdictedit(parent)
109
110 def usage():
111     print "\nUsage of objdictedit.py :"
112     print "\n   %s [Filepath, ...]\n"%sys.argv[0]
113
114 try:
115     opts, args = getopt.getopt(sys.argv[1:], "h", ["help"])
116 except getopt.GetoptError:
117     # print help information and exit:
118     usage()
119     sys.exit(2)
120
121 for o, a in opts:
122     if o in ("-h", "--help"):
123         usage()
124         sys.exit()
125
126 filesOpen = args
127 ScriptDirectory = sys.path[0]
128
129
130 [wxID_OBJDICTEDIT, wxID_OBJDICTEDITFILEOPENED, 
131  wxID_OBJDICTEDITHELPBAR,
132 ] = [wx.NewId() for _init_ctrls in range(3)]
133
134 [wxID_OBJDICTEDITADDMENUITEMS0, wxID_OBJDICTEDITADDMENUITEMS1, 
135  wxID_OBJDICTEDITADDMENUITEMS2, wxID_OBJDICTEDITADDMENUITEMS3, 
136  wxID_OBJDICTEDITADDMENUITEMS4, wxID_OBJDICTEDITADDMENUITEMS5, 
137 ] = [wx.NewId() for _init_coll_AddMenu_Items in range(6)]
138
139 [wxID_OBJDICTEDITFILEMENUITEMS0, wxID_OBJDICTEDITFILEMENUITEMS1, 
140  wxID_OBJDICTEDITFILEMENUITEMS2, wxID_OBJDICTEDITFILEMENUITEMS4, 
141  wxID_OBJDICTEDITFILEMENUITEMS5, wxID_OBJDICTEDITFILEMENUITEMS6, 
142  wxID_OBJDICTEDITFILEMENUITEMS7, wxID_OBJDICTEDITFILEMENUITEMS8,
143  wxID_OBJDICTEDITFILEMENUITEMS9,
144 ] = [wx.NewId() for _init_coll_FileMenu_Items in range(9)]
145
146 [wxID_OBJDICTEDITEDITMENUITEMS0, wxID_OBJDICTEDITEDITMENUITEMS1, 
147  wxID_OBJDICTEDITEDITMENUITEMS2, wxID_OBJDICTEDITEDITMENUITEMS4, 
148  wxID_OBJDICTEDITEDITMENUITEMS6, wxID_OBJDICTEDITEDITMENUITEMS7, 
149  wxID_OBJDICTEDITEDITMENUITEMS8, 
150 ] = [wx.NewId() for _init_coll_EditMenu_Items in range(7)]
151
152 [wxID_OBJDICTEDITHELPMENUITEMS0, wxID_OBJDICTEDITHELPMENUITEMS1,
153  wxID_OBJDICTEDITHELPMENUITEMS2,
154 ] = [wx.NewId() for _init_coll_HelpMenu_Items in range(3)]
155
156 class objdictedit(wx.Frame):
157     def _init_coll_menuBar1_Menus(self, parent):
158         # generated method, don't edit
159
160         parent.Append(menu=self.FileMenu, title='File')
161         parent.Append(menu=self.EditMenu, title='Edit')
162         parent.Append(menu=self.AddMenu, title='Add')
163         parent.Append(menu=self.HelpMenu, title='Help')
164
165     def _init_coll_EditMenu_Items(self, parent):
166         # generated method, don't edit
167
168         parent.Append(help='', id=wxID_OBJDICTEDITEDITMENUITEMS4,
169               kind=wx.ITEM_NORMAL, text='Refresh\tCTRL+R')
170         parent.AppendSeparator()
171         parent.Append(help='', id=wxID_OBJDICTEDITEDITMENUITEMS1,
172               kind=wx.ITEM_NORMAL, text='Undo\tCTRL+Z')
173         parent.Append(help='', id=wxID_OBJDICTEDITEDITMENUITEMS0,
174               kind=wx.ITEM_NORMAL, text='Redo\tCTRL+Y')
175         parent.AppendSeparator()
176         parent.Append(help='', id=wxID_OBJDICTEDITEDITMENUITEMS6,
177               kind=wx.ITEM_NORMAL, text='Node infos')
178         parent.Append(help='', id=wxID_OBJDICTEDITEDITMENUITEMS2,
179               kind=wx.ITEM_NORMAL, text='DS-301 Profile')
180         parent.Append(help='', id=wxID_OBJDICTEDITEDITMENUITEMS8,
181               kind=wx.ITEM_NORMAL, text='DS-302 Profile')
182         parent.Append(help='', id=wxID_OBJDICTEDITEDITMENUITEMS7,
183               kind=wx.ITEM_NORMAL, text='Other Profile')
184         self.Bind(wx.EVT_MENU, self.OnUndoMenu,
185               id=wxID_OBJDICTEDITEDITMENUITEMS1)
186         self.Bind(wx.EVT_MENU, self.OnRedoMenu,
187               id=wxID_OBJDICTEDITEDITMENUITEMS0)
188         self.Bind(wx.EVT_MENU, self.OnCommunicationMenu,
189               id=wxID_OBJDICTEDITEDITMENUITEMS2)
190         self.Bind(wx.EVT_MENU, self.OnRefreshMenu,
191               id=wxID_OBJDICTEDITEDITMENUITEMS4)
192         self.Bind(wx.EVT_MENU, self.OnNodeInfosMenu,
193               id=wxID_OBJDICTEDITEDITMENUITEMS6)
194         self.Bind(wx.EVT_MENU, self.OnEditProfileMenu,
195               id=wxID_OBJDICTEDITEDITMENUITEMS7)
196         self.Bind(wx.EVT_MENU, self.OnOtherCommunicationMenu,
197               id=wxID_OBJDICTEDITEDITMENUITEMS8)
198
199     def _init_coll_HelpMenu_Items(self, parent):
200         # generated method, don't edit
201
202         parent.Append(help='', id=wxID_OBJDICTEDITHELPMENUITEMS0,
203               kind=wx.ITEM_NORMAL, text='DS-301 Standard\tF1')
204         self.Bind(wx.EVT_MENU, self.OnHelpDS301Menu,
205               id=wxID_OBJDICTEDITHELPMENUITEMS0)
206         parent.Append(help='', id=wxID_OBJDICTEDITHELPMENUITEMS1,
207               kind=wx.ITEM_NORMAL, text='CAN Festival Docs\tF2')
208         self.Bind(wx.EVT_MENU, self.OnHelpCANFestivalMenu,
209               id=wxID_OBJDICTEDITHELPMENUITEMS1)
210         if Html_Window:
211             parent.Append(help='', id=wxID_OBJDICTEDITHELPMENUITEMS2,
212                   kind=wx.ITEM_NORMAL, text='About')
213             self.Bind(wx.EVT_MENU, self.OnAboutMenu,
214                   id=wxID_OBJDICTEDITHELPMENUITEMS2)
215
216     def _init_coll_FileMenu_Items(self, parent):
217         # generated method, don't edit
218
219         parent.Append(help='', id=wxID_OBJDICTEDITFILEMENUITEMS5,
220               kind=wx.ITEM_NORMAL, text='New\tCTRL+N')
221         parent.Append(help='', id=wxID_OBJDICTEDITFILEMENUITEMS0,
222               kind=wx.ITEM_NORMAL, text='Open\tCTRL+O')
223         parent.Append(help='', id=wxID_OBJDICTEDITFILEMENUITEMS1,
224               kind=wx.ITEM_NORMAL, text='Save\tCTRL+S')
225         parent.Append(help='', id=wxID_OBJDICTEDITFILEMENUITEMS6,
226               kind=wx.ITEM_NORMAL, text='Save As...\tALT+S')
227         parent.Append(help='', id=wxID_OBJDICTEDITFILEMENUITEMS2,
228               kind=wx.ITEM_NORMAL, text='Close\tCTRL+W')
229         parent.AppendSeparator()
230         parent.Append(help='', id=wxID_OBJDICTEDITFILEMENUITEMS7,
231               kind=wx.ITEM_NORMAL, text='Import EDS file')
232         parent.Append(help='', id=wxID_OBJDICTEDITFILEMENUITEMS9,
233               kind=wx.ITEM_NORMAL, text='Export to EDS file')
234         parent.Append(help='', id=wxID_OBJDICTEDITFILEMENUITEMS8,
235               kind=wx.ITEM_NORMAL, text='Build Dictionary\tCTRL+B')
236         parent.AppendSeparator()
237         parent.Append(help='', id=wxID_OBJDICTEDITFILEMENUITEMS4,
238               kind=wx.ITEM_NORMAL, text='Exit')
239         self.Bind(wx.EVT_MENU, self.OnOpenMenu,
240               id=wxID_OBJDICTEDITFILEMENUITEMS0)
241         self.Bind(wx.EVT_MENU, self.OnSaveMenu,
242               id=wxID_OBJDICTEDITFILEMENUITEMS1)
243         self.Bind(wx.EVT_MENU, self.OnCloseMenu,
244               id=wxID_OBJDICTEDITFILEMENUITEMS2)
245         self.Bind(wx.EVT_MENU, self.OnQuitMenu,
246               id=wxID_OBJDICTEDITFILEMENUITEMS4)
247         self.Bind(wx.EVT_MENU, self.OnNewMenu,
248               id=wxID_OBJDICTEDITFILEMENUITEMS5)
249         self.Bind(wx.EVT_MENU, self.OnSaveAsMenu,
250               id=wxID_OBJDICTEDITFILEMENUITEMS6)
251         self.Bind(wx.EVT_MENU, self.OnImportEDSMenu,
252               id=wxID_OBJDICTEDITFILEMENUITEMS7)
253         self.Bind(wx.EVT_MENU, self.OnExportCMenu,
254               id=wxID_OBJDICTEDITFILEMENUITEMS8)
255         self.Bind(wx.EVT_MENU, self.OnExportEDSMenu,
256               id=wxID_OBJDICTEDITFILEMENUITEMS9)
257
258     def _init_coll_AddMenu_Items(self, parent):
259         # generated method, don't edit
260
261         parent.Append(help='', id=wxID_OBJDICTEDITADDMENUITEMS0,
262               kind=wx.ITEM_NORMAL, text='SDO Server')
263         parent.Append(help='', id=wxID_OBJDICTEDITADDMENUITEMS1,
264               kind=wx.ITEM_NORMAL, text='SDO Client')
265         parent.Append(help='', id=wxID_OBJDICTEDITADDMENUITEMS2,
266               kind=wx.ITEM_NORMAL, text='PDO Transmit')
267         parent.Append(help='', id=wxID_OBJDICTEDITADDMENUITEMS3,
268               kind=wx.ITEM_NORMAL, text='PDO Receive')
269         parent.Append(help='', id=wxID_OBJDICTEDITADDMENUITEMS4,
270               kind=wx.ITEM_NORMAL, text='Map Variable')
271         parent.Append(help='', id=wxID_OBJDICTEDITADDMENUITEMS5,
272               kind=wx.ITEM_NORMAL, text='User Type')
273         self.Bind(wx.EVT_MENU, self.OnAddSDOServerMenu,
274               id=wxID_OBJDICTEDITADDMENUITEMS0)
275         self.Bind(wx.EVT_MENU, self.OnAddSDOClientMenu,
276               id=wxID_OBJDICTEDITADDMENUITEMS1)
277         self.Bind(wx.EVT_MENU, self.OnAddPDOTransmitMenu,
278               id=wxID_OBJDICTEDITADDMENUITEMS2)
279         self.Bind(wx.EVT_MENU, self.OnAddPDOReceiveMenu,
280               id=wxID_OBJDICTEDITADDMENUITEMS3)
281         self.Bind(wx.EVT_MENU, self.OnAddMapVariableMenu,
282               id=wxID_OBJDICTEDITADDMENUITEMS4)
283         self.Bind(wx.EVT_MENU, self.OnAddUserTypeMenu,
284               id=wxID_OBJDICTEDITADDMENUITEMS5)
285
286     def _init_coll_HelpBar_Fields(self, parent):
287         # generated method, don't edit
288         parent.SetFieldsCount(3)
289
290         parent.SetStatusText(number=0, text='')
291         parent.SetStatusText(number=1, text='')
292         parent.SetStatusText(number=2, text='')
293
294         parent.SetStatusWidths([100, 110, -1])
295
296     def _init_utils(self):
297         # generated method, don't edit
298         self.menuBar1 = wx.MenuBar()
299         self.menuBar1.SetEvtHandlerEnabled(True)
300
301         self.FileMenu = wx.Menu(title='')
302
303         self.EditMenu = wx.Menu(title='')
304
305         self.AddMenu = wx.Menu(title='')
306
307         self.HelpMenu = wx.Menu(title='')
308
309         self._init_coll_menuBar1_Menus(self.menuBar1)
310         self._init_coll_FileMenu_Items(self.FileMenu)
311         self._init_coll_EditMenu_Items(self.EditMenu)
312         self._init_coll_AddMenu_Items(self.AddMenu)
313         self._init_coll_HelpMenu_Items(self.HelpMenu)
314
315     def _init_ctrls(self, prnt):
316         # generated method, don't edit
317         wx.Frame.__init__(self, id=wxID_OBJDICTEDIT, name='objdictedit',
318               parent=prnt, pos=wx.Point(149, 178), size=wx.Size(1000, 700),
319               style=wx.DEFAULT_FRAME_STYLE, title='Objdictedit')
320         self._init_utils()
321         self.SetClientSize(wx.Size(1000, 700))
322         self.SetMenuBar(self.menuBar1)
323         self.Bind(wx.EVT_CLOSE, self.OnCloseFrame, id=wxID_OBJDICTEDIT)
324
325         self.FileOpened = wx.Notebook(id=wxID_OBJDICTEDITFILEOPENED,
326               name='FileOpened', parent=self, pos=wx.Point(0, 0),
327               size=wx.Size(0, 0), style=0)
328         self.FileOpened.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED,
329               self.OnFileSelectedChanged, id=wxID_OBJDICTEDITFILEOPENED)
330
331         self.HelpBar = wx.StatusBar(id=wxID_OBJDICTEDITHELPBAR, name='HelpBar',
332               parent=self, style=wxST_SIZEGRIP)
333         self._init_coll_HelpBar_Fields(self.HelpBar)
334         self.SetStatusBar(self.HelpBar)
335
336     def __init__(self, parent):
337         self._init_ctrls(parent)
338         self.HtmlFrameOpened = []
339         
340         self.Manager = NodeManager(ScriptDirectory)
341         for filepath in filesOpen:
342             self.Manager.OpenFileInCurrent(filepath)
343             new_editingpanel = EditingPanel(self, self.Manager)
344             self.FileOpened.AddPage(new_editingpanel, "")
345             self.FileOpened.SetSelection(self.Manager.GetCurrentNodeIndex())
346         if self.Manager.CurrentDS302Defined(): 
347             self.EditMenu.Enable(wxID_OBJDICTEDITEDITMENUITEMS8, True)
348         else:
349             self.EditMenu.Enable(wxID_OBJDICTEDITEDITMENUITEMS8, False)
350         self.RefreshEditMenu()
351         self.RefreshBufferState()
352         self.RefreshProfileMenu()
353         self.RefreshTitle()
354         self.RefreshMainMenu()
355
356     def GetNoteBook(self):
357         return self.FileOpened
358
359     def OnAddSDOServerMenu(self, event):
360         self.Manager.AddSDOServerToCurrent()
361         self.RefreshBufferState()
362         self.RefreshCurrentIndexList()
363         event.Skip()
364     
365     def OnAddSDOClientMenu(self, event):
366         self.Manager.AddSDOClientToCurrent()
367         self.RefreshBufferState()
368         self.RefreshCurrentIndexList()
369         event.Skip()
370
371     def OnAddPDOTransmitMenu(self, event):
372         self.Manager.AddPDOTransmitToCurrent()
373         self.RefreshBufferState()
374         self.RefreshCurrentIndexList()
375         event.Skip()
376
377     def OnAddPDOReceiveMenu(self, event):
378         self.Manager.AddPDOReceiveToCurrent()
379         self.RefreshBufferState()
380         self.RefreshCurrentIndexList()
381         event.Skip()
382
383     def OnAddMapVariableMenu(self, event):
384         self.AddMapVariable()
385         event.Skip()
386
387     def OnAddUserTypeMenu(self, event):
388         self.AddUserType()
389         event.Skip()
390
391     def OnFileSelectedChanged(self, event):
392         selected = event.GetSelection()
393         # At init selected = -1
394         if selected >= 0:
395             window = self.FileOpened.GetPage(selected)
396             self.Manager.ChangeCurrentNode(window.GetIndex())
397             self.RefreshBufferState()
398             self.RefreshStatusBar()
399             self.RefreshProfileMenu()
400         event.Skip()
401
402     def OnHelpDS301Menu(self, event):
403         find_index = False
404         selected = self.FileOpened.GetSelection()
405         if selected >= 0:
406             window = self.FileOpened.GetPage(selected)
407             result = window.GetSelection()
408             if result:
409                 find_index = True
410                 index, subIndex = result
411                 result = OpenPDFDocIndex(index, ScriptDirectory)
412                 if type(result) == StringType:
413                     message = wxMessageDialog(self, result, "ERROR", wxOK|wxICON_ERROR)
414                     message.ShowModal()
415                     message.Destroy()
416         if not find_index:
417             result = OpenPDFDocIndex(None, ScriptDirectory)
418             if type(result) == StringType:
419                 message = wxMessageDialog(self, result, "ERROR", wxOK|wxICON_ERROR)
420                 message.ShowModal()
421                 message.Destroy()
422         event.Skip()
423         
424     def OnHelpCANFestivalMenu(self, event):
425         #self.OpenHtmlFrame("CAN Festival Reference", os.path.join(ScriptDirectory, "doc/canfestival.html"), wx.Size(1000, 600))
426         os.system("xpdf -remote CANFESTIVAL %s %d &"%(os.path.join(ScriptDirectory, "doc/manual_en.pdf"),16))
427         event.Skip()
428
429     def OnAboutMenu(self, event):
430         self.OpenHtmlFrame("About CAN Festival", os.path.join(ScriptDirectory, "doc/about.html"), wx.Size(500, 450))
431         event.Skip()
432
433     def OpenHtmlFrame(self, title, file, size):
434         if title not in self.HtmlFrameOpened:
435             self.HtmlFrameOpened.append(title)
436             window = HtmlFrame(self, self.HtmlFrameOpened)
437             window.SetTitle(title)
438             window.SetHtmlPage(file)
439             window.SetClientSize(size)
440             window.Show()
441
442     def OnQuitMenu(self, event):
443         self.Close()
444         event.Skip()
445     
446     def OnCloseFrame(self, event):
447         if self.Manager.OneFileHasChanged():
448             dialog = wxMessageDialog(self, "There are changes, do you want to save?",  "Close Application", wxYES_NO|wxCANCEL|wxICON_QUESTION)
449             answer = dialog.ShowModal()
450             dialog.Destroy()
451             if answer == wxID_YES:
452                 self.Manager.ChangeCurrentNode(0)
453                 for i in xrange(self.FileOpened.GetPageCount()):
454                     if self.Manager.CurrentIsSaved():
455                         self.Manager.CloseCurrent()
456                     else:
457                         self.Save()
458                         self.Manager.CloseCurrent(True)
459                 event.Skip()
460             elif answer == wxID_NO:
461                 for i in xrange(self.FileOpened.GetPageCount()):
462                     self.Manager.CloseCurrent(True)
463                 wxCallAfter(self.Close)
464                 event.Skip()
465         else:
466             event.Skip()
467
468 #-------------------------------------------------------------------------------
469 #                             Refresh Functions
470 #-------------------------------------------------------------------------------
471
472     def RefreshTitle(self):
473         if self.FileOpened.GetPageCount() > 0:
474             self.SetTitle("Objdictedit - %s"%self.Manager.GetCurrentFilename())
475         else:
476             self.SetTitle("Objdictedit")
477
478     def OnRefreshMenu(self, event):
479         self.RefreshCurrentIndexList()
480         event.Skip()
481
482     def RefreshCurrentIndexList(self):
483         selected = self.FileOpened.GetSelection()
484         window = self.FileOpened.GetPage(selected)
485         window.RefreshIndexList()
486
487     def RefreshStatusBar(self):
488         if self.HelpBar:
489             window = self.FileOpened.GetPage(self.FileOpened.GetSelection())
490             selection = window.GetSelection()
491             if selection:
492                 index, subIndex = selection
493                 if self.Manager.IsCurrentEntry(index):
494                     self.HelpBar.SetStatusText("Index: 0x%04X"%index, 0)
495                     self.HelpBar.SetStatusText("Subindex: 0x%02X"%subIndex, 1)
496                     entryinfos = self.Manager.GetEntryInfos(index)
497                     name = entryinfos["name"]
498                     category = "Optional"
499                     if entryinfos["need"]:
500                         category = "Mandatory"
501                     struct = "VAR"
502                     number = ""
503                     if entryinfos["struct"] & OD_IdenticalIndexes:
504                         number = " possibly defined %d times"%entryinfos["nbmax"]
505                     if entryinfos["struct"] & OD_IdenticalSubindexes:
506                         struct = "REC"
507                     elif entryinfos["struct"] & OD_MultipleSubindexes:
508                         struct = "ARRAY"
509                     text = "%s: %s entry of struct %s%s."%(name,category,struct,number)
510                     self.HelpBar.SetStatusText(text, 2)
511                 else:
512                     for i in xrange(3):
513                         self.HelpBar.SetStatusText("", i)
514             else:
515                 for i in xrange(3):
516                     self.HelpBar.SetStatusText("", i)
517
518     def RefreshMainMenu(self):
519         if self.FileMenu:
520             if self.FileOpened.GetPageCount() > 0:
521                 self.menuBar1.EnableTop(1, True)
522                 self.menuBar1.EnableTop(2, True)
523                 self.FileMenu.Enable(wxID_OBJDICTEDITFILEMENUITEMS1, True)
524                 self.FileMenu.Enable(wxID_OBJDICTEDITFILEMENUITEMS2, True)
525                 self.FileMenu.Enable(wxID_OBJDICTEDITFILEMENUITEMS6, True)
526                 self.FileMenu.Enable(wxID_OBJDICTEDITFILEMENUITEMS8, True)
527                 self.FileMenu.Enable(wxID_OBJDICTEDITFILEMENUITEMS9, True)
528             else:
529                 self.menuBar1.EnableTop(1, False)      
530                 self.menuBar1.EnableTop(2, False)
531                 self.FileMenu.Enable(wxID_OBJDICTEDITFILEMENUITEMS1, False)
532                 self.FileMenu.Enable(wxID_OBJDICTEDITFILEMENUITEMS2, False)
533                 self.FileMenu.Enable(wxID_OBJDICTEDITFILEMENUITEMS6, False)
534                 self.FileMenu.Enable(wxID_OBJDICTEDITFILEMENUITEMS8, False)
535                 self.FileMenu.Enable(wxID_OBJDICTEDITFILEMENUITEMS9, False)
536
537     def RefreshEditMenu(self):
538         if self.FileMenu:
539             if self.FileOpened.GetPageCount() > 0:
540                 undo, redo = self.Manager.GetCurrentBufferState()
541                 self.EditMenu.Enable(wxID_OBJDICTEDITEDITMENUITEMS1, undo)
542                 self.EditMenu.Enable(wxID_OBJDICTEDITEDITMENUITEMS0, redo)
543             else:
544                 self.EditMenu.Enable(wxID_OBJDICTEDITEDITMENUITEMS1, False)
545                 self.EditMenu.Enable(wxID_OBJDICTEDITEDITMENUITEMS0, False)
546
547     def RefreshProfileMenu(self):
548         if self.EditMenu:
549             profile = self.Manager.GetCurrentProfileName()
550             edititem = self.EditMenu.FindItemById(wxID_OBJDICTEDITEDITMENUITEMS7)
551             if edititem:
552                 length = self.AddMenu.GetMenuItemCount()
553                 for i in xrange(length-6):
554                     additem = self.AddMenu.FindItemByPosition(6)
555                     self.AddMenu.Delete(additem.GetId())
556                 if profile not in ("None", "DS-301"):
557                     edititem.SetText("%s Profile"%profile)
558                     edititem.Enable(True)
559                     self.AddMenu.AppendSeparator()
560                     for text, indexes in self.Manager.GetCurrentSpecificMenu():
561                         new_id = wx.NewId()
562                         self.AddMenu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=text)
563                         self.Bind(wx.EVT_MENU, self.GetProfileCallBack(text), id=new_id)
564                 else:
565                     edititem.SetText("Other Profile")
566                     edititem.Enable(False)
567         
568
569 #-------------------------------------------------------------------------------
570 #                            Buffer Functions
571 #-------------------------------------------------------------------------------
572
573     def RefreshBufferState(self):
574         fileopened = self.Manager.GetAllFilenames()
575         for idx, filename in enumerate(fileopened):
576             self.FileOpened.SetPageText(idx, filename)
577         self.RefreshEditMenu()
578         self.RefreshTitle()
579
580     def OnUndoMenu(self, event):
581         self.Manager.LoadCurrentPrevious()
582         self.RefreshCurrentIndexList()
583         self.RefreshBufferState()
584         event.Skip()
585
586     def OnRedoMenu(self, event):
587         self.Manager.LoadCurrentNext()
588         self.RefreshCurrentIndexList()
589         self.RefreshBufferState()
590         event.Skip()
591
592
593 #-------------------------------------------------------------------------------
594 #                         Load and Save Funtions
595 #-------------------------------------------------------------------------------
596
597     def OnNewMenu(self, event):
598         self.FilePath = ""
599         dialog = CreateNodeDialog(self)
600         if dialog.ShowModal() == wxID_OK:
601             name, id, nodetype, description = dialog.GetValues()
602             profile, filepath = dialog.GetProfile()
603             NMT = dialog.GetNMTManagement()
604             options = dialog.GetOptions()
605             result = self.Manager.CreateNewNode(name, id, nodetype, description, profile, filepath, NMT, options)
606             if type(result) == IntType:
607                 new_editingpanel = EditingPanel(self, self.Manager)
608                 new_editingpanel.SetIndex(result)
609                 self.FileOpened.AddPage(new_editingpanel, "")
610                 self.FileOpened.SetSelection(self.FileOpened.GetPageCount() - 1)
611                 self.EditMenu.Enable(wxID_OBJDICTEDITEDITMENUITEMS8, False)
612                 if "DS302" in options:
613                     self.EditMenu.Enable(wxID_OBJDICTEDITEDITMENUITEMS8, True)
614                 self.RefreshBufferState()
615                 self.RefreshProfileMenu()
616                 self.RefreshMainMenu()
617             else:
618                 message = wxMessageDialog(self, result, "ERROR", wxOK|wxICON_ERROR)
619                 message.ShowModal()
620                 message.Destroy()
621         event.Skip()
622
623     def OnOpenMenu(self, event):
624         filepath = self.Manager.GetCurrentFilePath()
625         if filepath != "":
626             directory = os.path.dirname(filepath)
627         else:
628             directory = os.getcwd()
629         dialog = wxFileDialog(self, "Choose a file", directory, "",  "OD files (*.od)|*.od|All files|*.*", wxOPEN|wxCHANGE_DIR)
630         if dialog.ShowModal() == wxID_OK:
631             filepath = dialog.GetPath()
632             if os.path.isfile(filepath):
633                 result = self.Manager.OpenFileInCurrent(filepath)
634                 if type(result) == IntType:
635                     new_editingpanel = EditingPanel(self, self.Manager)
636                     new_editingpanel.SetIndex(result)
637                     self.FileOpened.AddPage(new_editingpanel, "")
638                     self.FileOpened.SetSelection(self.FileOpened.GetPageCount() - 1)
639                     if self.Manager.CurrentDS302Defined(): 
640                         self.EditMenu.Enable(wxID_OBJDICTEDITEDITMENUITEMS8, True)
641                     else:
642                         self.EditMenu.Enable(wxID_OBJDICTEDITEDITMENUITEMS8, False)
643                     self.RefreshEditMenu()
644                     self.RefreshBufferState()
645                     self.RefreshProfileMenu()
646                     self.RefreshMainMenu()
647                 else:
648                     message = wxMessageDialog(self, e.args[0], "Error", wxOK|wxICON_ERROR)
649                     message.ShowModal()
650                     message.Destroy()
651         dialog.Destroy()
652         event.Skip()
653
654     def OnSaveMenu(self, event):
655         self.Save()
656         event.Skip()
657     
658     def OnSaveAsMenu(self, event):
659         self.SaveAs()
660         event.Skip()
661         
662     def Save(self):
663         result = self.Manager.SaveCurrentInFile()
664         if not result:
665             self.SaveAs()
666         elif type(result) != StringType:
667             self.RefreshBufferState()
668         else:
669             message = wxMessageDialog(self, result, "Error", wxOK|wxICON_ERROR)
670             message.ShowModal()
671             message.Destroy()
672
673     def SaveAs(self):
674         filepath = self.Manager.GetCurrentFilePath()
675         if filepath != "":
676             directory, filename = os.path.split(filepath)
677         else:
678             directory, filename = os.getcwd(), "%s.od"%self.Manager.GetCurrentNodeInfos()[0]
679         dialog = wxFileDialog(self, "Choose a file", directory, filename,  "OD files (*.od)|*.od|All files|*.*", wxSAVE|wxOVERWRITE_PROMPT|wxCHANGE_DIR)
680         if dialog.ShowModal() == wxID_OK:
681             filepath = dialog.GetPath()
682             if os.path.isdir(os.path.dirname(filepath)):
683                 result = self.Manager.SaveCurrentInFile(filepath)
684                 if type(result) != StringType:
685                     self.RefreshBufferState()
686                 else:
687                     message = wxMessageDialog(self, result, "Error", wxOK|wxICON_ERROR)
688                     message.ShowModal()
689                     message.Destroy()
690             else:
691                 message = wxMessageDialog(self, "%s is not a valid folder!"%os.path.dirname(filepath), "Error", wxOK|wxICON_ERROR)
692                 message.ShowModal()
693                 message.Destroy()
694         dialog.Destroy()
695
696     def OnCloseMenu(self, event):
697         answer = wxID_YES
698         result = self.Manager.CloseCurrent()
699         if not result:
700             dialog = wxMessageDialog(self, "There are changes, do you want to save?",  "Close File", wxYES_NO|wxCANCEL|wxICON_QUESTION)
701             answer = dialog.ShowModal()
702             dialog.Destroy()
703             if answer == wxID_YES:
704                 self.OnSaveMenu(event)
705                 if self.Manager.CurrentIsSaved():
706                     self.Manager.CloseCurrent()
707             elif answer == wxID_NO:
708                 self.Manager.CloseCurrent(True)
709         if self.FileOpened.GetPageCount() > self.Manager.GetBufferNumber():
710             current = self.FileOpened.GetSelection()
711             self.FileOpened.DeletePage(current)
712             if self.FileOpened.GetPageCount() > 0:
713                 self.FileOpened.SetSelection(min(current, self.FileOpened.GetPageCount() - 1))
714             self.RefreshBufferState()
715             self.RefreshMainMenu()
716         event.Skip()
717         
718
719 #-------------------------------------------------------------------------------
720 #                         Import and Export Functions
721 #-------------------------------------------------------------------------------
722
723     def OnImportEDSMenu(self, event):
724         dialog = wxFileDialog(self, "Choose a file", os.getcwd(), "",  "EDS files (*.eds)|*.eds|All files|*.*", wxOPEN|wxCHANGE_DIR)
725         if dialog.ShowModal() == wxID_OK:
726             filepath = dialog.GetPath()
727             if os.path.isfile(filepath):
728                 result = self.Manager.ImportCurrentFromEDSFile(filepath)
729                 if type(result) == IntType:
730                     new_editingpanel = EditingPanel(self, self.Manager)
731                     new_editingpanel.SetIndex(result)
732                     self.FileOpened.AddPage(new_editingpanel, "")
733                     self.FileOpened.SetSelection(self.FileOpened.GetPageCount() - 1)
734                     self.RefreshBufferState()
735                     self.RefreshCurrentIndexList()
736                     self.RefreshProfileMenu()
737                     self.RefreshMainMenu()
738                     message = wxMessageDialog(self, "Import successful", "Information", wxOK|wxICON_INFORMATION)
739                     message.ShowModal()
740                     message.Destroy()
741                 else:
742                     message = wxMessageDialog(self, result, "Error", wxOK|wxICON_ERROR)
743                     message.ShowModal()
744                     message.Destroy()
745             else:
746                 message = wxMessageDialog(self, "\"%s\" is not a valid file!"%filepath, "Error", wxOK|wxICON_ERROR)
747                 message.ShowModal()
748                 message.Destroy()
749         dialog.Destroy()
750         event.Skip()
751
752
753     def OnExportEDSMenu(self, event):
754         dialog = wxFileDialog(self, "Choose a file", os.getcwd(), self.Manager.GetCurrentNodeInfos()[0], "EDS files (*.eds)|*.eds|All files|*.*", wxSAVE|wxOVERWRITE_PROMPT|wxCHANGE_DIR)
755         if dialog.ShowModal() == wxID_OK:
756             filepath = dialog.GetPath()
757             if os.path.isdir(os.path.dirname(filepath)):
758                 path, extend = os.path.splitext(filepath)
759                 if extend in ("", "."):
760                     filepath = path + ".eds"
761                 result = self.Manager.ExportCurrentToEDSFile(filepath)
762                 if not result:
763                     message = wxMessageDialog(self, "Export successful", "Information", wxOK|wxICON_INFORMATION)
764                     message.ShowModal()
765                     message.Destroy()
766                 else:
767                     message = wxMessageDialog(self, result, "Error", wxOK|wxICON_ERROR)
768                     message.ShowModal()
769                     message.Destroy()
770             else:
771                 message = wxMessageDialog(self, "\"%s\" is not a valid folder!"%os.path.dirname(filepath), "Error", wxOK|wxICON_ERROR)
772                 message.ShowModal()
773                 message.Destroy()
774         dialog.Destroy()
775         event.Skip()
776
777     def OnExportCMenu(self, event):
778         dialog = wxFileDialog(self, "Choose a file", os.getcwd(), self.Manager.GetCurrentNodeInfos()[0],  "CANFestival OD files (*.c)|*.c|All files|*.*", wxSAVE|wxOVERWRITE_PROMPT|wxCHANGE_DIR)
779         if dialog.ShowModal() == wxID_OK:
780             filepath = dialog.GetPath()
781             if os.path.isdir(os.path.dirname(filepath)):
782                 path, extend = os.path.splitext(filepath)
783                 if extend in ("", "."):
784                     filepath = path + ".c"
785                 result = self.Manager.ExportCurrentToCFile(filepath)
786                 if not result:
787                     message = wxMessageDialog(self, "Export successful", "Information", wxOK|wxICON_INFORMATION)
788                     message.ShowModal()
789                     message.Destroy()
790                 else:
791                     message = wxMessageDialog(self, result, "Error", wxOK|wxICON_ERROR)
792                     message.ShowModal()
793                     message.Destroy()
794             else:
795                 message = wxMessageDialog(self, "\"%s\" is not a valid folder!"%os.path.dirname(filepath), "Error", wxOK|wxICON_ERROR)
796                 message.ShowModal()
797                 message.Destroy()
798         dialog.Destroy()
799         event.Skip()
800
801 #-------------------------------------------------------------------------------
802 #                          Editing Profiles functions
803 #-------------------------------------------------------------------------------
804
805     def OnCommunicationMenu(self, event):
806         dictionary,current = self.Manager.GetCurrentCommunicationLists()
807         self.EditProfile("Edit DS-301 Profile", dictionary, current)
808         event.Skip()
809     
810     def OnOtherCommunicationMenu(self, event):
811         dictionary,current = self.Manager.GetCurrentDS302Lists()
812         self.EditProfile("Edit DS-301 Profile", dictionary, current)
813         event.Skip()
814     
815     def OnEditProfileMenu(self, event):
816         title = "Edit %s Profile"%self.Manager.GetCurrentProfileName()
817         dictionary,current = self.Manager.GetCurrentProfileLists()
818         self.EditProfile(title, dictionary, current)
819         event.Skip()
820     
821     def EditProfile(self, title, dictionary, current):
822         dialog = CommunicationDialog(self)
823         dialog.SetTitle(title)
824         dialog.SetIndexDictionary(dictionary)
825         dialog.SetCurrentList(current)
826         dialog.RefreshLists()
827         if dialog.ShowModal() == wxID_OK:
828             new_profile = dialog.GetCurrentList()
829             addinglist = []
830             removinglist = []
831             for index in new_profile:
832                 if index not in current:
833                     addinglist.append(index)
834             for index in current:
835                 if index not in new_profile:
836                     removinglist.append(index)
837             self.Manager.ManageEntriesOfCurrent(addinglist, removinglist)
838             self.Manager.GenerateMapList()
839             self.Manager.BufferCurrentNode()
840             self.RefreshBufferState()
841             self.RefreshCurrentIndexList()
842         dialog.Destroy()
843
844     def GetProfileCallBack(self, text):
845         def ProfileCallBack(event):
846             self.Manager.AddSpecificEntryToCurrent(text)
847             self.RefreshBufferState()
848             self.RefreshCurrentIndexList()
849             event.Skip()
850         return ProfileCallBack
851
852 #-------------------------------------------------------------------------------
853 #                         Edit Node informations function
854 #-------------------------------------------------------------------------------
855
856     def OnNodeInfosMenu(self, event):
857         dialog = NodeInfosDialog(self)
858         name, id, type, description = self.Manager.GetCurrentNodeInfos()
859         dialog.SetValues(name, id, type, description)
860         if dialog.ShowModal() == wxID_OK:
861             name, id, type, description = dialog.GetValues()
862             self.Manager.SetCurrentNodeInfos(name, id, type, description)
863             self.RefreshBufferState()
864             self.RefreshProfileMenu()
865             selected = self.FileOpened.GetSelection()
866             if selected >= 0:
867                 window = self.FileOpened.GetPage(selected)
868                 window.RefreshTable()
869         event.Skip()
870
871
872 #-------------------------------------------------------------------------------
873 #                           Add User Types and Variables
874 #-------------------------------------------------------------------------------
875         
876     def AddMapVariable(self):
877         index = self.Manager.GetCurrentNextMapIndex()
878         if index:
879             dialog = MapVariableDialog(self)
880             dialog.SetIndex(index)
881             if dialog.ShowModal() == wxID_OK:
882                 index, name, struct, number = dialog.GetValues()
883                 result = self.Manager.AddMapVariableToCurrent(index, name, struct, number)
884                 if type(result) != StringType:
885                     self.RefreshBufferState()
886                     self.RefreshCurrentIndexList()
887                 else:
888                     message = wxMessageDialog(self, result, "Error", wxOK|wxICON_ERROR)
889                     message.ShowModal()
890                     message.Destroy()
891             dialog.Destroy()
892         else:
893             message = wxMessageDialog(self, result, "No map variable index left!", wxOK|wxICON_ERROR)
894             message.ShowModal()
895             message.Destroy()
896         
897     def AddUserType(self):
898         dialog = UserTypeDialog(self)
899         dialog.SetTypeList(self.Manager.GetCustomisableTypes())
900         if dialog.ShowModal() == wxID_OK:
901             type, min, max, length = dialog.GetValues()
902             result = self.Manager.AddUserTypeToCurrent(type, min, max, length)
903             if not result:
904                 self.RefreshBufferState()
905                 self.RefreshCurrentIndexList()
906             else:
907                 message = wxMessageDialog(self, result, "Error", wxOK|wxICON_ERROR)
908                 message.ShowModal()
909                 message.Destroy()
910         dialog.Destroy()
911     
912
913 #-------------------------------------------------------------------------------
914 #                               Exception Handler
915 #-------------------------------------------------------------------------------
916
917 Max_Traceback_List_Size = 20
918
919 def Display_Exception_Dialog(e_type,e_value,e_tb):
920     trcbck_lst = []
921     for i,line in enumerate(traceback.extract_tb(e_tb)):
922         trcbck = " " + str(i+1) + ". "
923         if line[0].find(os.getcwd()) == -1:
924             trcbck += "file : " + str(line[0]) + ",   "
925         else:
926             trcbck += "file : " + str(line[0][len(os.getcwd()):]) + ",   "
927         trcbck += "line : " + str(line[1]) + ",   " + "function : " + str(line[2])
928         trcbck_lst.append(trcbck)
929         
930     # Allow clicking....
931     cap = wx.Window_GetCapture()
932     if cap:
933         cap.ReleaseMouse()
934
935     dlg = wx.SingleChoiceDialog(None, 
936         """
937 An error happens.
938
939 Click on OK for saving an error report.
940
941 Please contact LOLITech at:
942 +33 (0)3 29 52 95 67
943 bugs_objdictedit@lolitech.fr
944
945
946 Error:
947 """ +
948         str(e_type) + " : " + str(e_value), 
949         "Error",
950         trcbck_lst)
951     try:
952         res = (dlg.ShowModal() == wx.ID_OK)
953     finally:
954         dlg.Destroy()
955
956     return res
957
958 def Display_Error_Dialog(e_value):
959     message = wxMessageDialog(None, str(e_value), "Error", wxOK|wxICON_ERROR)
960     message.ShowModal()
961     message.Destroy()
962
963 def get_last_traceback(tb):
964     while tb.tb_next:
965         tb = tb.tb_next
966     return tb
967
968
969 def format_namespace(d, indent='    '):
970     return '\n'.join(['%s%s: %s' % (indent, k, repr(v)[:10000]) for k, v in d.iteritems()])
971
972
973 ignored_exceptions = [] # a problem with a line in a module is only reported once per session
974
975 def wxAddExceptHook(path, app_version='[No version]'):#, ignored_exceptions=[]):
976     
977     def handle_exception(e_type, e_value, e_traceback):
978         traceback.print_exception(e_type, e_value, e_traceback) # this is very helpful when there's an exception in the rest of this func
979         last_tb = get_last_traceback(e_traceback)
980         ex = (last_tb.tb_frame.f_code.co_filename, last_tb.tb_frame.f_lineno)
981         if str(e_value).startswith("!!!"):
982             Display_Error_Dialog(e_value)
983         elif ex not in ignored_exceptions:
984             ignored_exceptions.append(ex)
985             result = Display_Exception_Dialog(e_type,e_value,e_traceback)
986             if result:
987                 info = {
988                     'app-title' : wx.GetApp().GetAppName(), # app_title
989                     'app-version' : app_version,
990                     'wx-version' : wx.VERSION_STRING,
991                     'wx-platform' : wx.Platform,
992                     'python-version' : platform.python_version(), #sys.version.split()[0],
993                     'platform' : platform.platform(),
994                     'e-type' : e_type,
995                     'e-value' : e_value,
996                     'date' : time.ctime(),
997                     'cwd' : os.getcwd(),
998                     }
999                 if e_traceback:
1000                     info['traceback'] = ''.join(traceback.format_tb(e_traceback)) + '%s: %s' % (e_type, e_value)
1001                     last_tb = get_last_traceback(e_traceback)
1002                     exception_locals = last_tb.tb_frame.f_locals # the locals at the level of the stack trace where the exception actually occurred
1003                     info['locals'] = format_namespace(exception_locals)
1004                     if 'self' in exception_locals:
1005                         info['self'] = format_namespace(exception_locals['self'].__dict__)
1006                 
1007                 output = open(path+os.sep+"bug_report_"+info['date'].replace(':','-').replace(' ','_')+".txt",'w')
1008                 lst = info.keys()
1009                 lst.sort()
1010                 for a in lst:
1011                     output.write(a+":\n"+str(info[a])+"\n\n")
1012
1013     #sys.excepthook = lambda *args: wx.CallAfter(handle_exception, *args)
1014     sys.excepthook = handle_exception
1015
1016 if __name__ == '__main__':
1017     app = wxPySimpleApp()
1018     wxInitAllImageHandlers()
1019     
1020     # Install a exception handle for bug reports
1021     wxAddExceptHook(os.getcwd(),__version__)
1022     
1023     frame = objdictedit(None)
1024
1025     frame.Show()
1026     app.MainLoop()