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