1
2
3
4
5
6
7
8
9
10
11
12
13 """
14 GUI Wrapper for L{XPyTools.codetpl.codetpl} Code template manager.
15 """
16
17 import wx
18 from wx.lib.anchors import LayoutAnchors
19 import wx.grid
20 import codetpl
21 import os
22
23
24
25
26 [wxID_CODETPLMANAGERDLG, wxID_CODETPLMANAGERDLGTXTTPLNAME,
27 wxID_CODETPLMANAGERDLGCHOICELANG, wxID_CODETPLMANAGERDLGGRIDFIELDS,
28 wxID_CODETPLMANAGERDLGLBLDESCRIPTION, wxID_CODETPLMANAGERDLGLBLFIELDS,
29 wxID_CODETPLMANAGERDLGLBLINFORMATION, wxID_CODETPLMANAGERDLGSTATICLINE1,
30 wxID_CODETPLMANAGERDLGTOOLBARTAB, wxID_CODETPLMANAGERDLGTREETPLNAMES,
31 wxID_CODETPLMANAGERDLGTXTDESCRIPTION, wxID_CODETPLMANAGERDLGTXTINFORMATION,
32 wxID_CODETPLMANAGERDLGTXTPREVIEW
33 ] = [wx.NewId() for _init_ctrls in range(13)]
34
36 """
37 Dialog, main window of gui templates.
38
39 For you may specify (set befor calling C{ShowModal()} dialog method)
40 L{self.language} and L{self.srcfile} and L{self.init_name}
41 for default language and source file for
42 which called template.
43
44 For setting of I{srcfile} and I{language} take effect you must call
45 L{self.ReloadCtrls} before calling show dialog.
46
47 I{init_name} - currently not work properly, but after fix in future
48 must select toolbar tool as here given.
49
50 For initialize this dialog you must additionaly get for parameters
51 L{codetpl.CodeTemplateMngr} instance.
52 """
53
54
55
57
58
59 parent.AddSizer(self.bsMiddleRightTopLeft, 1, border=0, flag=wx.EXPAND)
60 parent.AddSizer(self.bsMiddleRightTopRight, 2, border=0, flag=wx.EXPAND)
61
63
64
65 parent.AddSizer(self.bsMiddleRightTop, 2, border=0, flag=wx.EXPAND)
66 parent.AddWindow(self.lblFields, 0, border=2,
67 flag=wx.ALL | wx.ADJUST_MINSIZE | wx.ALIGN_TOP | wx.ALIGN_LEFT)
68 parent.AddWindow(self.gridFields, 3, border=2,
69 flag=wx.ALL | wx.ALIGN_BOTTOM | wx.EXPAND | wx.ALIGN_LEFT)
70
72
73
74 parent.AddWindow(self.lblInformation, 0, border=2,
75 flag=wx.ALL | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ADJUST_MINSIZE)
76 parent.AddWindow(self.txtInformation, 1, border=2,
77 flag=wx.ALL | wx.EXPAND| wx.ALIGN_LEFT)
78
80
81
82 parent.AddWindow(self.toolBarTab, 0, border=2,
83 flag=wx.ALL | wx.ALIGN_TOP)
84 parent.AddWindow(self.staticLine1, 0, border=2, flag=wx.ALL)
85 parent.AddSizer(self.bsMiddleSizer, 3, border=0, flag=wx.EXPAND)
86 parent.AddWindow(self.txtPreview, 2, border=2,
87 flag=wx.ALL | wx.EXPAND | wx.ALIGN_BOTTOM)
88 if self.sizerButtonSizer:
89 parent.AddSizer(self.sizerButtonSizer, 0, border=2, flag=0)
90
92
93
94 parent.AddWindow(self.txtTplName, 0, border=2,
95 flag=wx.ADJUST_MINSIZE | wx.EXPAND | wx.ALL | wx.ALIGN_TOP)
96 parent.AddWindow(self.treeTplNames, 2, border=2,
97 flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER_VERTICAL)
98 parent.AddWindow(self.choiceLang, 0, border=2,
99 flag=wx.ADJUST_MINSIZE | wx.EXPAND | wx.ALL | wx.ALIGN_BOTTOM)
100
102
103
104 parent.AddWindow(self.lblDescription, 0, border=2,
105 flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT | wx.ADJUST_MINSIZE)
106 parent.AddWindow(self.txtDescription, 1, border=2,
107 flag=wx.ALL | wx.EXPAND| wx.ALIGN_RIGHT)
108
110
111
112 parent.AddSizer(self.bsMiddleLeft, 3, border=0,
113 flag=wx.EXPAND | wx.ALIGN_LEFT)
114 parent.AddSizer(self.bsMiddleRight, 8, border=0,
115 flag=wx.EXPAND | wx.ALIGN_RIGHT)
116
144
146
147 wx.Dialog.__init__(self, id=wxID_CODETPLMANAGERDLG,
148 name=u'CodeTplManagerDlg', parent=prnt, pos=wx.Point(-1, -1),
149 size=wx.Size(888, 700),
150 style=wx.RESIZE_BORDER | wx.DEFAULT_DIALOG_STYLE,
151 title=u'Code template manager')
152 self.SetClientSize(wx.Size(880, 673))
153 self.SetToolTipString(u'')
154 self.SetHelpText(u'')
155 self.SetThemeEnabled(True)
156
157 self.toolBarTab = wx.ToolBar(id=wxID_CODETPLMANAGERDLGTOOLBARTAB,
158 name=u'toolBarTab', parent=self, pos=wx.Point(2, 2),
159 size=wx.Size(788, 30),
160 style=wx.TB_NOICONS | wx.TB_TEXT | wx.TB_HORIZONTAL)
161 self.toolBarTab.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD, False,
162 u'MS Shell Dlg 2'))
163 self.toolBarTab.SetThemeEnabled(False)
164 self.toolBarTab.SetToolTipString(u'')
165 self.toolBarTab.SetHelpText(u'Change code template mode')
166 self.toolBarTab.SetLabel(u'')
167 self.toolBarTab.SetToolPacking(0)
168 self.toolBarTab.SetMaxSize(wx.Size(-1, -1))
169 self.toolBarTab.SetMinSize(wx.Size(788, -1))
170
171 self.txtPreview = wx.TextCtrl(id=wxID_CODETPLMANAGERDLGTXTPREVIEW,
172 name=u'txtPreview', parent=self, pos=wx.Point(2, 361),
173 size=wx.Size(776, 209),
174 style=wx.STATIC_BORDER | wx.VSCROLL | wx.HSCROLL | wx.TE_READONLY | \
175 wx.TE_MULTILINE | wx.TE_DONTWRAP | wx.ALWAYS_SHOW_SB | wx.TE_RICH,
176 value='textCtrl1')
177 self.txtPreview.SetToolTipString(u'Preview code.')
178
179 f=wx.Font(pointSize=-1, family=wx.FONTFAMILY_MODERN, \
180 style= wx.FONTSTYLE_NORMAL, weight=wx.FONTWEIGHT_NORMAL)
181 f=wx.TextAttr(font=f)
182 f.SetFlags(wx.TEXT_ATTR_FONT)
183 self.txtPreview.SetDefaultStyle(f)
184
185 self.txtTplName = wx.TextCtrl(id=wxID_CODETPLMANAGERDLGTXTTPLNAME, name=u'txtTplName',
186 parent=self, pos=wx.Point(2, 42), size=wx.Size(256, 21), style= wx.TE_PROCESS_ENTER | \
187 wx.WANTS_CHARS, \
188 value='txtTplName')
189 self.txtTplName.SetToolTipString(u'Select arrows or enter template name.')
190
191 self.Bind(wx.EVT_TEXT, self.OntxtTplNameText, id=wxID_CODETPLMANAGERDLGTXTTPLNAME)
192 self.Bind(wx.EVT_TEXT_ENTER, self.OntxtTplNameEnter, id=wxID_CODETPLMANAGERDLGTXTTPLNAME)
193
194
195
196
197
198
199
200
201 self.treeTplNames = wx.TreeCtrl(id=wxID_CODETPLMANAGERDLGTREETPLNAMES,
202 name=u'treeTplNames', parent=self, pos=wx.Point(2, 67),
203 size=wx.Size(256, 265),
204 style=wx.STATIC_BORDER | wx.VSCROLL | wx.HSCROLL | wx.ALWAYS_SHOW_SB | wx.TR_HAS_BUTTONS | \
205 wx.TR_FULL_ROW_HIGHLIGHT | wx.TR_ROW_LINES | wx.TR_SINGLE | wx.TR_HAS_BUTTONS)
206 self.treeTplNames.SetToolTipString(u'Tree of templates by category. You may select template here.')
207 self.treeTplNames.SetQuickBestSize(True)
208 self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OntreeTplNamesSelChanged, id=wxID_CODETPLMANAGERDLGTREETPLNAMES)
209
210 self.choiceLang = wx.Choice(choices=[],
211 id=wxID_CODETPLMANAGERDLGCHOICELANG, name=u'choiceLang',
212 parent=self, pos=wx.Point(2, 336), size=wx.Size(256, 21),
213 style=0)
214 self.choiceLang.SetToolTipString(u'Select language. Usualy not needed (select auto).')
215 self.Bind(wx.EVT_CHOICE, self.OnChoiceSelected, id=wxID_CODETPLMANAGERDLGCHOICELANG)
216
217 self.lblFields = wx.StaticText(id=wxID_CODETPLMANAGERDLGLBLFIELDS,
218 label=u'Fields:', name=u'lblFields', parent=self,
219 pos=wx.Point(262, 162), size=wx.Size(31, 13), style=0)
220 self.lblFields.SetToolTipString(u'')
221 self.lblFields.SetMinSize(wx.Size(-1, -1))
222
223 self.gridFields = wx.grid.Grid(id=wxID_CODETPLMANAGERDLGGRIDFIELDS,
224 name=u'gridFields', parent=self, pos=wx.Point(262, 179),
225 size=wx.Size(516, 177),
226 style=wx.VSCROLL | wx.HSCROLL | wx.ALWAYS_SHOW_SB)
227 self.gridFields.SetToolTipString(u'')
228 self.gridFields.CreateGrid(5, 1, 0)
229 self.gridFields.SetColLabelValue(0, ' Field value ')
230 w1=self.gridFields.GetColSize(0)
231 self.gridFields.SetRowLabelAlignment(wx.ALIGN_LEFT, wx.ALIGN_CENTER)
232 self.gridFields.SetColSize(0,w1*5.5)
233 self.gridFields.SetRowLabelSize(w1*2)
234
235 self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OngridCellChange)
236
237
238
239 self.staticLine1 = wx.StaticLine(id=wxID_CODETPLMANAGERDLGSTATICLINE1,
240 name='staticLine1', parent=self, pos=wx.Point(2, 36),
241 size=wx.Size(788, 2), style=wx.LI_HORIZONTAL)
242 self.staticLine1.SetConstraints(LayoutAnchors(self.staticLine1, True,
243 True, False, False))
244 self.staticLine1.SetToolTipString(u'')
245
246 self.lblInformation = wx.StaticText(id=wxID_CODETPLMANAGERDLGLBLINFORMATION,
247 label=u'Information:', name=u'lblInformation', parent=self,
248 pos=wx.Point(262, 42), size=wx.Size(60, 13), style=0)
249 self.lblInformation.SetToolTipString(u'')
250 self.lblInformation.SetMinSize(wx.Size(-1, -1))
251
252 self.lblDescription = wx.StaticText(id=wxID_CODETPLMANAGERDLGLBLDESCRIPTION,
253 label=u'Description', name=u'lblDescription', parent=self,
254 pos=wx.Point(522, 42), size=wx.Size(53, 13), style=0)
255 self.lblDescription.SetToolTipString(u'')
256 self.lblDescription.SetMinSize(wx.Size(-1, -1))
257
258 self.txtInformation = wx.TextCtrl(id=wxID_CODETPLMANAGERDLGTXTINFORMATION,
259 name=u'txtInformation', parent=self, pos=wx.Point(262, 59),
260 size=wx.Size(256, 99), style=wx.STATIC_BORDER | wx.TE_MULTILINE | wx.TE_READONLY | \
261 wx.TE_RICH,
262 value=u'textCtrl2')
263 self.txtInformation.SetToolTipString(u'')
264
265 self.txtDescription = wx.TextCtrl(id=wxID_CODETPLMANAGERDLGTXTDESCRIPTION,
266 name=u'txtDescription', parent=self, pos=wx.Point(522, 59),
267 size=wx.Size(256, 99), style=wx.STATIC_BORDER | wx.TE_MULTILINE | \
268 wx.TE_READONLY, value='textCtrl3')
269 self.txtDescription.SetToolTipString(u'')
270
271 self._init_sizers()
272
273
274 self.Bind(wx.EVT_BUTTON, self.OnOk, id=wx.ID_OK)
275 self.Bind(wx.EVT_BUTTON, self.OnCancel, id=wx.ID_CANCEL)
276
277 self.Bind(wx.EVT_ACTIVATE, self.OnActivate)
278
280 """
281 @param ctm: XPyTools.codetpl.codetpl.CodetemplateMngr instance.
282 @type ctm: L{XPyTools.codetpl.codetpl.CodetemplateMngr}
283 """
284
285
286
287 self._init_ctrls(parent)
288
289 icofile='codetpl.bmp'
290 path=os.path.join(os.path.dirname(__file__),icofile)
291
292 if os.path.exists(path):
293 icon=wx.Icon(path,wx.BITMAP_TYPE_ICO,-1,-1)
294 else:
295 icon=wx.NullIcon
296 self.SetIcon(icon)
297
298
299
300
301
302
303 self.ctm=ctm
304
305
306
307
308
309
310 self.__types={}
311
312
313
314 self.__fields={}
315
316
317
318 self.__lang=codetpl.ANY
319
320
321
322 self.__type=''
323
324
325
326 self.init_name=''
327
328
329
330 self.__tpls=[]
331
332
333
334 self.__tplsid=[]
335
336
337
338 self.__prevval=''
339
340
341
342 self.__nomodtxt=False
343
344
345
346
347 self.srcfile='SRCFILE'
348
349
350
351
352 self.params={}
353
354
355
356
357
358 self.language=codetpl.ANY
359
360
361
362 self.result=''
363
364
365 self.ReloadToolbar()
366
367
368 self.ReloadCtrls()
369
370
371
372
408
410 """
411 Reload controls content.
412
413 1st stage: reload choiceLang.
414 """
415
416
417
418 self.txtTplName.ChangeValue('')
419 self.choiceLang.Clear()
420 self.treeTplNames.DeleteAllItems()
421 self.txtDescription.Clear()
422 self.txtInformation.Clear()
423 self.txtPreview.Clear()
424 self.result=''
425 self.__tpls=[]
426 self.__tplsid=[]
427 self.__prevval=''
428 self.__nomodtxt=False
429 self.ClearGrid()
430
431
432 if not type:
433 return
434
435
436 lang=self.ctm.GetMetaAllValues(self.__type, 'language')
437
438 lang.sort()
439 if codetpl.ANY in lang:
440 lang.remove(codetpl.ANY)
441 lang.append(codetpl.ANY)
442 self.choiceLang.AppendItems(lang)
443 if self.language:
444 self.__lang=self.language
445
446
447 i=self.choiceLang.FindString(self.__lang)
448
449 if i==wx.NOT_FOUND:
450 i=0
451 self.choiceLang.SetSelection(i)
452 self.__lang=self.choiceLang.GetStringSelection()
453
454 assert self.__lang!=''
455
456 self.ReloadCtrls2()
457
459 """
460 Reload controls.
461 Stage 2: Reload all exclude choiceLang.
462 """
463
464
465
466
467 self.__tpls=[]
468 self.__tplsid=[]
469 self.__prevval=''
470 self.__nomodtxt=False
471 self.result=''
472 self.txtTplName.ChangeValue('')
473 self.treeTplNames.DeleteAllItems()
474
475
476
477
478
479 f={'language':self.__lang}
480
481 tpls=self.ctm.GetTemplates(self.__type, f, self.__lang==codetpl.ANY)
482 tpls.sort()
483
484
485
486
487 cat={'Unknown':[]}
488
489 for t in tpls:
490
491 mi=self.ctm.GetMetaInfo(self.__type, t)
492 if mi[1].has_key('category'):
493 c=mi[1]['category']
494 else:
495 c='Unknown'
496
497 if c==codetpl.ANY or c=='':
498 c='Unknown'
499 if not cat.has_key(c):
500 cat[c]=[]
501 cat[c].append(t)
502
503
504
505 self.__tpls=[]
506 self.__tplsid=[]
507 r=self.treeTplNames.AddRoot('Templates')
508 self.treeTplNames.SetItemBold(r)
509 for k,v in cat.items():
510 if v:
511 f=self.treeTplNames.AppendItem(r, k)
512 self.treeTplNames.SetItemBold(f)
513 for t in v:
514
515 self.__tpls.append(t)
516 self.__tplsid.append(self.treeTplNames.AppendItem(f, t))
517
518
519
520 self.treeTplNames.Expand(r)
521 self.txtTplName.SetFocus()
522
524 """
525 Clear grid.
526 """
527
528 self.gridFields.ClearGrid()
529 nr=self.gridFields.GetNumberRows()
530 for i in xrange(nr):
531 self.gridFields.SetRowLabelValue(i,'')
532
534 """
535 You must clear grid if need by calling L{self.ClearGrid}.
536 """
537 nr=self.gridFields.GetNumberRows()
538
539 i=0
540 for k,v in self.__fields.items():
541 if i >= nr:
542 nr+=1
543 self.gridFields.AppendRows(1)
544 self.gridFields.SetRowLabelValue(i,k)
545 self.gridFields.SetCellValue(i, 0, v)
546 i+=1
547
548
550 """
551 Validate with whole templates name and partial.
552 For partial validation return fist equal template name.
553
554 @param txt: Text for validation with templates name.
555 @type txt: str
556 @return: liked template name if text is valid or empty string.
557 @rtype: str
558 """
559 for i in self.__tpls:
560 if i.startswith(txt):
561 return i
562
563
564 return ''
565
567 """
568 Fill controls for priview.
569
570 Before calling preview you must set or clear L{self.__fields}.
571 If need you must fill Fields grid by calling L{self.FillGrid}.
572
573 @note: If error rised then return error message as template string.
574 """
575
576 self.txtDescription.Clear()
577 self.txtInformation.Clear()
578 self.txtPreview.Clear()
579
580 sel=self.treeTplNames.GetSelection()
581
582 if not sel.IsOk:
583 return
584
585 if not self.txtTplName.Value:
586 return
587 t=self.treeTplNames.GetItemText(sel)
588 if not self.ValidateTxt(t):
589 return
590
591 d,m=self.ctm.GetMetaInfo(self.__type, t)
592 self.txtDescription.AppendText(d)
593
594 fb=wx.Font(pointSize=-1, family=wx.FONTFAMILY_DEFAULT, \
595 style=wx.FONTSTYLE_NORMAL, weight=wx.FONTWEIGHT_BOLD)
596 fn=wx.Font(pointSize=-1, family=wx.FONTFAMILY_DEFAULT, \
597 style=wx.FONTSTYLE_NORMAL, weight=wx.FONTWEIGHT_NORMAL)
598 sb=wx.TextAttr(font=fb)
599 sb.SetFlags(wx.TEXT_ATTR_FONT_WEIGHT)
600 sn=wx.TextAttr(font=fn)
601 sn.SetFlags(wx.TEXT_ATTR_FONT_WEIGHT)
602 for k,v in m.items():
603 self.txtInformation.SetDefaultStyle(sb)
604 self.txtInformation.AppendText(k.capitalize()+': ')
605 self.txtInformation.SetDefaultStyle(sn)
606 self.txtInformation.AppendText(v+'\n')
607 try:
608 d=self.ctm.ParseTemplate(self.__type, t, self.__fields, self.srcfile, self.params)
609
610 except codetpl.codetplArgumentError, e:
611
612 d='ERROR: ' + str(e)
613 self.txtPreview.AppendText(d)
614
615 self.txtPreview.ShowPosition(0)
616
617
618
619
620
636
638 """
639 Language changed.
640 """
641
642 self.__lang=event.GetString()
643 assert self.__lang!=''
644 self.ReloadCtrls2()
645 event.Skip()
646
648 """
649 Tree selection changed.
650 """
651
652 sel=treeevent.GetItem()
653 t=self.treeTplNames.GetItemText(sel)
654
655 if self.ValidateTxt(t) and not self.__nomodtxt:
656 self.txtTplName.ChangeValue(t)
657 self.txtTplName.SetInsertionPointEnd()
658 self.__nomodtxt=False
659
660 self.__fields={}
661 self.Preview()
662 self.ClearGrid()
663 self.FillGrid()
664 treeevent.Skip()
665
666 - def OntxtTplNameText(self, event=None):
667 """
668 Validate input to existing templates.
669
670 @Note: C{event} may be None if method called from code for validating.
671 """
672
673 t=self.txtTplName.GetValue()
674 if t in self.__tpls:
675 self.__nomodtxt=True
676 self.treeTplNames.SelectItem(self.__tplsid[self.__tpls.index(t)])
677 self.__prevval=t
678 else:
679 i=self.ValidateTxt(t)
680 if i:
681
682 self.__prevval=t
683 self.__nomodtxt=True
684 self.treeTplNames.SelectItem(self.__tplsid[self.__tpls.index(i)])
685 self.txtTplName.ChangeValue(i)
686 self.txtTplName.SetSelection(len(t), -1)
687 else:
688
689 self.txtTplName.ChangeValue(self.__prevval)
690 self.txtTplName.SetInsertionPointEnd()
691
692 if event:
693 event.Skip()
694
695
697 """
698 """
699 kc=keyevent.GetKeyCode()
700
701 dbg.writeln('Key Event hand, key code=', str(kc))
702 keyevent.Skip()
703
705 """
706 Enter pressed, work for templates
707 and end modal.
708 """
709 dbg.writeln('Enter pressed')
710 if self.txtTplName.Value:
711 self.DoAction()
712 self.EndModal(1)
713 else:
714 self.result=''
715 self.EndModal(0)
716 event.Skip()
717
719 """
720 Call handler for working with selected template.
721
722 If find method named B{toolbarhandler_I{typ}}, where typ - template type,
723 then call it, else call default handler L{toolhandlerdefault}.
724 """
725 self.result=''
726
727
728
729 hname='toolbarhandler_' + self.__type
730 h=getattr(self, hname, None)
731 try:
732 if h:
733 h()
734 else:
735
736 self.toolhandlerdefault()
737
738 except Exception, e:
739 self.result='ERROR: '+str(e)
740
742 """
743 Field value changed event.
744
745 Update L{self.__fields}, and preview.
746 """
747 k=self.gridFields.GetRowLabelValue( gridevent.GetRow() )
748 v=self.gridFields.GetCellValue( gridevent.GetRow(), gridevent.GetCol() )
749 if self.__fields.has_key(k):
750 self.__fields[k]=unicode(v)
751 self.Preview()
752 gridevent.Skip()
753
754 - def OnOk(self, event):
755 """
756 Okey event/button.
757
758 @return: 1 == True.
759 """
760 self.DoAction()
761 self.EndModal(1)
762
763 event.Skip()
764
766 """
767 Cancel event/button.
768
769 @return: 0 == False.
770 """
771 self.result=''
772
773 self.EndModal(0)
774
775 event.Skip()
776
777
779 """
780 Try select tool then window activated.
781 """
782
783 event.Skip()
784 return
785
786 if event.GetActive() or True:
787
788
789
790 if (len(self.__types) > 0):
791 if not self.init_name and not self.__types.has_key(self.init_name):
792 self.init_name=self.__types.keys()[0]
793 id=self.__types[self.init_name][4]
794
795 self.__type=self.__types[self.init_name][0]
796
797 self.toolBarTab.ToggleTool(self.__types[self.init_name][4], True)
798 self.toolBarTab.Realize()
799
800 self.toolBarTab.Realize()
801 tool=self.toolBarTab.FindById(id)
802
803
804 event.Skip()
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
852
853
854
855
856
857
858 if __name__=='__main__':
859 app=wx.PySimpleApp()
860
861
862
863
864
865 dlg=CodeTplManagerDlg(None, \
866 codetpl.CodeTemplateMngr() )
867
868 try:
869
870 setattr(dlg, 'init_name','New')
871
872
873 dlg.ShowModal()
874
875 pass
876 finally:
877 dlg.Destroy()
878 pass
879