2 # -*- coding: utf-8 -*-
4 #This file is part of CanFestival, a library implementing CanOpen Stack.
6 #Copyright (C): Edouard TISSERANT, Francis DUPIN and Laurent BESSARD
8 #See COPYING file for copyrights details.
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.
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.
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
27 import os, re, platform, sys, time, traceback, getopt
29 __version__ = "$Revision: 1.41 $"
31 from node import OD_Subindex, OD_MultipleSubindexes, OD_IdenticalSubindexes, OD_IdenticalIndexes
33 from nodemanager import *
34 from subindextable import *
35 from commondialogs import *
36 from doc_index.DS301_index import *
41 EVT_HTML_URL_CLICK = wx.NewId()
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())
49 class UrlClickHtmlWindow(wx.html.HtmlWindow):
50 """ HTML window that generates and OnLinkClicked event.
52 Use this to avoid having to override HTMLWindow
54 def OnLinkClicked(self, linkinfo):
55 wx.PostEvent(self, HtmlWindowUrlClick(linkinfo))
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)
61 wx.html.HtmlWindow.Bind(event, handler, source=source, id=id, id2=id2)
63 #-------------------------------------------------------------------------------
65 #-------------------------------------------------------------------------------
67 [ID_HTMLFRAME, ID_HTMLFRAMEHTMLCONTENT] = [wx.NewId() for _init_ctrls in range(2)]
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)
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)
81 def __init__(self, parent, opened):
82 self._init_ctrls(parent)
83 self.HtmlFrameOpened = opened
85 def SetHtmlCode(self, htmlcode):
86 self.HtmlContent.SetPage(htmlcode)
88 def SetHtmlPage(self, htmlpage):
89 self.HtmlContent.LoadPage(htmlpage)
91 def OnCloseFrame(self, event):
92 self.HtmlFrameOpened.remove(self.GetTitle())
95 def OnLinkClick(self, event):
96 url = event.linkinfo[0]
100 wx.MessageBox('Please point your browser at: %s' % url)
108 ScriptDirectory = os.path.split(os.path.realpath(__file__))[0]
110 [ID_OBJDICTEDIT, ID_OBJDICTEDITFILEOPENED,
111 ID_OBJDICTEDITHELPBAR,
112 ] = [wx.NewId() for _init_ctrls in range(3)]
114 [ID_OBJDICTEDITFILEMENUIMPORTEDS, ID_OBJDICTEDITFILEMENUEXPORTEDS,
115 ID_OBJDICTEDITFILEMENUEXPORTC,
116 ] = [wx.NewId() for _init_coll_FileMenu_Items in range(3)]
118 [ID_OBJDICTEDITEDITMENUNODEINFOS, ID_OBJDICTEDITEDITMENUDS301PROFILE,
119 ID_OBJDICTEDITEDITMENUDS302PROFILE, ID_OBJDICTEDITEDITMENUOTHERPROFILE,
120 ] = [wx.NewId() for _init_coll_EditMenu_Items in range(4)]
122 [ID_OBJDICTEDITADDMENUSDOSERVER, ID_OBJDICTEDITADDMENUSDOCLIENT,
123 ID_OBJDICTEDITADDMENUPDOTRANSMIT, ID_OBJDICTEDITADDMENUPDORECEIVE,
124 ID_OBJDICTEDITADDMENUMAPVARIABLE, ID_OBJDICTEDITADDMENUUSERTYPE,
125 ] = [wx.NewId() for _init_coll_AddMenu_Items in range(6)]
127 class objdictedit(wx.Frame):
128 def _init_coll_MenuBar_Menus(self, parent):
129 parent.Append(menu=self.FileMenu, title='File')
130 parent.Append(menu=self.EditMenu, title='Edit')
131 parent.Append(menu=self.AddMenu, title='Add')
132 parent.Append(menu=self.HelpMenu, title='Help')
134 def _init_coll_FileMenu_Items(self, parent):
135 parent.Append(help='', id=wx.ID_NEW,
136 kind=wx.ITEM_NORMAL, text='New\tCTRL+N')
137 parent.Append(help='', id=wx.ID_OPEN,
138 kind=wx.ITEM_NORMAL, text='Open\tCTRL+O')
139 parent.Append(help='', id=wx.ID_CLOSE,
140 kind=wx.ITEM_NORMAL, text='Close\tCTRL+W')
141 parent.AppendSeparator()
142 parent.Append(help='', id=wx.ID_SAVE,
143 kind=wx.ITEM_NORMAL, text='Save\tCTRL+S')
144 parent.Append(help='', id=wx.ID_SAVEAS,
145 kind=wx.ITEM_NORMAL, text='Save As...\tALT+S')
146 parent.AppendSeparator()
147 parent.Append(help='', id=ID_OBJDICTEDITFILEMENUIMPORTEDS,
148 kind=wx.ITEM_NORMAL, text='Import EDS file')
149 parent.Append(help='', id=ID_OBJDICTEDITFILEMENUEXPORTEDS,
150 kind=wx.ITEM_NORMAL, text='Export to EDS file')
151 parent.Append(help='', id=ID_OBJDICTEDITFILEMENUEXPORTC,
152 kind=wx.ITEM_NORMAL, text='Build Dictionary\tCTRL+B')
153 parent.AppendSeparator()
154 parent.Append(help='', id=wx.ID_EXIT,
155 kind=wx.ITEM_NORMAL, text='Exit')
156 self.Bind(wx.EVT_MENU, self.OnNewMenu, id=wx.ID_NEW)
157 self.Bind(wx.EVT_MENU, self.OnOpenMenu, id=wx.ID_OPEN)
158 self.Bind(wx.EVT_MENU, self.OnCloseMenu, id=wx.ID_CLOSE)
159 self.Bind(wx.EVT_MENU, self.OnSaveMenu, id=wx.ID_SAVE)
160 self.Bind(wx.EVT_MENU, self.OnSaveAsMenu, id=wx.ID_SAVEAS)
161 self.Bind(wx.EVT_MENU, self.OnImportEDSMenu,
162 id=ID_OBJDICTEDITFILEMENUIMPORTEDS)
163 self.Bind(wx.EVT_MENU, self.OnExportEDSMenu,
164 id=ID_OBJDICTEDITFILEMENUEXPORTEDS)
165 self.Bind(wx.EVT_MENU, self.OnExportCMenu,
166 id=ID_OBJDICTEDITFILEMENUEXPORTC)
167 self.Bind(wx.EVT_MENU, self.OnQuitMenu, id=wx.ID_EXIT)
169 def _init_coll_EditMenu_Items(self, parent):
170 parent.Append(help='', id=wx.ID_REFRESH,
171 kind=wx.ITEM_NORMAL, text='Refresh\tCTRL+R')
172 parent.AppendSeparator()
173 parent.Append(help='', id=wx.ID_UNDO,
174 kind=wx.ITEM_NORMAL, text='Undo\tCTRL+Z')
175 parent.Append(help='', id=wx.ID_REDO,
176 kind=wx.ITEM_NORMAL, text='Redo\tCTRL+Y')
177 parent.AppendSeparator()
178 parent.Append(help='', id=ID_OBJDICTEDITEDITMENUNODEINFOS,
179 kind=wx.ITEM_NORMAL, text='Node infos')
180 parent.Append(help='', id=ID_OBJDICTEDITEDITMENUDS301PROFILE,
181 kind=wx.ITEM_NORMAL, text='DS-301 Profile')
182 parent.Append(help='', id=ID_OBJDICTEDITEDITMENUDS302PROFILE,
183 kind=wx.ITEM_NORMAL, text='DS-302 Profile')
184 parent.Append(help='', id=ID_OBJDICTEDITEDITMENUOTHERPROFILE,
185 kind=wx.ITEM_NORMAL, text='Other Profile')
186 self.Bind(wx.EVT_MENU, self.OnRefreshMenu, id=wx.ID_REFRESH)
187 self.Bind(wx.EVT_MENU, self.OnUndoMenu, id=wx.ID_UNDO)
188 self.Bind(wx.EVT_MENU, self.OnRedoMenu, id=wx.ID_REDO)
189 self.Bind(wx.EVT_MENU, self.OnNodeInfosMenu,
190 id=ID_OBJDICTEDITEDITMENUNODEINFOS)
191 self.Bind(wx.EVT_MENU, self.OnCommunicationMenu,
192 id=ID_OBJDICTEDITEDITMENUDS301PROFILE)
193 self.Bind(wx.EVT_MENU, self.OnOtherCommunicationMenu,
194 id=ID_OBJDICTEDITEDITMENUDS302PROFILE)
195 self.Bind(wx.EVT_MENU, self.OnEditProfileMenu,
196 id=ID_OBJDICTEDITEDITMENUOTHERPROFILE)
198 def _init_coll_AddMenu_Items(self, parent):
199 parent.Append(help='', id=ID_OBJDICTEDITADDMENUSDOSERVER,
200 kind=wx.ITEM_NORMAL, text='SDO Server')
201 parent.Append(help='', id=ID_OBJDICTEDITADDMENUSDOCLIENT,
202 kind=wx.ITEM_NORMAL, text='SDO Client')
203 parent.Append(help='', id=ID_OBJDICTEDITADDMENUPDOTRANSMIT,
204 kind=wx.ITEM_NORMAL, text='PDO Transmit')
205 parent.Append(help='', id=ID_OBJDICTEDITADDMENUPDORECEIVE,
206 kind=wx.ITEM_NORMAL, text='PDO Receive')
207 parent.Append(help='', id=ID_OBJDICTEDITADDMENUMAPVARIABLE,
208 kind=wx.ITEM_NORMAL, text='Map Variable')
209 parent.Append(help='', id=ID_OBJDICTEDITADDMENUUSERTYPE,
210 kind=wx.ITEM_NORMAL, text='User Type')
211 self.Bind(wx.EVT_MENU, self.OnAddSDOServerMenu,
212 id=ID_OBJDICTEDITADDMENUSDOSERVER)
213 self.Bind(wx.EVT_MENU, self.OnAddSDOClientMenu,
214 id=ID_OBJDICTEDITADDMENUSDOCLIENT)
215 self.Bind(wx.EVT_MENU, self.OnAddPDOTransmitMenu,
216 id=ID_OBJDICTEDITADDMENUPDOTRANSMIT)
217 self.Bind(wx.EVT_MENU, self.OnAddPDOReceiveMenu,
218 id=ID_OBJDICTEDITADDMENUPDORECEIVE)
219 self.Bind(wx.EVT_MENU, self.OnAddMapVariableMenu,
220 id=ID_OBJDICTEDITADDMENUMAPVARIABLE)
221 self.Bind(wx.EVT_MENU, self.OnAddUserTypeMenu,
222 id=ID_OBJDICTEDITADDMENUUSERTYPE)
224 def _init_coll_HelpMenu_Items(self, parent):
225 parent.Append(help='', id=wx.ID_HELP,
226 kind=wx.ITEM_NORMAL, text='DS-301 Standard\tF1')
227 self.Bind(wx.EVT_MENU, self.OnHelpDS301Menu, id=wx.ID_HELP)
228 parent.Append(help='', id=wx.ID_HELP_CONTEXT,
229 kind=wx.ITEM_NORMAL, text='CAN Festival Docs\tF2')
230 self.Bind(wx.EVT_MENU, self.OnHelpCANFestivalMenu, id=wx.ID_HELP_CONTEXT)
232 parent.Append(help='', id=wx.ID_ABOUT,
233 kind=wx.ITEM_NORMAL, text='About')
234 self.Bind(wx.EVT_MENU, self.OnAboutMenu, id=wx.ID_ABOUT)
236 def _init_coll_HelpBar_Fields(self, parent):
237 parent.SetFieldsCount(3)
239 parent.SetStatusText(number=0, text='')
240 parent.SetStatusText(number=1, text='')
241 parent.SetStatusText(number=2, text='')
243 parent.SetStatusWidths([100, 110, -1])
245 def _init_utils(self):
246 self.MenuBar = wx.MenuBar()
247 self.MenuBar.SetEvtHandlerEnabled(True)
249 self.FileMenu = wx.Menu(title='')
250 self.EditMenu = wx.Menu(title='')
251 self.AddMenu = wx.Menu(title='')
252 self.HelpMenu = wx.Menu(title='')
254 self._init_coll_MenuBar_Menus(self.MenuBar)
255 self._init_coll_FileMenu_Items(self.FileMenu)
256 self._init_coll_EditMenu_Items(self.EditMenu)
257 self._init_coll_AddMenu_Items(self.AddMenu)
258 self._init_coll_HelpMenu_Items(self.HelpMenu)
260 def _init_ctrls(self, prnt):
261 wx.Frame.__init__(self, id=ID_OBJDICTEDIT, name='objdictedit',
262 parent=prnt, pos=wx.Point(149, 178), size=wx.Size(1000, 700),
263 style=wx.DEFAULT_FRAME_STYLE, title='Objdictedit')
265 self.SetClientSize(wx.Size(1000, 700))
266 self.SetMenuBar(self.MenuBar)
267 self.Bind(wx.EVT_CLOSE, self.OnCloseFrame)
269 self.FileOpened = wx.Notebook(id=ID_OBJDICTEDITFILEOPENED,
270 name='FileOpened', parent=self, pos=wx.Point(0, 0),
271 size=wx.Size(0, 0), style=0)
272 self.FileOpened.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED,
273 self.OnFileSelectedChanged, id=ID_OBJDICTEDITFILEOPENED)
275 self.HelpBar = wx.StatusBar(id=ID_OBJDICTEDITHELPBAR, name='HelpBar',
276 parent=self, style=wx.ST_SIZEGRIP)
277 self._init_coll_HelpBar_Fields(self.HelpBar)
278 self.SetStatusBar(self.HelpBar)
280 def __init__(self, parent, filesOpen = []):
281 self._init_ctrls(parent)
282 self.HtmlFrameOpened = []
285 icon = wx.Icon(os.path.join(ScriptDirectory,"networkedit.ico"),wx.BITMAP_TYPE_ICO)
288 self.Manager = NodeManager()
289 for filepath in filesOpen:
290 result = self.Manager.OpenFileInCurrent(filepath)
291 if type(result) == IntType:
292 new_editingpanel = EditingPanel(self.FileOpened, self, self.Manager)
293 new_editingpanel.SetIndex(result)
294 self.FileOpened.AddPage(new_editingpanel, "")
295 window = self.FileOpened.GetPage(0)
297 self.Manager.ChangeCurrentNode(window.GetIndex())
298 self.FileOpened.SetSelection(0)
299 if self.Manager.CurrentDS302Defined():
300 self.EditMenu.Enable(ID_OBJDICTEDITEDITMENUDS302PROFILE, True)
302 self.EditMenu.Enable(ID_OBJDICTEDITEDITMENUDS302PROFILE, False)
303 self.RefreshEditMenu()
304 self.RefreshBufferState()
305 self.RefreshProfileMenu()
307 self.RefreshMainMenu()
309 def OnAddSDOServerMenu(self, event):
310 self.Manager.AddSDOServerToCurrent()
311 self.RefreshBufferState()
312 self.RefreshCurrentIndexList()
315 def OnAddSDOClientMenu(self, event):
316 self.Manager.AddSDOClientToCurrent()
317 self.RefreshBufferState()
318 self.RefreshCurrentIndexList()
321 def OnAddPDOTransmitMenu(self, event):
322 self.Manager.AddPDOTransmitToCurrent()
323 self.RefreshBufferState()
324 self.RefreshCurrentIndexList()
327 def OnAddPDOReceiveMenu(self, event):
328 self.Manager.AddPDOReceiveToCurrent()
329 self.RefreshBufferState()
330 self.RefreshCurrentIndexList()
333 def OnAddMapVariableMenu(self, event):
334 self.AddMapVariable()
337 def OnAddUserTypeMenu(self, event):
341 def OnFileSelectedChanged(self, event):
342 selected = event.GetSelection()
343 # At init selected = -1
345 window = self.FileOpened.GetPage(selected)
347 self.Manager.ChangeCurrentNode(window.GetIndex())
348 wx.CallAfter(self.RefreshBufferState)
349 self.RefreshStatusBar()
350 self.RefreshProfileMenu()
353 def OnHelpDS301Menu(self, event):
355 selected = self.FileOpened.GetSelection()
357 window = self.FileOpened.GetPage(selected)
358 result = window.GetSelection()
361 index, subIndex = result
362 result = OpenPDFDocIndex(index, ScriptDirectory)
363 if type(result) == StringType:
364 message = wx.MessageDialog(self, result, "ERROR", wx.OK|wx.ICON_ERROR)
368 result = OpenPDFDocIndex(None, ScriptDirectory)
369 if type(result) == StringType:
370 message = wx.MessageDialog(self, result, "ERROR", wx.OK|wx.ICON_ERROR)
375 def OnHelpCANFestivalMenu(self, event):
376 #self.OpenHtmlFrame("CAN Festival Reference", os.path.join(ScriptDirectory, "doc/canfestival.html"), wx.Size(1000, 600))
377 if wx.Platform == '__WXMSW__':
378 readerpath = get_acroversion()
379 readerexepath = os.path.join(readerpath,"AcroRd32.exe")
380 if(os.path.isfile(readerexepath)):
381 os.spawnl(os.P_DETACH, readerexepath, "AcroRd32.exe", '"%s"'%os.path.join(ScriptDirectory, "doc","manual_en.pdf"))
383 os.system("xpdf -remote CANFESTIVAL %s %d &"%(os.path.join(ScriptDirectory, "doc/manual_en.pdf"),16))
386 def OnAboutMenu(self, event):
387 self.OpenHtmlFrame("About CAN Festival", os.path.join(ScriptDirectory, "doc/about.html"), wx.Size(500, 450))
390 def OpenHtmlFrame(self, title, file, size):
391 if title not in self.HtmlFrameOpened:
392 self.HtmlFrameOpened.append(title)
393 window = HtmlFrame(self, self.HtmlFrameOpened)
394 window.SetTitle(title)
395 window.SetHtmlPage(file)
396 window.SetClientSize(size)
399 def OnQuitMenu(self, event):
403 def OnCloseFrame(self, event):
404 if self.Manager.OneFileHasChanged():
405 dialog = wx.MessageDialog(self, "There are changes, do you want to save?", "Close Application", wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
406 answer = dialog.ShowModal()
408 if answer == wx.ID_YES:
409 self.Manager.ChangeCurrentNode(0)
410 for i in xrange(self.FileOpened.GetPageCount()):
411 window = self.FileOpened.GetPage(i)
412 self.Manager.ChangeCurrentNode(window.GetIndex())
413 if self.Manager.CurrentIsSaved():
414 self.Manager.CloseCurrent()
417 self.Manager.CloseCurrent(True)
419 elif answer == wx.ID_NO:
420 for i in xrange(self.FileOpened.GetPageCount()):
421 self.Manager.CloseCurrent(True)
422 wx.CallAfter(self.Close)
427 #-------------------------------------------------------------------------------
429 #-------------------------------------------------------------------------------
431 def RefreshTitle(self):
432 if self.FileOpened.GetPageCount() > 0:
433 self.SetTitle("Objdictedit - %s"%self.Manager.GetCurrentFilename())
435 self.SetTitle("Objdictedit")
437 def OnRefreshMenu(self, event):
438 self.RefreshCurrentIndexList()
441 def RefreshCurrentIndexList(self):
442 selected = self.FileOpened.GetSelection()
443 window = self.FileOpened.GetPage(selected)
444 window.RefreshIndexList()
446 def RefreshStatusBar(self):
447 if self and self.HelpBar:
448 selected = self.FileOpened.GetSelection()
450 window = self.FileOpened.GetPage(selected)
451 selection = window.GetSelection()
453 index, subIndex = selection
454 if self.Manager.IsCurrentEntry(index):
455 self.HelpBar.SetStatusText("Index: 0x%04X"%index, 0)
456 self.HelpBar.SetStatusText("Subindex: 0x%02X"%subIndex, 1)
457 entryinfos = self.Manager.GetEntryInfos(index)
458 name = entryinfos["name"]
459 category = "Optional"
460 if entryinfos["need"]:
461 category = "Mandatory"
464 if entryinfos["struct"] & OD_IdenticalIndexes:
465 number = " possibly defined %d times"%entryinfos["nbmax"]
466 if entryinfos["struct"] & OD_IdenticalSubindexes:
468 elif entryinfos["struct"] & OD_MultipleSubindexes:
470 text = "%s: %s entry of struct %s%s."%(name,category,struct,number)
471 self.HelpBar.SetStatusText(text, 2)
474 self.HelpBar.SetStatusText("", i)
477 self.HelpBar.SetStatusText("", i)
479 def RefreshMainMenu(self):
481 if self.FileOpened.GetPageCount() > 0:
482 self.MenuBar.EnableTop(1, True)
483 self.MenuBar.EnableTop(2, True)
484 self.FileMenu.Enable(wx.ID_CLOSE, True)
485 self.FileMenu.Enable(wx.ID_SAVE, True)
486 self.FileMenu.Enable(wx.ID_SAVEAS, True)
487 self.FileMenu.Enable(ID_OBJDICTEDITFILEMENUEXPORTEDS, True)
488 self.FileMenu.Enable(ID_OBJDICTEDITFILEMENUEXPORTC, True)
490 self.MenuBar.EnableTop(1, False)
491 self.MenuBar.EnableTop(2, False)
492 self.FileMenu.Enable(wx.ID_CLOSE, False)
493 self.FileMenu.Enable(wx.ID_SAVE, False)
494 self.FileMenu.Enable(wx.ID_SAVEAS, False)
495 self.FileMenu.Enable(ID_OBJDICTEDITFILEMENUEXPORTEDS, False)
496 self.FileMenu.Enable(ID_OBJDICTEDITFILEMENUEXPORTC, False)
498 def RefreshEditMenu(self):
500 if self.FileOpened.GetPageCount() > 0:
501 undo, redo = self.Manager.GetCurrentBufferState()
502 self.EditMenu.Enable(wx.ID_UNDO, undo)
503 self.EditMenu.Enable(wx.ID_REDO, redo)
505 self.EditMenu.Enable(wx.ID_UNDO, False)
506 self.EditMenu.Enable(wx.ID_REDO, False)
508 def RefreshProfileMenu(self):
510 profile = self.Manager.GetCurrentProfileName()
511 edititem = self.EditMenu.FindItemById(ID_OBJDICTEDITEDITMENUOTHERPROFILE)
513 length = self.AddMenu.GetMenuItemCount()
514 for i in xrange(length-6):
515 additem = self.AddMenu.FindItemByPosition(6)
516 self.AddMenu.Delete(additem.GetId())
517 if profile not in ("None", "DS-301"):
518 edititem.SetText("%s Profile"%profile)
519 edititem.Enable(True)
520 self.AddMenu.AppendSeparator()
521 for text, indexes in self.Manager.GetCurrentSpecificMenu():
523 self.AddMenu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=text)
524 self.Bind(wx.EVT_MENU, self.GetProfileCallBack(text), id=new_id)
526 edititem.SetText("Other Profile")
527 edititem.Enable(False)
530 #-------------------------------------------------------------------------------
532 #-------------------------------------------------------------------------------
534 def RefreshBufferState(self):
535 fileopened = self.Manager.GetAllFilenames()
536 for idx, filename in enumerate(fileopened):
537 self.FileOpened.SetPageText(idx, filename)
538 self.RefreshEditMenu()
541 def OnUndoMenu(self, event):
542 self.Manager.LoadCurrentPrevious()
543 self.RefreshCurrentIndexList()
544 self.RefreshBufferState()
547 def OnRedoMenu(self, event):
548 self.Manager.LoadCurrentNext()
549 self.RefreshCurrentIndexList()
550 self.RefreshBufferState()
554 #-------------------------------------------------------------------------------
555 # Load and Save Funtions
556 #-------------------------------------------------------------------------------
558 def OnNewMenu(self, event):
560 dialog = CreateNodeDialog(self)
561 if dialog.ShowModal() == wx.ID_OK:
562 name, id, nodetype, description = dialog.GetValues()
563 profile, filepath = dialog.GetProfile()
564 NMT = dialog.GetNMTManagement()
565 options = dialog.GetOptions()
566 result = self.Manager.CreateNewNode(name, id, nodetype, description, profile, filepath, NMT, options)
567 if type(result) == IntType:
568 new_editingpanel = EditingPanel(self.FileOpened, self, self.Manager)
569 new_editingpanel.SetIndex(result)
570 self.FileOpened.AddPage(new_editingpanel, "")
571 self.FileOpened.SetSelection(self.FileOpened.GetPageCount() - 1)
572 self.EditMenu.Enable(ID_OBJDICTEDITEDITMENUDS302PROFILE, False)
573 if "DS302" in options:
574 self.EditMenu.Enable(ID_OBJDICTEDITEDITMENUDS302PROFILE, True)
575 self.RefreshBufferState()
576 self.RefreshProfileMenu()
577 self.RefreshMainMenu()
579 message = wx.MessageDialog(self, result, "ERROR", wx.OK|wx.ICON_ERROR)
585 def OnOpenMenu(self, event):
586 filepath = self.Manager.GetCurrentFilePath()
588 directory = os.path.dirname(filepath)
590 directory = os.getcwd()
591 dialog = wx.FileDialog(self, "Choose a file", directory, "", "OD files (*.od)|*.od|All files|*.*", wx.OPEN|wx.CHANGE_DIR)
592 if dialog.ShowModal() == wx.ID_OK:
593 filepath = dialog.GetPath()
594 if os.path.isfile(filepath):
595 result = self.Manager.OpenFileInCurrent(filepath)
596 if type(result) == IntType:
597 new_editingpanel = EditingPanel(self.FileOpened, self, self.Manager)
598 new_editingpanel.SetIndex(result)
599 self.FileOpened.AddPage(new_editingpanel, "")
600 self.FileOpened.SetSelection(self.FileOpened.GetPageCount() - 1)
601 if self.Manager.CurrentDS302Defined():
602 self.EditMenu.Enable(ID_OBJDICTEDITEDITMENUDS302PROFILE, True)
604 self.EditMenu.Enable(ID_OBJDICTEDITEDITMENUDS302PROFILE, False)
605 self.RefreshEditMenu()
606 self.RefreshBufferState()
607 self.RefreshProfileMenu()
608 self.RefreshMainMenu()
610 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
616 def OnSaveMenu(self, event):
620 def OnSaveAsMenu(self, event):
625 result = self.Manager.SaveCurrentInFile()
628 elif type(result) != StringType:
629 self.RefreshBufferState()
631 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
636 filepath = self.Manager.GetCurrentFilePath()
638 directory, filename = os.path.split(filepath)
640 directory, filename = os.getcwd(), "%s.od"%self.Manager.GetCurrentNodeInfos()[0]
641 dialog = wx.FileDialog(self, "Choose a file", directory, filename, "OD files (*.od)|*.od|All files|*.*", wx.SAVE|wx.OVERWRITE_PROMPT|wx.CHANGE_DIR)
642 if dialog.ShowModal() == wx.ID_OK:
643 filepath = dialog.GetPath()
644 if os.path.isdir(os.path.dirname(filepath)):
645 result = self.Manager.SaveCurrentInFile(filepath)
646 if type(result) != StringType:
647 self.RefreshBufferState()
649 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
653 message = wx.MessageDialog(self, "%s is not a valid folder!"%os.path.dirname(filepath), "Error", wx.OK|wx.ICON_ERROR)
658 def OnCloseMenu(self, event):
660 result = self.Manager.CloseCurrent()
662 dialog = wx.MessageDialog(self, "There are changes, do you want to save?", "Close File", wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
663 answer = dialog.ShowModal()
665 if answer == wx.ID_YES:
666 self.OnSaveMenu(event)
667 if self.Manager.CurrentIsSaved():
668 self.Manager.CloseCurrent()
669 elif answer == wx.ID_NO:
670 self.Manager.CloseCurrent(True)
671 if self.FileOpened.GetPageCount() > self.Manager.GetBufferNumber():
672 current = self.FileOpened.GetSelection()
673 self.FileOpened.DeletePage(current)
674 if self.FileOpened.GetPageCount() > 0:
675 self.FileOpened.SetSelection(min(current, self.FileOpened.GetPageCount() - 1))
676 self.RefreshBufferState()
677 self.RefreshMainMenu()
681 #-------------------------------------------------------------------------------
682 # Import and Export Functions
683 #-------------------------------------------------------------------------------
685 def OnImportEDSMenu(self, event):
686 dialog = wx.FileDialog(self, "Choose a file", os.getcwd(), "", "EDS files (*.eds)|*.eds|All files|*.*", wx.OPEN|wx.CHANGE_DIR)
687 if dialog.ShowModal() == wx.ID_OK:
688 filepath = dialog.GetPath()
689 if os.path.isfile(filepath):
690 result = self.Manager.ImportCurrentFromEDSFile(filepath)
691 if type(result) == IntType:
692 new_editingpanel = EditingPanel(self.FileOpened, self, self.Manager)
693 new_editingpanel.SetIndex(result)
694 self.FileOpened.AddPage(new_editingpanel, "")
695 self.FileOpened.SetSelection(self.FileOpened.GetPageCount() - 1)
696 self.RefreshBufferState()
697 self.RefreshCurrentIndexList()
698 self.RefreshProfileMenu()
699 self.RefreshMainMenu()
700 message = wx.MessageDialog(self, "Import successful", "Information", wx.OK|wx.ICON_INFORMATION)
704 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
708 message = wx.MessageDialog(self, "\"%s\" is not a valid file!"%filepath, "Error", wx.OK|wx.ICON_ERROR)
715 def OnExportEDSMenu(self, event):
716 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)
717 if dialog.ShowModal() == wx.ID_OK:
718 filepath = dialog.GetPath()
719 if os.path.isdir(os.path.dirname(filepath)):
720 path, extend = os.path.splitext(filepath)
721 if extend in ("", "."):
722 filepath = path + ".eds"
723 result = self.Manager.ExportCurrentToEDSFile(filepath)
725 message = wx.MessageDialog(self, "Export successful", "Information", wx.OK|wx.ICON_INFORMATION)
729 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
733 message = wx.MessageDialog(self, "\"%s\" is not a valid folder!"%os.path.dirname(filepath), "Error", wx.OK|wx.ICON_ERROR)
739 def OnExportCMenu(self, event):
740 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)
741 if dialog.ShowModal() == wx.ID_OK:
742 filepath = dialog.GetPath()
743 if os.path.isdir(os.path.dirname(filepath)):
744 path, extend = os.path.splitext(filepath)
745 if extend in ("", "."):
746 filepath = path + ".c"
747 result = self.Manager.ExportCurrentToCFile(filepath)
749 message = wx.MessageDialog(self, "Export successful", "Information", wx.OK|wx.ICON_INFORMATION)
753 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
757 message = wx.MessageDialog(self, "\"%s\" is not a valid folder!"%os.path.dirname(filepath), "Error", wx.OK|wx.ICON_ERROR)
763 #-------------------------------------------------------------------------------
764 # Editing Profiles functions
765 #-------------------------------------------------------------------------------
767 def OnCommunicationMenu(self, event):
768 dictionary,current = self.Manager.GetCurrentCommunicationLists()
769 self.EditProfile("Edit DS-301 Profile", dictionary, current)
772 def OnOtherCommunicationMenu(self, event):
773 dictionary,current = self.Manager.GetCurrentDS302Lists()
774 self.EditProfile("Edit DS-301 Profile", dictionary, current)
777 def OnEditProfileMenu(self, event):
778 title = "Edit %s Profile"%self.Manager.GetCurrentProfileName()
779 dictionary,current = self.Manager.GetCurrentProfileLists()
780 self.EditProfile(title, dictionary, current)
783 def EditProfile(self, title, dictionary, current):
784 dialog = CommunicationDialog(self)
785 dialog.SetTitle(title)
786 dialog.SetIndexDictionary(dictionary)
787 dialog.SetCurrentList(current)
788 dialog.RefreshLists()
789 if dialog.ShowModal() == wx.ID_OK:
790 new_profile = dialog.GetCurrentList()
793 for index in new_profile:
794 if index not in current:
795 addinglist.append(index)
796 for index in current:
797 if index not in new_profile:
798 removinglist.append(index)
799 self.Manager.ManageEntriesOfCurrent(addinglist, removinglist)
800 self.Manager.BufferCurrentNode()
801 self.RefreshBufferState()
802 self.RefreshCurrentIndexList()
805 def GetProfileCallBack(self, text):
806 def ProfileCallBack(event):
807 self.Manager.AddSpecificEntryToCurrent(text)
808 self.RefreshBufferState()
809 self.RefreshCurrentIndexList()
811 return ProfileCallBack
813 #-------------------------------------------------------------------------------
814 # Edit Node informations function
815 #-------------------------------------------------------------------------------
817 def OnNodeInfosMenu(self, event):
818 dialog = NodeInfosDialog(self)
819 name, id, type, description = self.Manager.GetCurrentNodeInfos()
820 defaultstringsize = self.Manager.GetCurrentNodeDefaultStringSize()
821 dialog.SetValues(name, id, type, description, defaultstringsize)
822 if dialog.ShowModal() == wx.ID_OK:
823 name, id, type, description, defaultstringsize = dialog.GetValues()
824 self.Manager.SetCurrentNodeInfos(name, id, type, description)
825 self.Manager.SetCurrentNodeDefaultStringSize(defaultstringsize)
826 self.RefreshBufferState()
827 self.RefreshProfileMenu()
828 selected = self.FileOpened.GetSelection()
830 window = self.FileOpened.GetPage(selected)
831 window.RefreshTable()
835 #-------------------------------------------------------------------------------
836 # Add User Types and Variables
837 #-------------------------------------------------------------------------------
839 def AddMapVariable(self):
840 index = self.Manager.GetCurrentNextMapIndex()
842 dialog = MapVariableDialog(self)
843 dialog.SetIndex(index)
844 if dialog.ShowModal() == wx.ID_OK:
845 index, name, struct, number = dialog.GetValues()
846 result = self.Manager.AddMapVariableToCurrent(index, name, struct, number)
847 if type(result) != StringType:
848 self.RefreshBufferState()
849 self.RefreshCurrentIndexList()
851 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
856 message = wx.MessageDialog(self, result, "No map variable index left!", wx.OK|wx.ICON_ERROR)
860 def AddUserType(self):
861 dialog = UserTypeDialog(self)
862 dialog.SetTypeList(self.Manager.GetCustomisableTypes())
863 if dialog.ShowModal() == wx.ID_OK:
864 type, min, max, length = dialog.GetValues()
865 result = self.Manager.AddUserTypeToCurrent(type, min, max, length)
867 self.RefreshBufferState()
868 self.RefreshCurrentIndexList()
870 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
876 #-------------------------------------------------------------------------------
878 #-------------------------------------------------------------------------------
880 Max_Traceback_List_Size = 20
882 def Display_Exception_Dialog(e_type,e_value,e_tb):
884 for i,line in enumerate(traceback.extract_tb(e_tb)):
885 trcbck = " " + str(i+1) + ". "
886 if line[0].find(os.getcwd()) == -1:
887 trcbck += "file : " + str(line[0]) + ", "
889 trcbck += "file : " + str(line[0][len(os.getcwd()):]) + ", "
890 trcbck += "line : " + str(line[1]) + ", " + "function : " + str(line[2])
891 trcbck_lst.append(trcbck)
894 cap = wx.Window_GetCapture()
898 dlg = wx.SingleChoiceDialog(None,
902 Click on OK for saving an error report.
904 Please contact LOLITech at:
906 bugs_objdictedit@lolitech.fr
911 str(e_type) + " : " + str(e_value),
915 res = (dlg.ShowModal() == wx.ID_OK)
921 def Display_Error_Dialog(e_value):
922 message = wx.MessageDialog(None, str(e_value), "Error", wx.OK|wx.ICON_ERROR)
926 def get_last_traceback(tb):
932 def format_namespace(d, indent=' '):
933 return '\n'.join(['%s%s: %s' % (indent, k, repr(v)[:10000]) for k, v in d.iteritems()])
936 ignored_exceptions = [] # a problem with a line in a module is only reported once per session
938 def AddExceptHook(path, app_version='[No version]'):#, ignored_exceptions=[]):
940 def handle_exception(e_type, e_value, e_traceback):
941 traceback.print_exception(e_type, e_value, e_traceback) # this is very helpful when there's an exception in the rest of this func
942 last_tb = get_last_traceback(e_traceback)
943 ex = (last_tb.tb_frame.f_code.co_filename, last_tb.tb_frame.f_lineno)
944 if str(e_value).startswith("!!!"):
945 Display_Error_Dialog(e_value)
946 elif ex not in ignored_exceptions:
947 ignored_exceptions.append(ex)
948 result = Display_Exception_Dialog(e_type,e_value,e_traceback)
951 'app-title' : wx.GetApp().GetAppName(), # app_title
952 'app-version' : app_version,
953 'wx-version' : wx.VERSION_STRING,
954 'wx-platform' : wx.Platform,
955 'python-version' : platform.python_version(), #sys.version.split()[0],
956 'platform' : platform.platform(),
959 'date' : time.ctime(),
963 info['traceback'] = ''.join(traceback.format_tb(e_traceback)) + '%s: %s' % (e_type, e_value)
964 last_tb = get_last_traceback(e_traceback)
965 exception_locals = last_tb.tb_frame.f_locals # the locals at the level of the stack trace where the exception actually occurred
966 info['locals'] = format_namespace(exception_locals)
967 if 'self' in exception_locals:
968 info['self'] = format_namespace(exception_locals['self'].__dict__)
970 output = open(path+os.sep+"bug_report_"+info['date'].replace(':','-').replace(' ','_')+".txt",'w')
974 output.write(a+":\n"+str(info[a])+"\n\n")
976 #sys.excepthook = lambda *args: wx.CallAfter(handle_exception, *args)
977 sys.excepthook = handle_exception
979 if __name__ == '__main__':
981 print "\nUsage of objdictedit.py :"
982 print "\n %s [Filepath, ...]\n"%sys.argv[0]
985 opts, args = getopt.getopt(sys.argv[1:], "h", ["help"])
986 except getopt.GetoptError:
987 # print help information and exit:
992 if o in ("-h", "--help"):
996 app = wx.PySimpleApp()
997 wx.InitAllImageHandlers()
999 # Install a exception handle for bug reports
1000 AddExceptHook(os.getcwd(),__version__)
1002 frame = objdictedit(None, args)