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