24 import wx |
24 import wx |
25 |
25 |
26 from types import * |
26 from types import * |
27 import os, re, platform, sys, time, traceback, getopt |
27 import os, re, platform, sys, time, traceback, getopt |
28 |
28 |
29 __version__ = "$Revision$" |
29 __version__ = "$Revision: 1.48 $" |
|
30 |
|
31 if __name__ == '__main__': |
|
32 def usage(): |
|
33 print _("\nUsage of objdictedit.py :") |
|
34 print "\n %s [Filepath, ...]\n"%sys.argv[0] |
|
35 |
|
36 try: |
|
37 opts, args = getopt.getopt(sys.argv[1:], "h", ["help"]) |
|
38 except getopt.GetoptError: |
|
39 # print help information and exit: |
|
40 usage() |
|
41 sys.exit(2) |
|
42 |
|
43 for o, a in opts: |
|
44 if o in ("-h", "--help"): |
|
45 usage() |
|
46 sys.exit() |
|
47 |
|
48 app = wx.PySimpleApp() |
|
49 |
|
50 ScriptDirectory = os.path.split(os.path.realpath(__file__))[0] |
|
51 |
|
52 # Import module for internationalization |
|
53 import gettext |
|
54 import __builtin__ |
|
55 |
|
56 # Get folder containing translation files |
|
57 localedir = os.path.join(ScriptDirectory,"locale") |
|
58 # Get the default language |
|
59 langid = wx.LANGUAGE_DEFAULT |
|
60 # Define translation domain (name of translation files) |
|
61 domain = "objdictgen" |
|
62 |
|
63 # Define locale for wx |
|
64 loc = __builtin__.__dict__.get('loc', None) |
|
65 if loc is None: |
|
66 loc = wx.Locale(langid) |
|
67 __builtin__.__dict__['loc'] = loc |
|
68 # Define location for searching translation files |
|
69 loc.AddCatalogLookupPathPrefix(localedir) |
|
70 # Define locale domain |
|
71 loc.AddCatalog(domain) |
|
72 |
|
73 if __name__ == '__main__': |
|
74 __builtin__.__dict__['_'] = wx.GetTranslation |
30 |
75 |
31 from node import OD_Subindex, OD_MultipleSubindexes, OD_IdenticalSubindexes, OD_IdenticalIndexes |
76 from node import OD_Subindex, OD_MultipleSubindexes, OD_IdenticalSubindexes, OD_IdenticalIndexes |
32 |
77 |
33 from nodemanager import * |
78 from nodemanager import * |
34 from subindextable import * |
79 from subindextable import * |
125 ] = [wx.NewId() for _init_coll_AddMenu_Items in range(6)] |
168 ] = [wx.NewId() for _init_coll_AddMenu_Items in range(6)] |
126 |
169 |
127 class objdictedit(wx.Frame): |
170 class objdictedit(wx.Frame): |
128 def _init_coll_MenuBar_Menus(self, parent): |
171 def _init_coll_MenuBar_Menus(self, parent): |
129 if self.ModeSolo: |
172 if self.ModeSolo: |
130 parent.Append(menu=self.FileMenu, title='File') |
173 parent.Append(menu=self.FileMenu, title=_('File')) |
131 parent.Append(menu=self.EditMenu, title='Edit') |
174 parent.Append(menu=self.EditMenu, title=_('Edit')) |
132 parent.Append(menu=self.AddMenu, title='Add') |
175 parent.Append(menu=self.AddMenu, title=_('Add')) |
133 parent.Append(menu=self.HelpMenu, title='Help') |
176 parent.Append(menu=self.HelpMenu, title=_('Help')) |
134 |
177 |
135 def _init_coll_FileMenu_Items(self, parent): |
178 def _init_coll_FileMenu_Items(self, parent): |
136 parent.Append(help='', id=wx.ID_NEW, |
179 parent.Append(help='', id=wx.ID_NEW, |
137 kind=wx.ITEM_NORMAL, text='New\tCTRL+N') |
180 kind=wx.ITEM_NORMAL, text=_('New\tCTRL+N')) |
138 parent.Append(help='', id=wx.ID_OPEN, |
181 parent.Append(help='', id=wx.ID_OPEN, |
139 kind=wx.ITEM_NORMAL, text='Open\tCTRL+O') |
182 kind=wx.ITEM_NORMAL, text=_('Open\tCTRL+O')) |
140 parent.Append(help='', id=wx.ID_CLOSE, |
183 parent.Append(help='', id=wx.ID_CLOSE, |
141 kind=wx.ITEM_NORMAL, text='Close\tCTRL+W') |
184 kind=wx.ITEM_NORMAL, text=_('Close\tCTRL+W')) |
142 parent.AppendSeparator() |
185 parent.AppendSeparator() |
143 parent.Append(help='', id=wx.ID_SAVE, |
186 parent.Append(help='', id=wx.ID_SAVE, |
144 kind=wx.ITEM_NORMAL, text='Save\tCTRL+S') |
187 kind=wx.ITEM_NORMAL, text=_('Save\tCTRL+S')) |
145 parent.Append(help='', id=wx.ID_SAVEAS, |
188 parent.Append(help='', id=wx.ID_SAVEAS, |
146 kind=wx.ITEM_NORMAL, text='Save As...\tALT+S') |
189 kind=wx.ITEM_NORMAL, text=_('Save As...\tALT+S')) |
147 parent.AppendSeparator() |
190 parent.AppendSeparator() |
148 parent.Append(help='', id=ID_OBJDICTEDITFILEMENUIMPORTEDS, |
191 parent.Append(help='', id=ID_OBJDICTEDITFILEMENUIMPORTEDS, |
149 kind=wx.ITEM_NORMAL, text='Import EDS file') |
192 kind=wx.ITEM_NORMAL, text=_('Import EDS file')) |
150 parent.Append(help='', id=ID_OBJDICTEDITFILEMENUEXPORTEDS, |
193 parent.Append(help='', id=ID_OBJDICTEDITFILEMENUEXPORTEDS, |
151 kind=wx.ITEM_NORMAL, text='Export to EDS file') |
194 kind=wx.ITEM_NORMAL, text=_('Export to EDS file')) |
152 parent.Append(help='', id=ID_OBJDICTEDITFILEMENUEXPORTC, |
195 parent.Append(help='', id=ID_OBJDICTEDITFILEMENUEXPORTC, |
153 kind=wx.ITEM_NORMAL, text='Build Dictionary\tCTRL+B') |
196 kind=wx.ITEM_NORMAL, text=_('Build Dictionary\tCTRL+B')) |
154 parent.AppendSeparator() |
197 parent.AppendSeparator() |
155 parent.Append(help='', id=wx.ID_EXIT, |
198 parent.Append(help='', id=wx.ID_EXIT, |
156 kind=wx.ITEM_NORMAL, text='Exit') |
199 kind=wx.ITEM_NORMAL, text=_('Exit')) |
157 self.Bind(wx.EVT_MENU, self.OnNewMenu, id=wx.ID_NEW) |
200 self.Bind(wx.EVT_MENU, self.OnNewMenu, id=wx.ID_NEW) |
158 self.Bind(wx.EVT_MENU, self.OnOpenMenu, id=wx.ID_OPEN) |
201 self.Bind(wx.EVT_MENU, self.OnOpenMenu, id=wx.ID_OPEN) |
159 self.Bind(wx.EVT_MENU, self.OnCloseMenu, id=wx.ID_CLOSE) |
202 self.Bind(wx.EVT_MENU, self.OnCloseMenu, id=wx.ID_CLOSE) |
160 self.Bind(wx.EVT_MENU, self.OnSaveMenu, id=wx.ID_SAVE) |
203 self.Bind(wx.EVT_MENU, self.OnSaveMenu, id=wx.ID_SAVE) |
161 self.Bind(wx.EVT_MENU, self.OnSaveAsMenu, id=wx.ID_SAVEAS) |
204 self.Bind(wx.EVT_MENU, self.OnSaveAsMenu, id=wx.ID_SAVEAS) |
167 id=ID_OBJDICTEDITFILEMENUEXPORTC) |
210 id=ID_OBJDICTEDITFILEMENUEXPORTC) |
168 self.Bind(wx.EVT_MENU, self.OnQuitMenu, id=wx.ID_EXIT) |
211 self.Bind(wx.EVT_MENU, self.OnQuitMenu, id=wx.ID_EXIT) |
169 |
212 |
170 def _init_coll_EditMenu_Items(self, parent): |
213 def _init_coll_EditMenu_Items(self, parent): |
171 parent.Append(help='', id=wx.ID_REFRESH, |
214 parent.Append(help='', id=wx.ID_REFRESH, |
172 kind=wx.ITEM_NORMAL, text='Refresh\tCTRL+R') |
215 kind=wx.ITEM_NORMAL, text=_('Refresh\tCTRL+R')) |
173 parent.AppendSeparator() |
216 parent.AppendSeparator() |
174 parent.Append(help='', id=wx.ID_UNDO, |
217 parent.Append(help='', id=wx.ID_UNDO, |
175 kind=wx.ITEM_NORMAL, text='Undo\tCTRL+Z') |
218 kind=wx.ITEM_NORMAL, text=_('Undo\tCTRL+Z')) |
176 parent.Append(help='', id=wx.ID_REDO, |
219 parent.Append(help='', id=wx.ID_REDO, |
177 kind=wx.ITEM_NORMAL, text='Redo\tCTRL+Y') |
220 kind=wx.ITEM_NORMAL, text=_('Redo\tCTRL+Y')) |
178 parent.AppendSeparator() |
221 parent.AppendSeparator() |
179 parent.Append(help='', id=ID_OBJDICTEDITEDITMENUNODEINFOS, |
222 parent.Append(help='', id=ID_OBJDICTEDITEDITMENUNODEINFOS, |
180 kind=wx.ITEM_NORMAL, text='Node infos') |
223 kind=wx.ITEM_NORMAL, text=_('Node infos')) |
181 parent.Append(help='', id=ID_OBJDICTEDITEDITMENUDS301PROFILE, |
224 parent.Append(help='', id=ID_OBJDICTEDITEDITMENUDS301PROFILE, |
182 kind=wx.ITEM_NORMAL, text='DS-301 Profile') |
225 kind=wx.ITEM_NORMAL, text=_('DS-301 Profile')) |
183 parent.Append(help='', id=ID_OBJDICTEDITEDITMENUDS302PROFILE, |
226 parent.Append(help='', id=ID_OBJDICTEDITEDITMENUDS302PROFILE, |
184 kind=wx.ITEM_NORMAL, text='DS-302 Profile') |
227 kind=wx.ITEM_NORMAL, text=_('DS-302 Profile')) |
185 parent.Append(help='', id=ID_OBJDICTEDITEDITMENUOTHERPROFILE, |
228 parent.Append(help='', id=ID_OBJDICTEDITEDITMENUOTHERPROFILE, |
186 kind=wx.ITEM_NORMAL, text='Other Profile') |
229 kind=wx.ITEM_NORMAL, text=_('Other Profile')) |
187 self.Bind(wx.EVT_MENU, self.OnRefreshMenu, id=wx.ID_REFRESH) |
230 self.Bind(wx.EVT_MENU, self.OnRefreshMenu, id=wx.ID_REFRESH) |
188 self.Bind(wx.EVT_MENU, self.OnUndoMenu, id=wx.ID_UNDO) |
231 self.Bind(wx.EVT_MENU, self.OnUndoMenu, id=wx.ID_UNDO) |
189 self.Bind(wx.EVT_MENU, self.OnRedoMenu, id=wx.ID_REDO) |
232 self.Bind(wx.EVT_MENU, self.OnRedoMenu, id=wx.ID_REDO) |
190 self.Bind(wx.EVT_MENU, self.OnNodeInfosMenu, |
233 self.Bind(wx.EVT_MENU, self.OnNodeInfosMenu, |
191 id=ID_OBJDICTEDITEDITMENUNODEINFOS) |
234 id=ID_OBJDICTEDITEDITMENUNODEINFOS) |
196 self.Bind(wx.EVT_MENU, self.OnEditProfileMenu, |
239 self.Bind(wx.EVT_MENU, self.OnEditProfileMenu, |
197 id=ID_OBJDICTEDITEDITMENUOTHERPROFILE) |
240 id=ID_OBJDICTEDITEDITMENUOTHERPROFILE) |
198 |
241 |
199 def _init_coll_AddMenu_Items(self, parent): |
242 def _init_coll_AddMenu_Items(self, parent): |
200 parent.Append(help='', id=ID_OBJDICTEDITADDMENUSDOSERVER, |
243 parent.Append(help='', id=ID_OBJDICTEDITADDMENUSDOSERVER, |
201 kind=wx.ITEM_NORMAL, text='SDO Server') |
244 kind=wx.ITEM_NORMAL, text=_('SDO Server')) |
202 parent.Append(help='', id=ID_OBJDICTEDITADDMENUSDOCLIENT, |
245 parent.Append(help='', id=ID_OBJDICTEDITADDMENUSDOCLIENT, |
203 kind=wx.ITEM_NORMAL, text='SDO Client') |
246 kind=wx.ITEM_NORMAL, text=_('SDO Client')) |
204 parent.Append(help='', id=ID_OBJDICTEDITADDMENUPDOTRANSMIT, |
247 parent.Append(help='', id=ID_OBJDICTEDITADDMENUPDOTRANSMIT, |
205 kind=wx.ITEM_NORMAL, text='PDO Transmit') |
248 kind=wx.ITEM_NORMAL, text=_('PDO Transmit')) |
206 parent.Append(help='', id=ID_OBJDICTEDITADDMENUPDORECEIVE, |
249 parent.Append(help='', id=ID_OBJDICTEDITADDMENUPDORECEIVE, |
207 kind=wx.ITEM_NORMAL, text='PDO Receive') |
250 kind=wx.ITEM_NORMAL, text=_('PDO Receive')) |
208 parent.Append(help='', id=ID_OBJDICTEDITADDMENUMAPVARIABLE, |
251 parent.Append(help='', id=ID_OBJDICTEDITADDMENUMAPVARIABLE, |
209 kind=wx.ITEM_NORMAL, text='Map Variable') |
252 kind=wx.ITEM_NORMAL, text=_('Map Variable')) |
210 parent.Append(help='', id=ID_OBJDICTEDITADDMENUUSERTYPE, |
253 parent.Append(help='', id=ID_OBJDICTEDITADDMENUUSERTYPE, |
211 kind=wx.ITEM_NORMAL, text='User Type') |
254 kind=wx.ITEM_NORMAL, text=_('User Type')) |
212 self.Bind(wx.EVT_MENU, self.OnAddSDOServerMenu, |
255 self.Bind(wx.EVT_MENU, self.OnAddSDOServerMenu, |
213 id=ID_OBJDICTEDITADDMENUSDOSERVER) |
256 id=ID_OBJDICTEDITADDMENUSDOSERVER) |
214 self.Bind(wx.EVT_MENU, self.OnAddSDOClientMenu, |
257 self.Bind(wx.EVT_MENU, self.OnAddSDOClientMenu, |
215 id=ID_OBJDICTEDITADDMENUSDOCLIENT) |
258 id=ID_OBJDICTEDITADDMENUSDOCLIENT) |
216 self.Bind(wx.EVT_MENU, self.OnAddPDOTransmitMenu, |
259 self.Bind(wx.EVT_MENU, self.OnAddPDOTransmitMenu, |
222 self.Bind(wx.EVT_MENU, self.OnAddUserTypeMenu, |
265 self.Bind(wx.EVT_MENU, self.OnAddUserTypeMenu, |
223 id=ID_OBJDICTEDITADDMENUUSERTYPE) |
266 id=ID_OBJDICTEDITADDMENUUSERTYPE) |
224 |
267 |
225 def _init_coll_HelpMenu_Items(self, parent): |
268 def _init_coll_HelpMenu_Items(self, parent): |
226 parent.Append(help='', id=wx.ID_HELP, |
269 parent.Append(help='', id=wx.ID_HELP, |
227 kind=wx.ITEM_NORMAL, text='DS-301 Standard\tF1') |
270 kind=wx.ITEM_NORMAL, text=_('DS-301 Standard\tF1')) |
228 self.Bind(wx.EVT_MENU, self.OnHelpDS301Menu, id=wx.ID_HELP) |
271 self.Bind(wx.EVT_MENU, self.OnHelpDS301Menu, id=wx.ID_HELP) |
229 parent.Append(help='', id=wx.ID_HELP_CONTEXT, |
272 parent.Append(help='', id=wx.ID_HELP_CONTEXT, |
230 kind=wx.ITEM_NORMAL, text='CAN Festival Docs\tF2') |
273 kind=wx.ITEM_NORMAL, text=_('CAN Festival Docs\tF2')) |
231 self.Bind(wx.EVT_MENU, self.OnHelpCANFestivalMenu, id=wx.ID_HELP_CONTEXT) |
274 self.Bind(wx.EVT_MENU, self.OnHelpCANFestivalMenu, id=wx.ID_HELP_CONTEXT) |
232 if Html_Window and self.ModeSolo: |
275 if Html_Window and self.ModeSolo: |
233 parent.Append(help='', id=wx.ID_ABOUT, |
276 parent.Append(help='', id=wx.ID_ABOUT, |
234 kind=wx.ITEM_NORMAL, text='About') |
277 kind=wx.ITEM_NORMAL, text=_('About')) |
235 self.Bind(wx.EVT_MENU, self.OnAboutMenu, id=wx.ID_ABOUT) |
278 self.Bind(wx.EVT_MENU, self.OnAboutMenu, id=wx.ID_ABOUT) |
236 |
279 |
237 def _init_coll_HelpBar_Fields(self, parent): |
280 def _init_coll_HelpBar_Fields(self, parent): |
238 parent.SetFieldsCount(3) |
281 parent.SetFieldsCount(3) |
239 |
282 |
261 self._init_coll_HelpMenu_Items(self.HelpMenu) |
304 self._init_coll_HelpMenu_Items(self.HelpMenu) |
262 |
305 |
263 def _init_ctrls(self, prnt): |
306 def _init_ctrls(self, prnt): |
264 wx.Frame.__init__(self, id=ID_OBJDICTEDIT, name='objdictedit', |
307 wx.Frame.__init__(self, id=ID_OBJDICTEDIT, name='objdictedit', |
265 parent=prnt, pos=wx.Point(149, 178), size=wx.Size(1000, 700), |
308 parent=prnt, pos=wx.Point(149, 178), size=wx.Size(1000, 700), |
266 style=wx.DEFAULT_FRAME_STYLE, title='Objdictedit') |
309 style=wx.DEFAULT_FRAME_STYLE, title=_('Objdictedit')) |
267 self._init_utils() |
310 self._init_utils() |
268 self.SetClientSize(wx.Size(1000, 700)) |
311 self.SetClientSize(wx.Size(1000, 700)) |
269 self.SetMenuBar(self.MenuBar) |
312 self.SetMenuBar(self.MenuBar) |
270 self.Bind(wx.EVT_CLOSE, self.OnCloseFrame) |
313 self.Bind(wx.EVT_CLOSE, self.OnCloseFrame) |
271 if not self.ModeSolo: |
314 if not self.ModeSolo: |
388 if result: |
431 if result: |
389 find_index = True |
432 find_index = True |
390 index, subIndex = result |
433 index, subIndex = result |
391 result = OpenPDFDocIndex(index, ScriptDirectory) |
434 result = OpenPDFDocIndex(index, ScriptDirectory) |
392 if isinstance(result, (StringType, UnicodeType)): |
435 if isinstance(result, (StringType, UnicodeType)): |
393 message = wx.MessageDialog(self, result, "ERROR", wx.OK|wx.ICON_ERROR) |
436 message = wx.MessageDialog(self, result, _("ERROR"), wx.OK|wx.ICON_ERROR) |
394 message.ShowModal() |
437 message.ShowModal() |
395 message.Destroy() |
438 message.Destroy() |
396 if not find_index: |
439 if not find_index: |
397 result = OpenPDFDocIndex(None, ScriptDirectory) |
440 result = OpenPDFDocIndex(None, ScriptDirectory) |
398 if isinstance(result, (StringType, UnicodeType)): |
441 if isinstance(result, (StringType, UnicodeType)): |
399 message = wx.MessageDialog(self, result, "ERROR", wx.OK|wx.ICON_ERROR) |
442 message = wx.MessageDialog(self, result, _("ERROR"), wx.OK|wx.ICON_ERROR) |
400 message.ShowModal() |
443 message.ShowModal() |
401 message.Destroy() |
444 message.Destroy() |
402 event.Skip() |
445 event.Skip() |
403 |
446 |
404 def OnHelpCANFestivalMenu(self, event): |
447 def OnHelpCANFestivalMenu(self, event): |
407 readerpath = get_acroversion() |
450 readerpath = get_acroversion() |
408 readerexepath = os.path.join(readerpath,"AcroRd32.exe") |
451 readerexepath = os.path.join(readerpath,"AcroRd32.exe") |
409 if(os.path.isfile(readerexepath)): |
452 if(os.path.isfile(readerexepath)): |
410 os.spawnl(os.P_DETACH, readerexepath, "AcroRd32.exe", '"%s"'%os.path.join(ScriptDirectory, "doc","manual_en.pdf")) |
453 os.spawnl(os.P_DETACH, readerexepath, "AcroRd32.exe", '"%s"'%os.path.join(ScriptDirectory, "doc","manual_en.pdf")) |
411 else: |
454 else: |
412 message = wx.MessageDialog(self, """Check if Acrobat Reader is correctly installed on your computer""", "ERROR", wx.OK|wx.ICON_ERROR) |
455 message = wx.MessageDialog(self, _("Check if Acrobat Reader is correctly installed on your computer"), _("ERROR"), wx.OK|wx.ICON_ERROR) |
413 message.ShowModal() |
456 message.ShowModal() |
414 message.Destroy() |
457 message.Destroy() |
415 |
|
416 else: |
458 else: |
417 try: |
459 try: |
418 os.system("xpdf -remote CANFESTIVAL %s %d &"%(os.path.join(ScriptDirectory, "doc/manual_en.pdf"),16)) |
460 os.system("xpdf -remote CANFESTIVAL %s %d &"%(os.path.join(ScriptDirectory, "doc/manual_en.pdf"),16)) |
419 except: |
461 except: |
420 message = wx.MessageDialog(self, """Check if xpdf is correctly installed on your computer""", "ERROR", wx.OK|wx.ICON_ERROR) |
462 message = wx.MessageDialog(self, _("Check if xpdf is correctly installed on your computer"), _("ERROR"), wx.OK|wx.ICON_ERROR) |
421 message.ShowModal() |
463 message.ShowModal() |
422 message.Destroy() |
464 message.Destroy() |
423 event.Skip() |
465 event.Skip() |
424 |
466 |
425 def OnAboutMenu(self, event): |
467 def OnAboutMenu(self, event): |
426 self.OpenHtmlFrame("About CAN Festival", os.path.join(ScriptDirectory, "doc/about.html"), wx.Size(500, 450)) |
468 self.OpenHtmlFrame(_("About CAN Festival"), os.path.join(ScriptDirectory, "doc/about.html"), wx.Size(500, 450)) |
427 event.Skip() |
469 event.Skip() |
428 |
470 |
429 def OpenHtmlFrame(self, title, file, size): |
471 def OpenHtmlFrame(self, title, file, size): |
430 if title not in self.HtmlFrameOpened: |
472 if title not in self.HtmlFrameOpened: |
431 self.HtmlFrameOpened.append(title) |
473 self.HtmlFrameOpened.append(title) |
444 if not self.ModeSolo: |
486 if not self.ModeSolo: |
445 if getattr(self, "_onclose", None) != None: |
487 if getattr(self, "_onclose", None) != None: |
446 self._onclose() |
488 self._onclose() |
447 event.Skip() |
489 event.Skip() |
448 elif self.Manager.OneFileHasChanged(): |
490 elif self.Manager.OneFileHasChanged(): |
449 dialog = wx.MessageDialog(self, "There are changes, do you want to save?", "Close Application", wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION) |
491 dialog = wx.MessageDialog(self, _("There are changes, do you want to save?"), _("Close Application"), wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION) |
450 answer = dialog.ShowModal() |
492 answer = dialog.ShowModal() |
451 dialog.Destroy() |
493 dialog.Destroy() |
452 if answer == wx.ID_YES: |
494 if answer == wx.ID_YES: |
453 for i in xrange(self.Manager.GetBufferNumber()): |
495 for i in xrange(self.Manager.GetBufferNumber()): |
454 if self.Manager.CurrentIsSaved(): |
496 if self.Manager.CurrentIsSaved(): |
489 window = self.FileOpened.GetPage(selected) |
531 window = self.FileOpened.GetPage(selected) |
490 selection = window.GetSelection() |
532 selection = window.GetSelection() |
491 if selection: |
533 if selection: |
492 index, subIndex = selection |
534 index, subIndex = selection |
493 if self.Manager.IsCurrentEntry(index): |
535 if self.Manager.IsCurrentEntry(index): |
494 self.HelpBar.SetStatusText("Index: 0x%04X"%index, 0) |
536 self.HelpBar.SetStatusText(_("Index: 0x%04X")%index, 0) |
495 self.HelpBar.SetStatusText("Subindex: 0x%02X"%subIndex, 1) |
537 self.HelpBar.SetStatusText(_("Subindex: 0x%02X")%subIndex, 1) |
496 entryinfos = self.Manager.GetEntryInfos(index) |
538 entryinfos = self.Manager.GetEntryInfos(index) |
497 name = entryinfos["name"] |
539 name = entryinfos["name"] |
498 category = "Optional" |
540 category = _("Optional") |
499 if entryinfos["need"]: |
541 if entryinfos["need"]: |
500 category = "Mandatory" |
542 category = _("Mandatory") |
501 struct = "VAR" |
543 struct = "VAR" |
502 number = "" |
544 number = "" |
503 if entryinfos["struct"] & OD_IdenticalIndexes: |
545 if entryinfos["struct"] & OD_IdenticalIndexes: |
504 number = " possibly defined %d times"%entryinfos["nbmax"] |
546 number = _(" possibly defined %d times")%entryinfos["nbmax"] |
505 if entryinfos["struct"] & OD_IdenticalSubindexes: |
547 if entryinfos["struct"] & OD_IdenticalSubindexes: |
506 struct = "REC" |
548 struct = "REC" |
507 elif entryinfos["struct"] & OD_MultipleSubindexes: |
549 elif entryinfos["struct"] & OD_MultipleSubindexes: |
508 struct = "ARRAY" |
550 struct = "ARRAY" |
509 text = "%s: %s entry of struct %s%s."%(name,category,struct,number) |
551 text = _("%s: %s entry of struct %s%s.")%(name,category,struct,number) |
510 self.HelpBar.SetStatusText(text, 2) |
552 self.HelpBar.SetStatusText(text, 2) |
511 else: |
553 else: |
512 for i in xrange(3): |
554 for i in xrange(3): |
513 self.HelpBar.SetStatusText("", i) |
555 self.HelpBar.SetStatusText("", i) |
514 else: |
556 else: |
557 length = self.AddMenu.GetMenuItemCount() |
599 length = self.AddMenu.GetMenuItemCount() |
558 for i in xrange(length-6): |
600 for i in xrange(length-6): |
559 additem = self.AddMenu.FindItemByPosition(6) |
601 additem = self.AddMenu.FindItemByPosition(6) |
560 self.AddMenu.Delete(additem.GetId()) |
602 self.AddMenu.Delete(additem.GetId()) |
561 if profile not in ("None", "DS-301"): |
603 if profile not in ("None", "DS-301"): |
562 edititem.SetText("%s Profile"%profile) |
604 edititem.SetText(_("%s Profile")%profile) |
563 edititem.Enable(True) |
605 edititem.Enable(True) |
564 self.AddMenu.AppendSeparator() |
606 self.AddMenu.AppendSeparator() |
565 for text, indexes in self.Manager.GetCurrentSpecificMenu(): |
607 for text, indexes in self.Manager.GetCurrentSpecificMenu(): |
566 new_id = wx.NewId() |
608 new_id = wx.NewId() |
567 self.AddMenu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=text) |
609 self.AddMenu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=text) |
568 self.Bind(wx.EVT_MENU, self.GetProfileCallBack(text), id=new_id) |
610 self.Bind(wx.EVT_MENU, self.GetProfileCallBack(text), id=new_id) |
569 else: |
611 else: |
570 edititem.SetText("Other Profile") |
612 edititem.SetText(_("Other Profile")) |
571 edititem.Enable(False) |
613 edititem.Enable(False) |
572 |
614 |
573 |
615 |
574 #------------------------------------------------------------------------------- |
616 #------------------------------------------------------------------------------- |
575 # Buffer Functions |
617 # Buffer Functions |
630 filepath = self.Manager.GetCurrentFilePath() |
672 filepath = self.Manager.GetCurrentFilePath() |
631 if filepath != "": |
673 if filepath != "": |
632 directory = os.path.dirname(filepath) |
674 directory = os.path.dirname(filepath) |
633 else: |
675 else: |
634 directory = os.getcwd() |
676 directory = os.getcwd() |
635 dialog = wx.FileDialog(self, "Choose a file", directory, "", "OD files (*.od)|*.od|All files|*.*", wx.OPEN|wx.CHANGE_DIR) |
677 dialog = wx.FileDialog(self, _("Choose a file"), directory, "", _("OD files (*.od)|*.od|All files|*.*"), wx.OPEN|wx.CHANGE_DIR) |
636 if dialog.ShowModal() == wx.ID_OK: |
678 if dialog.ShowModal() == wx.ID_OK: |
637 filepath = dialog.GetPath() |
679 filepath = dialog.GetPath() |
638 if os.path.isfile(filepath): |
680 if os.path.isfile(filepath): |
639 result = self.Manager.OpenFileInCurrent(filepath) |
681 result = self.Manager.OpenFileInCurrent(filepath) |
640 if isinstance(result, (IntType, LongType)): |
682 if isinstance(result, (IntType, LongType)): |
674 if not result: |
716 if not result: |
675 self.SaveAs() |
717 self.SaveAs() |
676 elif not isinstance(result, (StringType, UnicodeType)): |
718 elif not isinstance(result, (StringType, UnicodeType)): |
677 self.RefreshBufferState() |
719 self.RefreshBufferState() |
678 else: |
720 else: |
679 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR) |
721 message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR) |
680 message.ShowModal() |
722 message.ShowModal() |
681 message.Destroy() |
723 message.Destroy() |
682 |
724 |
683 def SaveAs(self): |
725 def SaveAs(self): |
684 filepath = self.Manager.GetCurrentFilePath() |
726 filepath = self.Manager.GetCurrentFilePath() |
685 if filepath != "": |
727 if filepath != "": |
686 directory, filename = os.path.split(filepath) |
728 directory, filename = os.path.split(filepath) |
687 else: |
729 else: |
688 directory, filename = os.getcwd(), "%s.od"%self.Manager.GetCurrentNodeInfos()[0] |
730 directory, filename = os.getcwd(), "%s.od"%self.Manager.GetCurrentNodeInfos()[0] |
689 dialog = wx.FileDialog(self, "Choose a file", directory, filename, "OD files (*.od)|*.od|All files|*.*", wx.SAVE|wx.OVERWRITE_PROMPT|wx.CHANGE_DIR) |
731 dialog = wx.FileDialog(self, _("Choose a file"), directory, filename, _("OD files (*.od)|*.od|All files|*.*"), wx.SAVE|wx.OVERWRITE_PROMPT|wx.CHANGE_DIR) |
690 if dialog.ShowModal() == wx.ID_OK: |
732 if dialog.ShowModal() == wx.ID_OK: |
691 filepath = dialog.GetPath() |
733 filepath = dialog.GetPath() |
692 if os.path.isdir(os.path.dirname(filepath)): |
734 if os.path.isdir(os.path.dirname(filepath)): |
693 result = self.Manager.SaveCurrentInFile(filepath) |
735 result = self.Manager.SaveCurrentInFile(filepath) |
694 if not isinstance(result, (StringType, UnicodeType)): |
736 if not isinstance(result, (StringType, UnicodeType)): |
695 self.RefreshBufferState() |
737 self.RefreshBufferState() |
696 else: |
738 else: |
697 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR) |
739 message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR) |
698 message.ShowModal() |
740 message.ShowModal() |
699 message.Destroy() |
741 message.Destroy() |
700 else: |
742 else: |
701 message = wx.MessageDialog(self, "%s is not a valid folder!"%os.path.dirname(filepath), "Error", wx.OK|wx.ICON_ERROR) |
743 message = wx.MessageDialog(self, _("%s is not a valid folder!")%os.path.dirname(filepath), _("Error"), wx.OK|wx.ICON_ERROR) |
702 message.ShowModal() |
744 message.ShowModal() |
703 message.Destroy() |
745 message.Destroy() |
704 dialog.Destroy() |
746 dialog.Destroy() |
705 |
747 |
706 def OnCloseMenu(self, event): |
748 def OnCloseMenu(self, event): |
707 answer = wx.ID_YES |
749 answer = wx.ID_YES |
708 result = self.Manager.CloseCurrent() |
750 result = self.Manager.CloseCurrent() |
709 if not result: |
751 if not result: |
710 dialog = wx.MessageDialog(self, "There are changes, do you want to save?", "Close File", wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION) |
752 dialog = wx.MessageDialog(self, _("There are changes, do you want to save?"), _("Close File"), wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION) |
711 answer = dialog.ShowModal() |
753 answer = dialog.ShowModal() |
712 dialog.Destroy() |
754 dialog.Destroy() |
713 if answer == wx.ID_YES: |
755 if answer == wx.ID_YES: |
714 self.OnSaveMenu(event) |
756 self.OnSaveMenu(event) |
715 if self.Manager.CurrentIsSaved(): |
757 if self.Manager.CurrentIsSaved(): |
729 #------------------------------------------------------------------------------- |
771 #------------------------------------------------------------------------------- |
730 # Import and Export Functions |
772 # Import and Export Functions |
731 #------------------------------------------------------------------------------- |
773 #------------------------------------------------------------------------------- |
732 |
774 |
733 def OnImportEDSMenu(self, event): |
775 def OnImportEDSMenu(self, event): |
734 dialog = wx.FileDialog(self, "Choose a file", os.getcwd(), "", "EDS files (*.eds)|*.eds|All files|*.*", wx.OPEN|wx.CHANGE_DIR) |
776 dialog = wx.FileDialog(self, _("Choose a file"), os.getcwd(), "", _("EDS files (*.eds)|*.eds|All files|*.*"), wx.OPEN|wx.CHANGE_DIR) |
735 if dialog.ShowModal() == wx.ID_OK: |
777 if dialog.ShowModal() == wx.ID_OK: |
736 filepath = dialog.GetPath() |
778 filepath = dialog.GetPath() |
737 if os.path.isfile(filepath): |
779 if os.path.isfile(filepath): |
738 result = self.Manager.ImportCurrentFromEDSFile(filepath) |
780 result = self.Manager.ImportCurrentFromEDSFile(filepath) |
739 if isinstance(result, (IntType, LongType)): |
781 if isinstance(result, (IntType, LongType)): |
743 self.FileOpened.SetSelection(self.FileOpened.GetPageCount() - 1) |
785 self.FileOpened.SetSelection(self.FileOpened.GetPageCount() - 1) |
744 self.RefreshBufferState() |
786 self.RefreshBufferState() |
745 self.RefreshCurrentIndexList() |
787 self.RefreshCurrentIndexList() |
746 self.RefreshProfileMenu() |
788 self.RefreshProfileMenu() |
747 self.RefreshMainMenu() |
789 self.RefreshMainMenu() |
748 message = wx.MessageDialog(self, "Import successful", "Information", wx.OK|wx.ICON_INFORMATION) |
790 message = wx.MessageDialog(self, _("Import successful"), _("Information"), wx.OK|wx.ICON_INFORMATION) |
749 message.ShowModal() |
791 message.ShowModal() |
750 message.Destroy() |
792 message.Destroy() |
751 else: |
793 else: |
752 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR) |
794 message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR) |
753 message.ShowModal() |
795 message.ShowModal() |
754 message.Destroy() |
796 message.Destroy() |
755 else: |
797 else: |
756 message = wx.MessageDialog(self, "\"%s\" is not a valid file!"%filepath, "Error", wx.OK|wx.ICON_ERROR) |
798 message = wx.MessageDialog(self, _("\"%s\" is not a valid file!")%filepath, _("Error"), wx.OK|wx.ICON_ERROR) |
757 message.ShowModal() |
799 message.ShowModal() |
758 message.Destroy() |
800 message.Destroy() |
759 dialog.Destroy() |
801 dialog.Destroy() |
760 event.Skip() |
802 event.Skip() |
761 |
803 |
762 def OnExportEDSMenu(self, event): |
804 def OnExportEDSMenu(self, event): |
763 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) |
805 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) |
764 if dialog.ShowModal() == wx.ID_OK: |
806 if dialog.ShowModal() == wx.ID_OK: |
765 filepath = dialog.GetPath() |
807 filepath = dialog.GetPath() |
766 if os.path.isdir(os.path.dirname(filepath)): |
808 if os.path.isdir(os.path.dirname(filepath)): |
767 path, extend = os.path.splitext(filepath) |
809 path, extend = os.path.splitext(filepath) |
768 if extend in ("", "."): |
810 if extend in ("", "."): |
769 filepath = path + ".eds" |
811 filepath = path + ".eds" |
770 result = self.Manager.ExportCurrentToEDSFile(filepath) |
812 result = self.Manager.ExportCurrentToEDSFile(filepath) |
771 if not result: |
813 if not result: |
772 message = wx.MessageDialog(self, "Export successful", "Information", wx.OK|wx.ICON_INFORMATION) |
814 message = wx.MessageDialog(self, _("Export successful"), _("Information"), wx.OK|wx.ICON_INFORMATION) |
773 message.ShowModal() |
815 message.ShowModal() |
774 message.Destroy() |
816 message.Destroy() |
775 else: |
817 else: |
776 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR) |
818 message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR) |
777 message.ShowModal() |
819 message.ShowModal() |
778 message.Destroy() |
820 message.Destroy() |
779 else: |
821 else: |
780 message = wx.MessageDialog(self, "\"%s\" is not a valid folder!"%os.path.dirname(filepath), "Error", wx.OK|wx.ICON_ERROR) |
822 message = wx.MessageDialog(self, _("\"%s\" is not a valid folder!")%os.path.dirname(filepath), _("Error"), wx.OK|wx.ICON_ERROR) |
781 message.ShowModal() |
823 message.ShowModal() |
782 message.Destroy() |
824 message.Destroy() |
783 dialog.Destroy() |
825 dialog.Destroy() |
784 event.Skip() |
826 event.Skip() |
785 |
827 |
786 def OnExportCMenu(self, event): |
828 def OnExportCMenu(self, event): |
787 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) |
829 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) |
788 if dialog.ShowModal() == wx.ID_OK: |
830 if dialog.ShowModal() == wx.ID_OK: |
789 filepath = dialog.GetPath() |
831 filepath = dialog.GetPath() |
790 if os.path.isdir(os.path.dirname(filepath)): |
832 if os.path.isdir(os.path.dirname(filepath)): |
791 path, extend = os.path.splitext(filepath) |
833 path, extend = os.path.splitext(filepath) |
792 if extend in ("", "."): |
834 if extend in ("", "."): |
793 filepath = path + ".c" |
835 filepath = path + ".c" |
794 result = self.Manager.ExportCurrentToCFile(filepath) |
836 result = self.Manager.ExportCurrentToCFile(filepath) |
795 if not result: |
837 if not result: |
796 message = wx.MessageDialog(self, "Export successful", "Information", wx.OK|wx.ICON_INFORMATION) |
838 message = wx.MessageDialog(self, _("Export successful"), _("Information"), wx.OK|wx.ICON_INFORMATION) |
797 message.ShowModal() |
839 message.ShowModal() |
798 message.Destroy() |
840 message.Destroy() |
799 else: |
841 else: |
800 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR) |
842 message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR) |
801 message.ShowModal() |
843 message.ShowModal() |
802 message.Destroy() |
844 message.Destroy() |
803 else: |
845 else: |
804 message = wx.MessageDialog(self, "\"%s\" is not a valid folder!"%os.path.dirname(filepath), "Error", wx.OK|wx.ICON_ERROR) |
846 message = wx.MessageDialog(self, _("\"%s\" is not a valid folder!")%os.path.dirname(filepath), _("Error"), wx.OK|wx.ICON_ERROR) |
805 message.ShowModal() |
847 message.ShowModal() |
806 message.Destroy() |
848 message.Destroy() |
807 dialog.Destroy() |
849 dialog.Destroy() |
808 event.Skip() |
850 event.Skip() |
809 |
851 |
811 # Editing Profiles functions |
853 # Editing Profiles functions |
812 #------------------------------------------------------------------------------- |
854 #------------------------------------------------------------------------------- |
813 |
855 |
814 def OnCommunicationMenu(self, event): |
856 def OnCommunicationMenu(self, event): |
815 dictionary,current = self.Manager.GetCurrentCommunicationLists() |
857 dictionary,current = self.Manager.GetCurrentCommunicationLists() |
816 self.EditProfile("Edit DS-301 Profile", dictionary, current) |
858 self.EditProfile(_("Edit DS-301 Profile"), dictionary, current) |
817 event.Skip() |
859 event.Skip() |
818 |
860 |
819 def OnOtherCommunicationMenu(self, event): |
861 def OnOtherCommunicationMenu(self, event): |
820 dictionary,current = self.Manager.GetCurrentDS302Lists() |
862 dictionary,current = self.Manager.GetCurrentDS302Lists() |
821 self.EditProfile("Edit DS-302 Profile", dictionary, current) |
863 self.EditProfile(_("Edit DS-302 Profile"), dictionary, current) |
822 event.Skip() |
864 event.Skip() |
823 |
865 |
824 def OnEditProfileMenu(self, event): |
866 def OnEditProfileMenu(self, event): |
825 title = "Edit %s Profile"%self.Manager.GetCurrentProfileName() |
867 title = _("Edit %s Profile")%self.Manager.GetCurrentProfileName() |
826 dictionary,current = self.Manager.GetCurrentProfileLists() |
868 dictionary,current = self.Manager.GetCurrentProfileLists() |
827 self.EditProfile(title, dictionary, current) |
869 self.EditProfile(title, dictionary, current) |
828 event.Skip() |
870 event.Skip() |
829 |
871 |
830 def EditProfile(self, title, dictionary, current): |
872 def EditProfile(self, title, dictionary, current): |
893 result = self.Manager.AddMapVariableToCurrent(index, name, struct, number) |
935 result = self.Manager.AddMapVariableToCurrent(index, name, struct, number) |
894 if not isinstance(result, (StringType, UnicodeType)): |
936 if not isinstance(result, (StringType, UnicodeType)): |
895 self.RefreshBufferState() |
937 self.RefreshBufferState() |
896 self.RefreshCurrentIndexList() |
938 self.RefreshCurrentIndexList() |
897 else: |
939 else: |
898 message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR) |
940 message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR) |
899 message.ShowModal() |
941 message.ShowModal() |
900 message.Destroy() |
942 message.Destroy() |
901 dialog.Destroy() |
943 dialog.Destroy() |
902 else: |
944 else: |
903 message = wx.MessageDialog(self, result, "No map variable index left!", wx.OK|wx.ICON_ERROR) |
945 message = wx.MessageDialog(self, result, _("No map variable index left!"), wx.OK|wx.ICON_ERROR) |
904 message.ShowModal() |
946 message.ShowModal() |
905 message.Destroy() |
947 message.Destroy() |
906 |
948 |
907 def AddUserType(self): |
949 def AddUserType(self): |
908 dialog = UserTypeDialog(self) |
950 dialog = UserTypeDialog(self) |
927 Max_Traceback_List_Size = 20 |
969 Max_Traceback_List_Size = 20 |
928 |
970 |
929 def Display_Exception_Dialog(e_type,e_value,e_tb): |
971 def Display_Exception_Dialog(e_type,e_value,e_tb): |
930 trcbck_lst = [] |
972 trcbck_lst = [] |
931 for i,line in enumerate(traceback.extract_tb(e_tb)): |
973 for i,line in enumerate(traceback.extract_tb(e_tb)): |
932 trcbck = " " + str(i+1) + ". " |
974 trcbck = " " + str(i+1) + _(". ") |
933 if line[0].find(os.getcwd()) == -1: |
975 if line[0].find(os.getcwd()) == -1: |
934 trcbck += "file : " + str(line[0]) + ", " |
976 trcbck += _("file : ") + str(line[0]) + _(", ") |
935 else: |
977 else: |
936 trcbck += "file : " + str(line[0][len(os.getcwd()):]) + ", " |
978 trcbck += _("file : ") + str(line[0][len(os.getcwd()):]) + _(", ") |
937 trcbck += "line : " + str(line[1]) + ", " + "function : " + str(line[2]) |
979 trcbck += _("line : ") + str(line[1]) + _(", ") + _("function : ") + str(line[2]) |
938 trcbck_lst.append(trcbck) |
980 trcbck_lst.append(trcbck) |
939 |
981 |
940 # Allow clicking.... |
982 # Allow clicking.... |
941 cap = wx.Window_GetCapture() |
983 cap = wx.Window_GetCapture() |
942 if cap: |
984 if cap: |
943 cap.ReleaseMouse() |
985 cap.ReleaseMouse() |
944 |
986 |
945 dlg = wx.SingleChoiceDialog(None, |
987 dlg = wx.SingleChoiceDialog(None, |
946 """ |
988 _(""" |
947 An error happens. |
989 An error happens. |
948 |
990 |
949 Click on OK for saving an error report. |
991 Click on OK for saving an error report. |
950 |
992 |
951 Please contact LOLITech at: |
993 Please contact LOLITech at: |
952 +33 (0)3 29 57 60 42 |
994 +33 (0)3 29 57 60 42 |
953 bugs_objdictedit@lolitech.fr |
995 bugs_objdictedit@lolitech.fr |
954 |
996 |
955 |
997 |
956 Error: |
998 Error: |
957 """ + |
999 """) + |
958 str(e_type) + " : " + str(e_value), |
1000 str(e_type) + _(" : ") + str(e_value), |
959 "Error", |
1001 _("Error"), |
960 trcbck_lst) |
1002 trcbck_lst) |
961 try: |
1003 try: |
962 res = (dlg.ShowModal() == wx.ID_OK) |
1004 res = (dlg.ShowModal() == wx.ID_OK) |
963 finally: |
1005 finally: |
964 dlg.Destroy() |
1006 dlg.Destroy() |
965 |
1007 |
966 return res |
1008 return res |
967 |
1009 |
968 def Display_Error_Dialog(e_value): |
1010 def Display_Error_Dialog(e_value): |
969 message = wx.MessageDialog(None, str(e_value), "Error", wx.OK|wx.ICON_ERROR) |
1011 message = wx.MessageDialog(None, str(e_value), _("Error"), wx.OK|wx.ICON_ERROR) |
970 message.ShowModal() |
1012 message.ShowModal() |
971 message.Destroy() |
1013 message.Destroy() |
972 |
1014 |
973 def get_last_traceback(tb): |
1015 def get_last_traceback(tb): |
974 while tb.tb_next: |
1016 while tb.tb_next: |