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.47 $"
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):
130 parent.Append(menu=self.FileMenu, title='File')
131 parent.Append(menu=self.EditMenu, title='Edit')
132 parent.Append(menu=self.AddMenu, title='Add')
133 parent.Append(menu=self.HelpMenu, title='Help')
135 def _init_coll_FileMenu_Items(self, parent):
136 parent.Append(help='', id=wx.ID_NEW,
137 kind=wx.ITEM_NORMAL, text='New\tCTRL+N')
138 parent.Append(help='', id=wx.ID_OPEN,
139 kind=wx.ITEM_NORMAL, text='Open\tCTRL+O')
140 parent.Append(help='', id=wx.ID_CLOSE,
141 kind=wx.ITEM_NORMAL, text='Close\tCTRL+W')
142 parent.AppendSeparator()
143 parent.Append(help='', id=wx.ID_SAVE,
144 kind=wx.ITEM_NORMAL, text='Save\tCTRL+S')
145 parent.Append(help='', id=wx.ID_SAVEAS,
146 kind=wx.ITEM_NORMAL, text='Save As...\tALT+S')
147 parent.AppendSeparator()
148 parent.Append(help='', id=ID_OBJDICTEDITFILEMENUIMPORTEDS,
149 kind=wx.ITEM_NORMAL, text='Import EDS file')
150 parent.Append(help='', id=ID_OBJDICTEDITFILEMENUEXPORTEDS,
151 kind=wx.ITEM_NORMAL, text='Export to EDS file')
152 parent.Append(help='', id=ID_OBJDICTEDITFILEMENUEXPORTC,
153 kind=wx.ITEM_NORMAL, text='Build Dictionary\tCTRL+B')
154 parent.AppendSeparator()
155 parent.Append(help='', id=wx.ID_EXIT,
156 kind=wx.ITEM_NORMAL, text='Exit')
157 self.Bind(wx.EVT_MENU, self.OnNewMenu, id=wx.ID_NEW)
158 self.Bind(wx.EVT_MENU, self.OnOpenMenu, id=wx.ID_OPEN)
159 self.Bind(wx.EVT_MENU, self.OnCloseMenu, id=wx.ID_CLOSE)
160 self.Bind(wx.EVT_MENU, self.OnSaveMenu, id=wx.ID_SAVE)
161 self.Bind(wx.EVT_MENU, self.OnSaveAsMenu, id=wx.ID_SAVEAS)
162 self.Bind(wx.EVT_MENU, self.OnImportEDSMenu,
163 id=ID_OBJDICTEDITFILEMENUIMPORTEDS)
164 self.Bind(wx.EVT_MENU, self.OnExportEDSMenu,
165 id=ID_OBJDICTEDITFILEMENUEXPORTEDS)
166 self.Bind(wx.EVT_MENU, self.OnExportCMenu,
167 id=ID_OBJDICTEDITFILEMENUEXPORTC)
168 self.Bind(wx.EVT_MENU, self.OnQuitMenu, id=wx.ID_EXIT)
170 def _init_coll_EditMenu_Items(self, parent):
171 parent.Append(help='', id=wx.ID_REFRESH,
172 kind=wx.ITEM_NORMAL, text='Refresh\tCTRL+R')
173 parent.AppendSeparator()
174 parent.Append(help='', id=wx.ID_UNDO,
175 kind=wx.ITEM_NORMAL, text='Undo\tCTRL+Z')
176 parent.Append(help='', id=wx.ID_REDO,
177 kind=wx.ITEM_NORMAL, text='Redo\tCTRL+Y')
178 parent.AppendSeparator()
179 parent.Append(help='', id=ID_OBJDICTEDITEDITMENUNODEINFOS,
180 kind=wx.ITEM_NORMAL, text='Node infos')
181 parent.Append(help='', id=ID_OBJDICTEDITEDITMENUDS301PROFILE,
182 kind=wx.ITEM_NORMAL, text='DS-301 Profile')
183 parent.Append(help='', id=ID_OBJDICTEDITEDITMENUDS302PROFILE,
184 kind=wx.ITEM_NORMAL, text='DS-302 Profile')
185 parent.Append(help='', id=ID_OBJDICTEDITEDITMENUOTHERPROFILE,
186 kind=wx.ITEM_NORMAL, text='Other Profile')
187 self.Bind(wx.EVT_MENU, self.OnRefreshMenu, id=wx.ID_REFRESH)
188 self.Bind(wx.EVT_MENU, self.OnUndoMenu, id=wx.ID_UNDO)
189 self.Bind(wx.EVT_MENU, self.OnRedoMenu, id=wx.ID_REDO)
190 self.Bind(wx.EVT_MENU, self.OnNodeInfosMenu,
191 id=ID_OBJDICTEDITEDITMENUNODEINFOS)
192 self.Bind(wx.EVT_MENU, self.OnCommunicationMenu,
193 id=ID_OBJDICTEDITEDITMENUDS301PROFILE)
194 self.Bind(wx.EVT_MENU, self.OnOtherCommunicationMenu,
195 id=ID_OBJDICTEDITEDITMENUDS302PROFILE)
196 self.Bind(wx.EVT_MENU, self.OnEditProfileMenu,
197 id=ID_OBJDICTEDITEDITMENUOTHERPROFILE)
199 def _init_coll_AddMenu_Items(self, parent):
200 parent.Append(help='', id=ID_OBJDICTEDITADDMENUSDOSERVER,
201 kind=wx.ITEM_NORMAL, text='SDO Server')
202 parent.Append(help='', id=ID_OBJDICTEDITADDMENUSDOCLIENT,
203 kind=wx.ITEM_NORMAL, text='SDO Client')
204 parent.Append(help='', id=ID_OBJDICTEDITADDMENUPDOTRANSMIT,
205 kind=wx.ITEM_NORMAL, text='PDO Transmit')
206 parent.Append(help='', id=ID_OBJDICTEDITADDMENUPDORECEIVE,
207 kind=wx.ITEM_NORMAL, text='PDO Receive')
208 parent.Append(help='', id=ID_OBJDICTEDITADDMENUMAPVARIABLE,
209 kind=wx.ITEM_NORMAL, text='Map Variable')
210 parent.Append(help='', id=ID_OBJDICTEDITADDMENUUSERTYPE,
211 kind=wx.ITEM_NORMAL, text='User Type')
212 self.Bind(wx.EVT_MENU, self.OnAddSDOServerMenu,
213 id=ID_OBJDICTEDITADDMENUSDOSERVER)
214 self.Bind(wx.EVT_MENU, self.OnAddSDOClientMenu,
215 id=ID_OBJDICTEDITADDMENUSDOCLIENT)
216 self.Bind(wx.EVT_MENU, self.OnAddPDOTransmitMenu,
217 id=ID_OBJDICTEDITADDMENUPDOTRANSMIT)
218 self.Bind(wx.EVT_MENU, self.OnAddPDOReceiveMenu,
219 id=ID_OBJDICTEDITADDMENUPDORECEIVE)
220 self.Bind(wx.EVT_MENU, self.OnAddMapVariableMenu,
221 id=ID_OBJDICTEDITADDMENUMAPVARIABLE)
222 self.Bind(wx.EVT_MENU, self.OnAddUserTypeMenu,
223 id=ID_OBJDICTEDITADDMENUUSERTYPE)
225 def _init_coll_HelpMenu_Items(self, parent):
226 parent.Append(help='', id=wx.ID_HELP,
227 kind=wx.ITEM_NORMAL, text='DS-301 Standard\tF1')
228 self.Bind(wx.EVT_MENU, self.OnHelpDS301Menu, id=wx.ID_HELP)
229 parent.Append(help='', id=wx.ID_HELP_CONTEXT,
230 kind=wx.ITEM_NORMAL, text='CAN Festival Docs\tF2')
231 self.Bind(wx.EVT_MENU, self.OnHelpCANFestivalMenu, id=wx.ID_HELP_CONTEXT)
232 if Html_Window and self.ModeSolo:
233 parent.Append(help='', id=wx.ID_ABOUT,
234 kind=wx.ITEM_NORMAL, text='About')
235 self.Bind(wx.EVT_MENU, self.OnAboutMenu, id=wx.ID_ABOUT)
237 def _init_coll_HelpBar_Fields(self, parent):
238 parent.SetFieldsCount(3)
240 parent.SetStatusText(number=0, text='')
241 parent.SetStatusText(number=1, text='')
242 parent.SetStatusText(number=2, text='')
244 parent.SetStatusWidths([100, 110, -1])
246 def _init_utils(self):
247 self.MenuBar = wx.MenuBar()
248 self.MenuBar.SetEvtHandlerEnabled(True)
251 self.FileMenu = wx.Menu(title='')
252 self.EditMenu = wx.Menu(title='')
253 self.AddMenu = wx.Menu(title='')
254 self.HelpMenu = wx.Menu(title='')
256 self._init_coll_MenuBar_Menus(self.MenuBar)
258 self._init_coll_FileMenu_Items(self.FileMenu)
259 self._init_coll_EditMenu_Items(self.EditMenu)
260 self._init_coll_AddMenu_Items(self.AddMenu)
261 self._init_coll_HelpMenu_Items(self.HelpMenu)
263 def _init_ctrls(self, prnt):
264 wx.Frame.__init__(self, id=ID_OBJDICTEDIT, name='objdictedit',
265 parent=prnt, pos=wx.Point(149, 178), size=wx.Size(1000, 700),
266 style=wx.DEFAULT_FRAME_STYLE, title='Objdictedit')
268 self.SetClientSize(wx.Size(1000, 700))
269 self.SetMenuBar(self.MenuBar)
270 self.Bind(wx.EVT_CLOSE, self.OnCloseFrame)
271 if not self.ModeSolo:
272 self.Bind(wx.EVT_MENU, self.OnSaveMenu, id=wx.ID_SAVE)
273 accel = wx.AcceleratorTable([wx.AcceleratorEntry(wx.ACCEL_CTRL, 83, wx.ID_SAVE)])
274 self.SetAcceleratorTable(accel)
276 self.FileOpened = wx.Notebook(id=ID_OBJDICTEDITFILEOPENED,
277 name='FileOpened', parent=self, pos=wx.Point(0, 0),
278 size=wx.Size(0, 0), style=0)
279 self.FileOpened.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED,
280 self.OnFileSelectedChanged, id=ID_OBJDICTEDITFILEOPENED)
282 self.HelpBar = wx.StatusBar(id=ID_OBJDICTEDITHELPBAR, name='HelpBar',
283 parent=self, style=wx.ST_SIZEGRIP)
284 self._init_coll_HelpBar_Fields(self.HelpBar)
285 self.SetStatusBar(self.HelpBar)
287 def __init__(self, parent, manager = None, filesOpen = []):
288 self.ModeSolo = manager == None
289 self._init_ctrls(parent)
290 self.HtmlFrameOpened = []
294 icon = wx.Icon(os.path.join(ScriptDirectory,"networkedit.ico"),wx.BITMAP_TYPE_ICO)
298 self.Manager = NodeManager()
299 for filepath in filesOpen:
300 result = self.Manager.OpenFileInCurrent(os.path.abspath(filepath))
301 if isinstance(result, (IntType, LongType)):
302 new_editingpanel = EditingPanel(self.FileOpened, self, self.Manager)
303 new_editingpanel.SetIndex(result)
304 self.FileOpened.AddPage(new_editingpanel, "")
306 self.Manager = manager
307 for index in self.Manager.GetBufferIndexes():
308 new_editingpanel = EditingPanel(self.FileOpened, self, self.Manager)
309 new_editingpanel.SetIndex(index)
310 self.FileOpened.AddPage(new_editingpanel, "")
312 if self.Manager.GetBufferNumber() > 0:
313 window = self.FileOpened.GetPage(0)
315 self.Manager.ChangeCurrentNode(window.GetIndex())
316 self.FileOpened.SetSelection(0)
318 if self.Manager.CurrentDS302Defined():
319 self.EditMenu.Enable(ID_OBJDICTEDITEDITMENUDS302PROFILE, True)
321 self.EditMenu.Enable(ID_OBJDICTEDITEDITMENUDS302PROFILE, False)
322 self.RefreshEditMenu()
323 self.RefreshBufferState()
324 self.RefreshProfileMenu()
326 self.RefreshMainMenu()
328 def SetBusId(self, bus_id):
337 def OnAddSDOServerMenu(self, event):
338 self.Manager.AddSDOServerToCurrent()
339 self.RefreshBufferState()
340 self.RefreshCurrentIndexList()
343 def OnAddSDOClientMenu(self, event):
344 self.Manager.AddSDOClientToCurrent()
345 self.RefreshBufferState()
346 self.RefreshCurrentIndexList()
349 def OnAddPDOTransmitMenu(self, event):
350 self.Manager.AddPDOTransmitToCurrent()
351 self.RefreshBufferState()
352 self.RefreshCurrentIndexList()
355 def OnAddPDOReceiveMenu(self, event):
356 self.Manager.AddPDOReceiveToCurrent()
357 self.RefreshBufferState()
358 self.RefreshCurrentIndexList()
361 def OnAddMapVariableMenu(self, event):
362 self.AddMapVariable()
365 def OnAddUserTypeMenu(self, event):
369 def OnFileSelectedChanged(self, event):
371 selected = event.GetSelection()
372 # At init selected = -1
374 window = self.FileOpened.GetPage(selected)
376 self.Manager.ChangeCurrentNode(window.GetIndex())
377 wx.CallAfter(self.RefreshBufferState)
378 self.RefreshStatusBar()
379 self.RefreshProfileMenu()
382 def OnHelpDS301Menu(self, event):
384 selected = self.FileOpened.GetSelection()
386 window = self.FileOpened.GetPage(selected)
387 result = window.GetSelection()
390 index, subIndex = result
391 result = OpenPDFDocIndex(index, ScriptDirectory)
392 if isinstance(result, (StringType, UnicodeType)):
393 message = wx.MessageDialog(self, result, "ERROR", wx.OK|wx.ICON_ERROR)
397 result = OpenPDFDocIndex(None, ScriptDirectory)
398 if isinstance(result, (StringType, UnicodeType)):
399 message = wx.MessageDialog(self, result, "ERROR", wx.OK|wx.ICON_ERROR)
404 def OnHelpCANFestivalMenu(self, event):
405 #self.OpenHtmlFrame("CAN Festival Reference", os.path.join(ScriptDirectory, "doc/canfestival.html"), wx.Size(1000, 600))
406 if wx.Platform == '__WXMSW__':
407 readerpath = get_acroversion()
408 readerexepath = os.path.join(readerpath,"AcroRd32.exe")
409 if(os.path.isfile(readerexepath)):
410 os.spawnl(os.P_DETACH, readerexepath, "AcroRd32.exe", '"%s"'%os.path.join(ScriptDirectory, "doc","manual_en.pdf"))
412 os.system("xpdf -remote CANFESTIVAL %s %d &"%(os.path.join(ScriptDirectory, "doc/manual_en.pdf"),16))
415 def OnAboutMenu(self, event):
416 self.OpenHtmlFrame("About CAN Festival", os.path.join(ScriptDirectory, "doc/about.html"), wx.Size(500, 450))
419 def OpenHtmlFrame(self, title, file, size):
420 if title not in self.HtmlFrameOpened:
421 self.HtmlFrameOpened.append(title)
422 window = HtmlFrame(self, self.HtmlFrameOpened)
423 window.SetTitle(title)
424 window.SetHtmlPage(file)
425 window.SetClientSize(size)
428 def OnQuitMenu(self, event):
432 def OnCloseFrame(self, event):
434 if not self.ModeSolo:
435 if getattr(self, "_onclose", None) != None:
438 elif self.Manager.OneFileHasChanged():
439 dialog = wx.MessageDialog(self, "There are changes, do you want to save?", "Close Application", wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
440 answer = dialog.ShowModal()
442 if answer == wx.ID_YES:
443 for i in xrange(self.Manager.GetBufferNumber()):
444 if self.Manager.CurrentIsSaved():
445 self.Manager.CloseCurrent()
448 self.Manager.CloseCurrent(True)
450 elif answer == wx.ID_NO:
457 #-------------------------------------------------------------------------------
459 #-------------------------------------------------------------------------------
461 def RefreshTitle(self):
462 if self.FileOpened.GetPageCount() > 0:
463 self.SetTitle("Objdictedit - %s"%self.Manager.GetCurrentFilename())
465 self.SetTitle("Objdictedit")
467 def OnRefreshMenu(self, event):
468 self.RefreshCurrentIndexList()
471 def RefreshCurrentIndexList(self):
472 selected = self.FileOpened.GetSelection()
473 window = self.FileOpened.GetPage(selected)
474 window.RefreshIndexList()
476 def RefreshStatusBar(self):
477 selected = self.FileOpened.GetSelection()
479 window = self.FileOpened.GetPage(selected)
480 selection = window.GetSelection()
482 index, subIndex = selection
483 if self.Manager.IsCurrentEntry(index):
484 self.HelpBar.SetStatusText("Index: 0x%04X"%index, 0)
485 self.HelpBar.SetStatusText("Subindex: 0x%02X"%subIndex, 1)
486 entryinfos = self.Manager.GetEntryInfos(index)
487 name = entryinfos["name"]
488 category = "Optional"
489 if entryinfos["need"]:
490 category = "Mandatory"
493 if entryinfos["struct"] & OD_IdenticalIndexes:
494 number = " possibly defined %d times"%entryinfos["nbmax"]
495 if entryinfos["struct"] & OD_IdenticalSubindexes:
497 elif entryinfos["struct"] & OD_MultipleSubindexes:
499 text = "%s: %s entry of struct %s%s."%(name,category,struct,number)
500 self.HelpBar.SetStatusText(text, 2)
503 self.HelpBar.SetStatusText("", i)
506 self.HelpBar.SetStatusText("", i)
508 def RefreshMainMenu(self):
509 if self.FileOpened.GetPageCount() > 0:
511 self.MenuBar.EnableTop(1, True)
512 self.MenuBar.EnableTop(2, True)
513 self.FileMenu.Enable(wx.ID_CLOSE, True)
514 self.FileMenu.Enable(wx.ID_SAVE, True)
515 self.FileMenu.Enable(wx.ID_SAVEAS, True)
516 self.FileMenu.Enable(ID_OBJDICTEDITFILEMENUEXPORTEDS, True)
517 self.FileMenu.Enable(ID_OBJDICTEDITFILEMENUEXPORTC, True)
519 self.MenuBar.EnableTop(0, True)
520 self.MenuBar.EnableTop(1, True)
523 self.MenuBar.EnableTop(1, False)
524 self.MenuBar.EnableTop(2, False)
525 self.FileMenu.Enable(wx.ID_CLOSE, False)
526 self.FileMenu.Enable(wx.ID_SAVE, False)
527 self.FileMenu.Enable(wx.ID_SAVEAS, False)
528 self.FileMenu.Enable(ID_OBJDICTEDITFILEMENUEXPORTEDS, False)
529 self.FileMenu.Enable(ID_OBJDICTEDITFILEMENUEXPORTC, False)
531 self.MenuBar.EnableTop(0, False)
532 self.MenuBar.EnableTop(1, False)
534 def RefreshEditMenu(self):
535 if self.FileOpened.GetPageCount() > 0:
536 undo, redo = self.Manager.GetCurrentBufferState()
537 self.EditMenu.Enable(wx.ID_UNDO, undo)
538 self.EditMenu.Enable(wx.ID_REDO, redo)
540 self.EditMenu.Enable(wx.ID_UNDO, False)
541 self.EditMenu.Enable(wx.ID_REDO, False)
543 def RefreshProfileMenu(self):
544 profile = self.Manager.GetCurrentProfileName()
545 edititem = self.EditMenu.FindItemById(ID_OBJDICTEDITEDITMENUOTHERPROFILE)
547 length = self.AddMenu.GetMenuItemCount()
548 for i in xrange(length-6):
549 additem = self.AddMenu.FindItemByPosition(6)
550 self.AddMenu.Delete(additem.GetId())
551 if profile not in ("None", "DS-301"):
552 edititem.SetText("%s Profile"%profile)
553 edititem.Enable(True)
554 self.AddMenu.AppendSeparator()
555 for text, indexes in self.Manager.GetCurrentSpecificMenu():
557 self.AddMenu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=text)
558 self.Bind(wx.EVT_MENU, self.GetProfileCallBack(text), id=new_id)
560 edititem.SetText("Other Profile")
561 edititem.Enable(False)
564 #-------------------------------------------------------------------------------
566 #-------------------------------------------------------------------------------
568 def RefreshBufferState(self):
569 fileopened = self.Manager.GetAllFilenames()
570 for idx, filename in enumerate(fileopened):
571 self.FileOpened.SetPageText(idx, filename)
572 self.RefreshEditMenu()
575 def OnUndoMenu(self, event):
576 self.Manager.LoadCurrentPrevious()
577 self.RefreshCurrentIndexList()
578 self.RefreshBufferState()
581 def OnRedoMenu(self, event):
582 self.Manager.LoadCurrentNext()
583 self.RefreshCurrentIndexList()
584 self.RefreshBufferState()
588 #-------------------------------------------------------------------------------
589 # Load and Save Funtions
590 #-------------------------------------------------------------------------------
592 def OnNewMenu(self, event):
594 dialog = CreateNodeDialog(self)
595 if dialog.ShowModal() == wx.ID_OK:
596 name, id, nodetype, description = dialog.GetValues()
597 profile, filepath = dialog.GetProfile()
598 NMT = dialog.GetNMTManagement()
599 options = dialog.GetOptions()
600 result = self.Manager.CreateNewNode(name, id, nodetype, description, profile, filepath, NMT, options)
601 if isinstance(result, (IntType, LongType)):
602 new_editingpanel = EditingPanel(self.FileOpened, self, self.Manager)
603 new_editingpanel.SetIndex(result)
604 self.FileOpened.AddPage(new_editingpanel, "")
605 self.FileOpened.SetSelection(self.FileOpened.GetPageCount() - 1)
606 self.EditMenu.Enable(ID_OBJDICTEDITEDITMENUDS302PROFILE, False)
607 if "DS302" in options:
608 self.EditMenu.Enable(ID_OBJDICTEDITEDITMENUDS302PROFILE, True)
609 self.RefreshBufferState()
610 self.RefreshProfileMenu()
611 self.RefreshMainMenu()
613 message = wx.MessageDialog(self, result, "ERROR", wx.OK|wx.ICON_ERROR)
619 def OnOpenMenu(self, event):
620 filepath = self.Manager.GetCurrentFilePath()
622 directory = os.path.dirname(filepath)
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 isinstance(result, (IntType, LongType)):
631 new_editingpanel = EditingPanel(self.FileOpened, 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_OBJDICTEDITEDITMENUDS302PROFILE, True)
638 self.EditMenu.Enable(ID_OBJDICTEDITEDITMENUDS302PROFILE, False)
639 self.RefreshEditMenu()
640 self.RefreshBufferState()
641 self.RefreshProfileMenu()
642 self.RefreshMainMenu()
644 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
650 def OnSaveMenu(self, event):
651 if not self.ModeSolo and getattr(self, "_onsave", None) != None:
653 self.RefreshBufferState()
658 def OnSaveAsMenu(self, event):
663 result = self.Manager.SaveCurrentInFile()
666 elif not isinstance(result, (StringType, UnicodeType)):
667 self.RefreshBufferState()
669 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
674 filepath = self.Manager.GetCurrentFilePath()
676 directory, filename = os.path.split(filepath)
678 directory, filename = os.getcwd(), "%s.od"%self.Manager.GetCurrentNodeInfos()[0]
679 dialog = wx.FileDialog(self, "Choose a file", directory, filename, "OD files (*.od)|*.od|All files|*.*", wx.SAVE|wx.OVERWRITE_PROMPT|wx.CHANGE_DIR)
680 if dialog.ShowModal() == wx.ID_OK:
681 filepath = dialog.GetPath()
682 if os.path.isdir(os.path.dirname(filepath)):
683 result = self.Manager.SaveCurrentInFile(filepath)
684 if not isinstance(result, (StringType, UnicodeType)):
685 self.RefreshBufferState()
687 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
691 message = wx.MessageDialog(self, "%s is not a valid folder!"%os.path.dirname(filepath), "Error", wx.OK|wx.ICON_ERROR)
696 def OnCloseMenu(self, event):
698 result = self.Manager.CloseCurrent()
700 dialog = wx.MessageDialog(self, "There are changes, do you want to save?", "Close File", wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
701 answer = dialog.ShowModal()
703 if answer == wx.ID_YES:
704 self.OnSaveMenu(event)
705 if self.Manager.CurrentIsSaved():
706 self.Manager.CloseCurrent()
707 elif answer == wx.ID_NO:
708 self.Manager.CloseCurrent(True)
709 if self.FileOpened.GetPageCount() > self.Manager.GetBufferNumber():
710 current = self.FileOpened.GetSelection()
711 self.FileOpened.DeletePage(current)
712 if self.FileOpened.GetPageCount() > 0:
713 self.FileOpened.SetSelection(min(current, self.FileOpened.GetPageCount() - 1))
714 self.RefreshBufferState()
715 self.RefreshMainMenu()
719 #-------------------------------------------------------------------------------
720 # Import and Export Functions
721 #-------------------------------------------------------------------------------
723 def OnImportEDSMenu(self, event):
724 dialog = wx.FileDialog(self, "Choose a file", os.getcwd(), "", "EDS files (*.eds)|*.eds|All files|*.*", wx.OPEN|wx.CHANGE_DIR)
725 if dialog.ShowModal() == wx.ID_OK:
726 filepath = dialog.GetPath()
727 if os.path.isfile(filepath):
728 result = self.Manager.ImportCurrentFromEDSFile(filepath)
729 if isinstance(result, (IntType, LongType)):
730 new_editingpanel = EditingPanel(self.FileOpened, self, self.Manager)
731 new_editingpanel.SetIndex(result)
732 self.FileOpened.AddPage(new_editingpanel, "")
733 self.FileOpened.SetSelection(self.FileOpened.GetPageCount() - 1)
734 self.RefreshBufferState()
735 self.RefreshCurrentIndexList()
736 self.RefreshProfileMenu()
737 self.RefreshMainMenu()
738 message = wx.MessageDialog(self, "Import successful", "Information", wx.OK|wx.ICON_INFORMATION)
742 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
746 message = wx.MessageDialog(self, "\"%s\" is not a valid file!"%filepath, "Error", wx.OK|wx.ICON_ERROR)
752 def OnExportEDSMenu(self, event):
753 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)
754 if dialog.ShowModal() == wx.ID_OK:
755 filepath = dialog.GetPath()
756 if os.path.isdir(os.path.dirname(filepath)):
757 path, extend = os.path.splitext(filepath)
758 if extend in ("", "."):
759 filepath = path + ".eds"
760 result = self.Manager.ExportCurrentToEDSFile(filepath)
762 message = wx.MessageDialog(self, "Export successful", "Information", wx.OK|wx.ICON_INFORMATION)
766 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
770 message = wx.MessageDialog(self, "\"%s\" is not a valid folder!"%os.path.dirname(filepath), "Error", wx.OK|wx.ICON_ERROR)
776 def OnExportCMenu(self, event):
777 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)
778 if dialog.ShowModal() == wx.ID_OK:
779 filepath = dialog.GetPath()
780 if os.path.isdir(os.path.dirname(filepath)):
781 path, extend = os.path.splitext(filepath)
782 if extend in ("", "."):
783 filepath = path + ".c"
784 result = self.Manager.ExportCurrentToCFile(filepath)
786 message = wx.MessageDialog(self, "Export successful", "Information", wx.OK|wx.ICON_INFORMATION)
790 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
794 message = wx.MessageDialog(self, "\"%s\" is not a valid folder!"%os.path.dirname(filepath), "Error", wx.OK|wx.ICON_ERROR)
800 #-------------------------------------------------------------------------------
801 # Editing Profiles functions
802 #-------------------------------------------------------------------------------
804 def OnCommunicationMenu(self, event):
805 dictionary,current = self.Manager.GetCurrentCommunicationLists()
806 self.EditProfile("Edit DS-301 Profile", dictionary, current)
809 def OnOtherCommunicationMenu(self, event):
810 dictionary,current = self.Manager.GetCurrentDS302Lists()
811 self.EditProfile("Edit DS-302 Profile", dictionary, current)
814 def OnEditProfileMenu(self, event):
815 title = "Edit %s Profile"%self.Manager.GetCurrentProfileName()
816 dictionary,current = self.Manager.GetCurrentProfileLists()
817 self.EditProfile(title, dictionary, current)
820 def EditProfile(self, title, dictionary, current):
821 dialog = CommunicationDialog(self)
822 dialog.SetTitle(title)
823 dialog.SetIndexDictionary(dictionary)
824 dialog.SetCurrentList(current)
825 dialog.RefreshLists()
826 if dialog.ShowModal() == wx.ID_OK:
827 new_profile = dialog.GetCurrentList()
830 for index in new_profile:
831 if index not in current:
832 addinglist.append(index)
833 for index in current:
834 if index not in new_profile:
835 removinglist.append(index)
836 self.Manager.ManageEntriesOfCurrent(addinglist, removinglist)
837 self.Manager.BufferCurrentNode()
838 self.RefreshBufferState()
839 self.RefreshCurrentIndexList()
842 def GetProfileCallBack(self, text):
843 def ProfileCallBack(event):
844 self.Manager.AddSpecificEntryToCurrent(text)
845 self.RefreshBufferState()
846 self.RefreshCurrentIndexList()
848 return ProfileCallBack
850 #-------------------------------------------------------------------------------
851 # Edit Node informations function
852 #-------------------------------------------------------------------------------
854 def OnNodeInfosMenu(self, event):
855 dialog = NodeInfosDialog(self)
856 name, id, type, description = self.Manager.GetCurrentNodeInfos()
857 defaultstringsize = self.Manager.GetCurrentNodeDefaultStringSize()
858 dialog.SetValues(name, id, type, description, defaultstringsize)
859 if dialog.ShowModal() == wx.ID_OK:
860 name, id, type, description, defaultstringsize = dialog.GetValues()
861 self.Manager.SetCurrentNodeInfos(name, id, type, description)
862 self.Manager.SetCurrentNodeDefaultStringSize(defaultstringsize)
863 self.RefreshBufferState()
864 self.RefreshProfileMenu()
865 selected = self.FileOpened.GetSelection()
867 window = self.FileOpened.GetPage(selected)
868 window.RefreshTable()
872 #-------------------------------------------------------------------------------
873 # Add User Types and Variables
874 #-------------------------------------------------------------------------------
876 def AddMapVariable(self):
877 index = self.Manager.GetCurrentNextMapIndex()
879 dialog = MapVariableDialog(self)
880 dialog.SetIndex(index)
881 if dialog.ShowModal() == wx.ID_OK:
882 index, name, struct, number = dialog.GetValues()
883 result = self.Manager.AddMapVariableToCurrent(index, name, struct, number)
884 if not isinstance(result, (StringType, UnicodeType)):
885 self.RefreshBufferState()
886 self.RefreshCurrentIndexList()
888 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
893 message = wx.MessageDialog(self, result, "No map variable index left!", wx.OK|wx.ICON_ERROR)
897 def AddUserType(self):
898 dialog = UserTypeDialog(self)
899 dialog.SetTypeList(self.Manager.GetCustomisableTypes())
900 if dialog.ShowModal() == wx.ID_OK:
901 type, min, max, length = dialog.GetValues()
902 result = self.Manager.AddUserTypeToCurrent(type, min, max, length)
904 self.RefreshBufferState()
905 self.RefreshCurrentIndexList()
907 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
913 #-------------------------------------------------------------------------------
915 #-------------------------------------------------------------------------------
917 Max_Traceback_List_Size = 20
919 def Display_Exception_Dialog(e_type,e_value,e_tb):
921 for i,line in enumerate(traceback.extract_tb(e_tb)):
922 trcbck = " " + str(i+1) + ". "
923 if line[0].find(os.getcwd()) == -1:
924 trcbck += "file : " + str(line[0]) + ", "
926 trcbck += "file : " + str(line[0][len(os.getcwd()):]) + ", "
927 trcbck += "line : " + str(line[1]) + ", " + "function : " + str(line[2])
928 trcbck_lst.append(trcbck)
931 cap = wx.Window_GetCapture()
935 dlg = wx.SingleChoiceDialog(None,
939 Click on OK for saving an error report.
941 Please contact LOLITech at:
943 bugs_objdictedit@lolitech.fr
948 str(e_type) + " : " + str(e_value),
952 res = (dlg.ShowModal() == wx.ID_OK)
958 def Display_Error_Dialog(e_value):
959 message = wx.MessageDialog(None, str(e_value), "Error", wx.OK|wx.ICON_ERROR)
963 def get_last_traceback(tb):
969 def format_namespace(d, indent=' '):
970 return '\n'.join(['%s%s: %s' % (indent, k, repr(v)[:10000]) for k, v in d.iteritems()])
973 ignored_exceptions = [] # a problem with a line in a module is only reported once per session
975 def AddExceptHook(path, app_version='[No version]'):#, ignored_exceptions=[]):
977 def handle_exception(e_type, e_value, e_traceback):
978 traceback.print_exception(e_type, e_value, e_traceback) # this is very helpful when there's an exception in the rest of this func
979 last_tb = get_last_traceback(e_traceback)
980 ex = (last_tb.tb_frame.f_code.co_filename, last_tb.tb_frame.f_lineno)
981 if str(e_value).startswith("!!!"):
982 Display_Error_Dialog(e_value)
983 elif ex not in ignored_exceptions:
984 ignored_exceptions.append(ex)
985 result = Display_Exception_Dialog(e_type,e_value,e_traceback)
988 'app-title' : wx.GetApp().GetAppName(), # app_title
989 'app-version' : app_version,
990 'wx-version' : wx.VERSION_STRING,
991 'wx-platform' : wx.Platform,
992 'python-version' : platform.python_version(), #sys.version.split()[0],
993 'platform' : platform.platform(),
996 'date' : time.ctime(),
1000 info['traceback'] = ''.join(traceback.format_tb(e_traceback)) + '%s: %s' % (e_type, e_value)
1001 last_tb = get_last_traceback(e_traceback)
1002 exception_locals = last_tb.tb_frame.f_locals # the locals at the level of the stack trace where the exception actually occurred
1003 info['locals'] = format_namespace(exception_locals)
1004 if 'self' in exception_locals:
1005 info['self'] = format_namespace(exception_locals['self'].__dict__)
1007 output = open(path+os.sep+"bug_report_"+info['date'].replace(':','-').replace(' ','_')+".txt",'w')
1011 output.write(a+":\n"+str(info[a])+"\n\n")
1013 #sys.excepthook = lambda *args: wx.CallAfter(handle_exception, *args)
1014 sys.excepthook = handle_exception
1016 if __name__ == '__main__':
1018 print "\nUsage of objdictedit.py :"
1019 print "\n %s [Filepath, ...]\n"%sys.argv[0]
1022 opts, args = getopt.getopt(sys.argv[1:], "h", ["help"])
1023 except getopt.GetoptError:
1024 # print help information and exit:
1029 if o in ("-h", "--help"):
1033 app = wx.PySimpleApp()
1034 wx.InitAllImageHandlers()
1036 # Install a exception handle for bug reports
1037 AddExceptHook(os.getcwd(),__version__)
1039 frame = objdictedit(None, filesOpen = args)