ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/ns_dev/Python/NinoCode/Active_prgs/MCP/MCP_ViewEdit_UI.py
Revision: 262
Committed: Fri Feb 1 23:56:28 2013 UTC (13 years, 1 month ago) by nino.borges
Content type: text/x-python
File size: 22145 byte(s)
Log Message:
Added the case directories settings

File Contents

# Content
1 """
2
3 MCP_ViewEdit_UI
4
5 Created by
6 Emanuel Borges
7 03.17.2011
8
9 This is the UI for viewing or editing case info
10
11 """
12
13
14 import wx, MCP_Lib, MCP_Console,os,CurrentProductionsDialog,CaseUploadsDialog,AddDocumentProductionDialog,CasePathsDialog,NinoGenTools
15
16 class MyFrame(wx.Frame):
17 def __init__(self, parent, ID, title, pos=wx.DefaultPosition):
18 self.console = MCP_Console.MainConsole()
19
20 wx.Frame.__init__(self, parent, ID, title, pos, size =(550,580))
21 self.panel = wx.Panel(self,-1)
22
23 #self.panel.SetBackgroundColour("yellow green")
24 casesListStaticText = wx.StaticText(self.panel, -1, "Select Case: ",wx.DefaultPosition)
25 #casesList,casesDir = MCP_Lib.GetCaseList()
26 self.myCases, self.officeCases, self.allCases, casesDir = MCP_Lib.GetCaseList()
27 self.casesListChoice = wx.Choice(self.panel, -1, wx.DefaultPosition, choices=self.myCases)
28 self.casesListChoice.SetSelection(0)
29 self.chargeableCheckBox = wx.CheckBox(self.panel,-1,"Chargeable?")
30 responsibleAttnyStaticText = wx.StaticText(self.panel, -1, "Responsible Attorney: ",wx.DefaultPosition)
31 self.responsibleAttnyTextCtrl = wx.TextCtrl(self.panel, -1, "", wx.DefaultPosition, (110,-1))
32 responsibleParalegalStaticText = wx.StaticText(self.panel, -1, "Responsible Paralegal: ",wx.DefaultPosition)
33 self.responsibleParalegalTextCtrl = wx.TextCtrl(self.panel, -1, "", wx.DefaultPosition, (110,-1))
34 platformChoicesList = ["",'Concordance DIS','Concordance LN','Relativity']
35 reviewPlatformStaticText = wx.StaticText(self.panel, -1, "Platform: ",wx.DefaultPosition)
36 self.reviewPlatformChoice = wx.Choice(self.panel, -1, wx.DefaultPosition, choices=platformChoicesList)
37 responsibleProcessingVendorStaticText = wx.StaticText(self.panel, -1, "Processing Vendor: ",wx.DefaultPosition)
38 self.responsibleProcessingVendorTextCtrl = wx.TextCtrl(self.panel, -1, "", wx.DefaultPosition, (150,-1))
39 responsibleScanningVendorStaticText = wx.StaticText(self.panel, -1, "Scanning Vendor: ",wx.DefaultPosition)
40 self.responsibleScanningVendorTextCtrl = wx.TextCtrl(self.panel, -1, "", wx.DefaultPosition, (150,-1))
41 responsibleHostingVendorStaticText = wx.StaticText(self.panel, -1, "Hosting Vendor: ",wx.DefaultPosition)
42 self.responsibleHostingVendorTextCtrl = wx.TextCtrl(self.panel, -1, "", wx.DefaultPosition, (150,-1))
43 responsibleTPMStaticText = wx.StaticText(self.panel, -1, "TPM: ",wx.DefaultPosition)
44 self.responsibleTPMTextCtrl = wx.TextCtrl(self.panel, -1, "", wx.DefaultPosition, (110,-1))
45 responsibleOfficeStaticText = wx.StaticText(self.panel, -1, "Office: ",wx.DefaultPosition)
46 self.responsibleOfficeTextCtrl = wx.TextCtrl(self.panel, -1, "", wx.DefaultPosition, (110,-1))
47 caseStatusStaticText = wx.StaticText(self.panel, -1, "Case Status: ",wx.DefaultPosition)
48 statusChoicesList = ['Active','Dormant','Closed','Archived']## Selecting archived automatically unchecks chareable.
49 self.caseStatusChoice = wx.Choice(self.panel, -1, wx.DefaultPosition, choices=statusChoicesList)
50
51
52 self.SetFields(self.myCases[0])
53
54 self.CreateBoxesSection()
55
56 casesSizer = wx.BoxSizer(wx.HORIZONTAL)
57 casesSizer.Add(casesListStaticText,0,wx.ALL,5)
58 casesSizer.Add(self.casesListChoice,0,wx.ALL,5)
59
60 secondHalfSizer = wx.GridBagSizer(5,5)
61 secondHalfSizer.Add(reviewPlatformStaticText, pos=(0,0))
62 secondHalfSizer.Add(self.reviewPlatformChoice, pos=(0,1))
63 secondHalfSizer.Add(self.chargeableCheckBox,pos=(0,3))
64 #secondHalfSizer.Add(self.chargeableCheckBox,pos=(0,2), span=(1,2), flag = wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL)
65 secondHalfSizer.Add(responsibleAttnyStaticText, pos=(1,0))
66 secondHalfSizer.Add(self.responsibleAttnyTextCtrl, pos=(1,1))
67 secondHalfSizer.Add(responsibleTPMStaticText, pos = (1,2))
68 secondHalfSizer.Add(self.responsibleTPMTextCtrl, pos = (1,3))
69 secondHalfSizer.Add(responsibleParalegalStaticText, pos=(2,0))
70 secondHalfSizer.Add(self.responsibleParalegalTextCtrl, pos=(2,1))
71 secondHalfSizer.Add(responsibleOfficeStaticText, pos=(2,2))
72 secondHalfSizer.Add(self.responsibleOfficeTextCtrl, pos=(2,3))
73 secondHalfSizer.Add(caseStatusStaticText, pos=(3,0))
74 secondHalfSizer.Add(self.caseStatusChoice, pos=(3,1))
75
76 respVendorsStaticBox = wx.StaticBox(self.panel, -1, 'Responsible Vendors:')
77 respVendorsStaticBoxSizer = wx.StaticBoxSizer(respVendorsStaticBox, wx.VERTICAL)
78 respVendorsFlexGridSizer = wx.FlexGridSizer(3,2,10,10)
79 respVendorsFlexGridSizer.Add(responsibleProcessingVendorStaticText,5)
80 respVendorsFlexGridSizer.Add(self.responsibleProcessingVendorTextCtrl,5)
81 respVendorsFlexGridSizer.Add(responsibleScanningVendorStaticText,5)
82 respVendorsFlexGridSizer.Add(self.responsibleScanningVendorTextCtrl,5)
83 respVendorsFlexGridSizer.Add(responsibleHostingVendorStaticText,5)
84 respVendorsFlexGridSizer.Add(self.responsibleHostingVendorTextCtrl,5)
85 respVendorsStaticBoxSizer.Add(respVendorsFlexGridSizer,0,wx.ALL,20)
86
87 mainSizer = wx.BoxSizer(wx.VERTICAL)
88 mainSizer.Add(casesSizer,0,wx.ALL, 20)
89 mainSizer.Add(secondHalfSizer,0,wx.ALL,20)
90 mainSizer.Add(respVendorsStaticBoxSizer,0,wx.ALL,20)
91 #mainSizer.Add(self.chargeableCheckBox,0,wx.ALL,5)
92 #mainSizer.Add(self.reviewPlatformChoice,0,wx.ALL,5)
93 #mainSizer.Add(self.responsibleAttnyTextCtrl,0,wx.ALL,5)
94 #mainSizer.Add(self.responsibleParalegalTextCtrl,0,wx.ALL,5)
95 #mainSizer.Add(self.responsibleProcessingVendorTextCtrl,0,wx.ALL,5)
96 #mainSizer.Add(self.responsibleScanningVendorTextCtrl,0,wx.ALL,5)
97 #mainSizer.Add(self.responsibleHostingVendorTextCtrl,0,wx.ALL,5)
98 #mainSizer.Add(workDirSizer,0,wx.ALL, 10)
99 #mainSizer.Add(copyUpTypeStaticBoxSizer, 0, wx.ALL, 10)
100 mainSizer.Add(self.buttonSizer,0, wx.ALL|wx.ALIGN_BOTTOM|wx.ALIGN_CENTER, 10)
101
102 self.oKButton.Disable()
103
104 #self.chargeableCheckBox.Disable() ## Remove me.
105
106 self.panel.SetSizer(mainSizer)
107
108 self.CreateStatusBar()
109 self.SetStatusText("Ready.")
110 self.CreateMenuBar()
111
112 self.Bind(wx.EVT_CHOICE, self.OnSetFields, self.casesListChoice)
113 self.Bind(wx.EVT_CHOICE, self.OnFormChanged, self.reviewPlatformChoice)
114 self.Bind(wx.EVT_CHOICE, self.OnFormChanged, self.caseStatusChoice)
115 self.Bind(wx.EVT_CHECKBOX, self.OnFormChanged, self.chargeableCheckBox)
116 self.Bind(wx.EVT_TEXT, self.OnFormChanged, self.responsibleAttnyTextCtrl)
117 self.Bind(wx.EVT_TEXT, self.OnFormChanged, self.responsibleTPMTextCtrl)
118 self.Bind(wx.EVT_TEXT, self.OnFormChanged, self.responsibleParalegalTextCtrl)
119 self.Bind(wx.EVT_TEXT, self.OnFormChanged, self.responsibleOfficeTextCtrl)
120 self.Bind(wx.EVT_TEXT, self.OnFormChanged, self.responsibleProcessingVendorTextCtrl)
121 self.Bind(wx.EVT_TEXT, self.OnFormChanged, self.responsibleScanningVendorTextCtrl)
122 self.Bind(wx.EVT_TEXT, self.OnFormChanged, self.responsibleHostingVendorTextCtrl)
123
124 self.Bind(wx.EVT_BUTTON, self.OnProcess, self.oKButton)
125 self.Bind(wx.EVT_BUTTON, self.CloseWindow, self.cancelButton)
126
127 def NothingYet(self,event):
128 """ A simple place holder function that is used to be a PASS statment when I'm creating controls"""
129 diag = wx.MessageDialog(self,"Nothing here yet!", "Disabled...",wx.OK | wx.ICON_INFORMATION)
130 diag.ShowModal()
131 diag.Destroy()
132
133 def MenuData(self):
134 return(("View",
135 ("My Cases", "Chooses from your assigned cases.",self.OnChangeCaseView,"RADIO"),
136 ("My Office Cases", "Chooses from cases assigned to everyone in your office.",self.OnChangeCaseView,"RADIO"),
137 ("All Cases", "Chooses from all cases.",self.OnChangeCaseView,"RADIO"),
138 ("","","",""),
139 ("Case &Uploads", "Displays the Case Uploads for this case.",self.OnViewCaseUploads,""),
140 ("&Production History", "Displays the Production History for this case.",self.OnViewDocProduction,""),
141 ("","","",""),
142 ("My Case &Notes","Opens the case notes file for the current selected case.",self.OnViewCaseNotes,""),
143 ("My Production &Spec","Opens the production specifications file for the current selected case.",self.OnViewProdSpec,""),
144 ("&Alternate Media Folder","Opens the alternate media path for the current selected case.",self.OnOpenAlternateMediaFolder,""),
145 ("Open Case &Folder","Opens the case folder for the current selected case.",self.OnOpenCaseFolder,"")),
146 ("Production",
147 ("&Add Production Entry","Adds a new production to the matter database.",self.OnAddDocProduction,"")),
148 ("Settings",
149 ("Linked &Vendor Folders","Allows you to link vendor folders to this case for copy ups.",self.NothingYet,""),
150 ("&Case Paths","Allows you to set or change the alternate media path.",self.OnCasePathsSettings,"")),
151 ("&Help",
152 ("&About", "Displays the About Window.", self.OnAbout,"")))
153
154 def CreateMenuBar(self):
155 menuBar = wx.MenuBar()
156 count = 1
157 for eachMenuData in self.MenuData():
158 menuLabel = eachMenuData[0]
159 menuItems = eachMenuData[1:]
160 menuBar.Append(self.CreateMenu(menuItems), menuLabel)
161 count = count + 1
162 self.SetMenuBar(menuBar)
163
164
165 def CreateMenu(self, menuData):
166 menu = wx.Menu()
167 for eachLabel, eachStatus, eachHandler, eachType in menuData:
168 if not eachLabel:
169 menu.AppendSeparator()
170 continue
171 if eachType == "RADIO":
172 menuItem = menu.AppendRadioItem(-1,eachLabel,eachStatus)
173 else:
174 menuItem = menu.Append(-1, eachLabel, eachStatus)
175 self.Bind(wx.EVT_MENU, eachHandler, menuItem)
176 return menu
177
178
179 def OnFormChanged(self,event):
180 self.oKButton.Enable()
181
182 def OnSetFields(self,event):
183 #print self.casesListChoice.GetStringSelection()
184 self.SetFields(self.casesListChoice.GetStringSelection())
185 self.oKButton.Disable()
186
187 def SetFields(self, case):
188 currentChargeableBool,currentRespAttorney,currentRespParalegal,currentRespVendorTpl,currentRevPlatform,respTPM,respOffice,caseStatus = self.console.GetCaseData(case)
189 if currentChargeableBool:
190 self.chargeableCheckBox.SetValue(True)
191 else:
192 self.chargeableCheckBox.SetValue(False)
193 if currentRevPlatform == 'Concordance':
194 ## Make an assumption
195 currentRevPlatform = "Concordance DIS"
196 if currentRevPlatform:
197 #print currentRevPlatform
198 self.reviewPlatformChoice.SetStringSelection(currentRevPlatform)
199 else:
200 self.reviewPlatformChoice.SetStringSelection('')
201 if currentRespAttorney:
202 self.responsibleAttnyTextCtrl.SetValue(currentRespAttorney)
203 else:
204 self.responsibleAttnyTextCtrl.SetValue('')
205 if currentRespParalegal:
206 self.responsibleParalegalTextCtrl.SetValue(currentRespParalegal)
207 else:
208 self.responsibleParalegalTextCtrl.SetValue('')
209 if currentRespVendorTpl[0]:
210 self.responsibleProcessingVendorTextCtrl.SetValue(currentRespVendorTpl[0])
211 else:
212 self.responsibleProcessingVendorTextCtrl.SetValue("")
213 if currentRespVendorTpl[1]:
214 self.responsibleScanningVendorTextCtrl.SetValue(currentRespVendorTpl[1])
215 else:
216 self.responsibleScanningVendorTextCtrl.SetValue('')
217 if currentRespVendorTpl[2]:
218 self.responsibleHostingVendorTextCtrl.SetValue(currentRespVendorTpl[2])
219 else:
220 self.responsibleHostingVendorTextCtrl.SetValue('')
221 if respTPM:
222 self.responsibleTPMTextCtrl.SetValue(respTPM)
223 else:
224 self.responsibleTPMTextCtrl.SetValue('')
225 if respOffice:
226 self.responsibleOfficeTextCtrl.SetValue(respOffice)
227 else:
228 self.responsibleOfficeTextCtrl.SetValue('')
229 if caseStatus:
230 self.caseStatusChoice.SetStringSelection(caseStatus)
231 else:
232 self.caseStatusChoice.SetStringSelection('')
233
234
235 def OnProcess(self, event):
236 caseName = self.casesListChoice.GetStringSelection()
237 if self.chargeableCheckBox.GetValue():
238 chargeableBool = True
239 else:
240 chargeableBool = False
241 currentRevPlatform = self.reviewPlatformChoice.GetStringSelection()
242 caseStatus = self.caseStatusChoice.GetStringSelection()
243 currentRespAttorney = self.responsibleAttnyTextCtrl.GetValue()
244 currentRespParalegal = self.responsibleParalegalTextCtrl.GetValue()
245 currentRespVendorTpl = (self.responsibleProcessingVendorTextCtrl.GetValue(),self.responsibleScanningVendorTextCtrl.GetValue(),
246 self.responsibleHostingVendorTextCtrl.GetValue())
247 respTPM = self.responsibleTPMTextCtrl.GetValue()
248 respOffice = self.responsibleOfficeTextCtrl.GetValue()
249 print "Updating Access DB..."
250 self.console.EditCaseData(caseName,chargeableBool,currentRespAttorney,currentRespParalegal,currentRespVendorTpl,currentRevPlatform,
251 respTPM,respOffice, caseStatus)
252 print "Complete!"
253 finishedDlg = wx.MessageDialog(self, "MCP: Your settings have been saved to the Matter Management database.", "MCP: Process Complete",wx.OK, wx.DefaultPosition)
254 finishedDlg.ShowModal()
255 finishedDlg.Destroy()
256 self.oKButton.Disable()
257
258 def CreateBoxesSection(self):
259 self.oKButton = wx.Button(self.panel, wx.ID_OK,'Save')
260 self.oKButton.SetDefault()
261 self.oKButton.SetSize(self.oKButton.GetBestSize())
262 self.cancelButton = wx.Button(self.panel, wx.ID_CANCEL,'Close')
263 self.cancelButton.SetSize(self.cancelButton.GetBestSize())
264 self.buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
265 self.buttonSizer.Add(self.oKButton,0,wx.ALL,10)
266 self.buttonSizer.Add(self.cancelButton,0,wx.ALL,10)
267
268 def CloseWindow(self, event):
269 self.Close(True)
270
271 def OnChangeCaseView(self,event):
272 self.casesListChoice.Clear()
273 eventID = event.GetId()
274 if eventID == 100:
275 #change it to my cases
276 self.casesListChoice.SetItems(self.myCases)
277 self.casesListChoice.SetSelection(0)
278 self.SetFields(self.myCases[0])
279 if eventID == 101:
280 #change it to office cases
281 self.casesListChoice.SetItems(self.officeCases)
282 self.casesListChoice.SetSelection(0)
283 self.SetFields(self.officeCases[0])
284 if eventID == 102:
285 #change it to all cases
286 self.casesListChoice.SetItems(self.allCases)
287 self.casesListChoice.SetSelection(0)
288 self.SetFields(self.allCases[0])
289
290
291 def OnViewCaseNotes(self,event):
292 caseName = self.casesListChoice.GetStringSelection()
293 office = self.responsibleOfficeTextCtrl.GetValue()
294 err = self.console.ViewCaseNotes(caseName,office)
295 if err:
296 errDlg = wx.MessageDialog(self, "MCP: The path to this case file could not be found.", "MCP: Does Not Compute",wx.OK, wx.DefaultPosition)
297 errDlg.ShowModal()
298 errDlg.Destroy()
299
300 def OnViewProdSpec(self,event):
301 caseName = self.casesListChoice.GetStringSelection()
302 office = self.responsibleOfficeTextCtrl.GetValue()
303 err = self.console.ViewProdSpec(caseName,office)
304 if err:
305 errDlg = wx.MessageDialog(self, "MCP: The path to this case file could not be found.", "MCP: Does Not Compute",wx.OK, wx.DefaultPosition)
306 errDlg.ShowModal()
307 errDlg.Destroy()
308
309 def OnOpenAlternateMediaFolder(self,event):
310 caseName = self.casesListChoice.GetStringSelection()
311 office = self.responsibleOfficeTextCtrl.GetValue()
312 err = self.console.OpenAlternateMediaFolder(caseName,office)
313 if err:
314 errDlg = wx.MessageDialog(self, "MCP: There is no current alternate media folder for this case.\nYou can set this in Settings.", "MCP: Does Not Compute",wx.OK, wx.DefaultPosition)
315 errDlg.ShowModal()
316 errDlg.Destroy()
317
318 def OnOpenCaseFolder(self,event):
319 caseName = self.casesListChoice.GetStringSelection()
320 office = self.responsibleOfficeTextCtrl.GetValue()
321 err = self.console.OpenCaseFolder(caseName,office)
322 if err:
323 errDlg = wx.MessageDialog(self, "MCP: The path to this case file could not be found.", "MCP: Does Not Compute",wx.OK, wx.DefaultPosition)
324 errDlg.ShowModal()
325 errDlg.Destroy()
326
327 def OnViewCaseUploads(self, event):
328 uploadList = self.console.GetUploadData(self.casesListChoice.GetStringSelection())
329 numberOfRows = len(uploadList)
330 uploadTotal = self.console.GetUploadTotal(uploadList)
331 caseName = self.casesListChoice.GetStringSelection()
332 CLM = caseName.split("_(")[1]
333 CLM = CLM[:-1]
334 CLM = CLM.replace('-','.')
335 #print CLM
336 if numberOfRows == 0:
337 dlg = wx.MessageDialog(self, "MCP: There are no case uploads for this case.", "MCP: Does Not Compute",wx.OK, wx.DefaultPosition)
338 else:
339 dlg = CaseUploadsDialog.CaseUploadsDialog(self,numberOfRows, uploadList, uploadTotal,CLM)
340 #dlg.Show(True)
341 dlg.ShowModal()
342 dlg.Destroy()
343
344 def OnViewDocProduction(self,event):
345 prodList = self.console.GetProductionData(self.casesListChoice.GetStringSelection())
346 numberOfRows = len(prodList)
347 prodTotals = self.console.GetProductionTotal(prodList)
348 caseName = self.casesListChoice.GetStringSelection()
349 CLM = caseName.split("_(")[1]
350 CLM = CLM[:-1]
351 CLM = CLM.replace('-','.')
352 #print CLM
353 if numberOfRows == 0:
354 dlg = wx.MessageDialog(self, "MCP: There are no current productions for this case.", "MCP: Does Not Compute",wx.OK, wx.DefaultPosition)
355 else:
356 dlg = CurrentProductionsDialog.CaseUploadsDialog(self,numberOfRows, prodList,CLM, prodTotals)
357 #dlg.Show(True)
358 dlg.ShowModal()
359 dlg.Destroy()
360
361 def OnAddDocProduction(self, event):
362 caseName = self.casesListChoice.GetStringSelection()
363 CLM = caseName.split("_(")[1]
364 CLM = CLM[:-1]
365 CLM = CLM.replace('-','.')
366 #print CLM
367 dlg = AddDocumentProductionDialog.AddDocumentProductionDialog(self,CLM)
368 if dlg.ShowModal() == wx.ID_OK:
369 prodDate, begBates, endBates, prodDocCount, prodPageCount, prodNotes = dlg.GetValues()
370 #print prodDate
371 dateConverter = NinoGenTools.DateUtilities()
372 prodID = 'prod_' + str(dateConverter.ConvertDateFormat(prodDate, convertToFormat='computer'))
373 errRpt = self.console.AddProductionEntry(CLM,prodID,prodDate,begBates,endBates,prodDocCount, prodPageCount, prodNotes)
374 if errRpt:
375 doneDlg = wx.MessageDialog(self, "MCP: All fields need to be filled out.\nPlease try again.", "MCP: Does Not Compute",wx.OK, wx.DefaultPosition)
376 else:
377 doneDlg = wx.MessageDialog(self, "MCP: Production detail added successfully.", "MCP: Success",wx.OK, wx.DefaultPosition)
378 doneDlg.ShowModal()
379 doneDlg.Destroy()
380
381 def OnCasePathsSettings(self, event):
382 office = self.responsibleOfficeTextCtrl.GetValue()
383 altMediaPath, casePath = self.console.GetCasePathsData(self.casesListChoice.GetStringSelection(),office)
384 if altMediaPath:
385 pass
386 else:
387 altMediaPath = ""
388 dlg = CasePathsDialog.CasePathsDialog(self, altMediaPath, casePath)
389 if dlg.ShowModal() == wx.ID_OK:
390 altmediaPath = dlg.GetValues()
391 #print self.workDir
392 dlg.Destroy()
393
394 def OnAbout(self, event):
395 """
396 OnAbout(self,event) Displays an about dialog with developer and bug reporting info
397 """
398 dlg = wx.MessageDialog(self, "MCP is a case organization program.\n"
399 "\n\n"
400 "For questions or comments about this program\n"
401 "or to report a bug, please email the program\n"
402 "creator at Nino.Borges@gmail.com\n\n"
403 "MCP is\n"
404 "Copyright (c) 2011 Emanuel Borges.\n"
405 "All rights reserved.\n"
406 "(Nino.Borges@gmail.com)\n",
407 "About MCP", wx.OK | wx.ICON_INFORMATION)
408 dlg.ShowModal()
409 dlg.Destroy()
410
411
412 class MyApp(wx.App):
413 def OnInit(self):
414 prgVersion = MCP_Lib.GetMCPVersion()
415 self.frame = MyFrame(None, -1, "View/Edit Case Information %s"%prgVersion)
416 self.frame.Show(True)
417 self.SetTopWindow(self.frame)
418 return True
419
420
421 if __name__ == '__main__':
422 app = MyApp(0)
423 app.MainLoop()