1
2
3
4
5
6
7
8
9
10 """The main gui code for BitPim"""
11
12
13 from __future__ import with_statement
14 import ConfigParser
15 import thread, threading
16 import Queue
17 import time
18 import os
19 import cStringIO
20 import zipfile
21 import re
22 import sys
23 import shutil
24 import types
25 import datetime
26 import sha
27 import codecs
28 import fileview
29 import widgets
30
31
32 import wx
33 import wx.lib.colourdb
34 import wx.gizmos
35 import wx.html
36 import wx.lib.mixins.listctrl as listmix
37
38
39 import guiwidgets
40 import common
41 import helpids
42 import comdiagnose
43 import guihelper
44 import hexeditor
45 import pubsub
46 import phones.com_brew as com_brew
47 import gui
48 import widgets
49
50
52 - def __init__(self, mainwindow, parent, id=-1):
53
54 self.mainwindow=mainwindow
55 wx.SplitterWindow.__init__(self, parent, id, style=wx.SP_LIVE_UPDATE)
56 self.tree=FileSystemDirectoryView(mainwindow, self, wx.NewId(), style=(wx.TR_DEFAULT_STYLE|wx.TR_NO_LINES)&~wx.TR_TWIST_BUTTONS)
57 self.list=FileSystemFileView(mainwindow, self, wx.NewId())
58 self.sash_pos=mainwindow.config.ReadInt("filesystemsplitterpos", 200)
59 self.update_sash=False
60 self.SplitVertically(self.tree, self.list, self.sash_pos)
61 self.SetMinimumPaneSize(20)
62 wx.EVT_SPLITTER_SASH_POS_CHANGED(self, id, self.OnSplitterPosChanged)
63 pubsub.subscribe(self.OnPhoneModelChanged, pubsub.PHONE_MODEL_CHANGED)
64
67
72
74 if self.update_sash:
75 self.sash_pos=self.GetSashPosition()
76 self.mainwindow.config.WriteInt("filesystemsplitterpos",
77 self.sash_pos)
78
80 self.update_sash=False
81 - def OnPostActivate(self):
82 self.SetSashPosition(self.sash_pos)
83 self.update_sash=True
84
89
97
102
106
111
115
118
123
125 - def __init__(self, mainwindow, parent, id, style=wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_SINGLE_SEL):
126 wx.ListCtrl.__init__(self, parent, id, style=style)
127 self.parent=parent
128 self.mainwindow=mainwindow
129 self.datacolumn=False
130 self.InsertColumn(0, "Name", width=300)
131 self.InsertColumn(1, "Size", format=wx.LIST_FORMAT_RIGHT)
132 self.InsertColumn(2, "Date", width=200)
133 self.font=wx.TheFontList.FindOrCreateFont(10, family=wx.SWISS, style=wx.NORMAL, weight=wx.NORMAL)
134
135 self.ResetView()
136
137 if self.datacolumn:
138 self.InsertColumn(3, "Extra Stuff", width=400)
139 listmix.ColumnSorterMixin.__init__(self, 4)
140 else:
141 listmix.ColumnSorterMixin.__init__(self, 3)
142
143
144 self.filemenu=wx.Menu()
145 self.filemenu.Append(guihelper.ID_FV_SAVE, "Save ...")
146 self.filemenu.Append(guihelper.ID_FV_HEXVIEW, "Hexdump")
147 self.filemenu.AppendSeparator()
148 self.filemenu.Append(guihelper.ID_FV_DELETE, "Delete")
149 self.filemenu.Append(guihelper.ID_FV_OVERWRITE, "Overwrite ...")
150
151 self.genericmenu=wx.Menu()
152 self.genericmenu.Append(guihelper.ID_FV_NEWFILE, "New File ...")
153 self.genericmenu.AppendSeparator()
154 self.genericmenu.Append(guihelper.ID_FV_OFFLINEPHONE, "Offline Phone")
155 self.genericmenu.Append(guihelper.ID_FV_REBOOTPHONE, "Reboot Phone")
156 self.genericmenu.Append(guihelper.ID_FV_MODEMMODE, "Go to modem mode")
157 wx.EVT_MENU(self.genericmenu, guihelper.ID_FV_NEWFILE, self.OnNewFile)
158 wx.EVT_MENU(self.genericmenu, guihelper.ID_FV_OFFLINEPHONE, parent.OnPhoneOffline)
159 wx.EVT_MENU(self.genericmenu, guihelper.ID_FV_REBOOTPHONE, parent.OnPhoneReboot)
160 wx.EVT_MENU(self.genericmenu, guihelper.ID_FV_MODEMMODE, parent.OnModemMode)
161 wx.EVT_MENU(self.filemenu, guihelper.ID_FV_SAVE, self.OnFileSave)
162 wx.EVT_MENU(self.filemenu, guihelper.ID_FV_HEXVIEW, self.OnHexView)
163 wx.EVT_MENU(self.filemenu, guihelper.ID_FV_DELETE, self.OnFileDelete)
164 wx.EVT_MENU(self.filemenu, guihelper.ID_FV_OVERWRITE, self.OnFileOverwrite)
165 wx.EVT_RIGHT_DOWN(self.GetMainWindow(), self.OnRightDown)
166 wx.EVT_RIGHT_UP(self.GetMainWindow(), self.OnRightUp)
167 wx.EVT_LIST_ITEM_ACTIVATED(self,id, self.OnItemActivated)
168 self.image_list=wx.ImageList(16, 16)
169 a={"sm_up":"GO_UP","sm_dn":"GO_DOWN","w_idx":"WARNING","e_idx":"ERROR","i_idx":"QUESTION"}
170 for k,v in a.items():
171 s="self.%s= self.image_list.Add(wx.ArtProvider_GetBitmap(wx.ART_%s,wx.ART_TOOLBAR,(16,16)))" % (k,v)
172 exec(s)
173 self.img_file=self.image_list.Add(wx.ArtProvider_GetBitmap(wx.ART_NORMAL_FILE,
174 wx.ART_OTHER,
175 (16, 16)))
176 self.SetImageList(self.image_list, wx.IMAGE_LIST_SMALL)
177
178
179
180
181
182 self.__dragging=False
183 self.add_files=[]
184 self.droptarget=fileview.MyFileDropTarget(self, True, False)
185 self.SetDropTarget(self.droptarget)
186
188 w,h=self.GetSize()
189 self.Refresh()
190 dc=wx.PaintDC(self)
191 dc.BeginDrawing()
192 dc.SetFont(self.font)
193 x,y= dc.GetTextExtent("There are no items to show in this view")
194
195 xx=(w-x)/2
196 if xx<0:
197 xx=0
198 dc.DrawText("There are no items to show in this view", xx, h/3)
199 dc.EndDrawing()
200
216
218
219 return wx._misc.DragCopy
220
222 mw=self.mainwindow
223 if not len(self.add_files):
224 return
225 for file in self.add_files:
226 if file is None:
227 continue
228 if len(self.path):
229 path=self.path+"/"+os.path.basename(file)
230 else:
231 path=os.path.basename(file)
232 contents=open(file, "rb").read()
233 mw.MakeCall( gui.Request(mw.wt.writefile, path, contents),
234 gui.Callback(self.OnAddFilesResults, self.path) )
235 self.add_files.remove(file)
236
237 break
238
247
248 if guihelper.IsMSWindows():
249
251 evt.Skip()
252 if not evt.LeftIsDown():
253 return
254 path=self.itemtopath(self.GetFirstSelected())
255 drag_source=wx.DropSource(self)
256 file_names=wx.FileDataObject()
257 file_names.AddFile(path)
258 drag_source.SetData(file_names)
259 self.__dragging=True
260 res=drag_source.DoDragDrop(wx.Drag_CopyOnly)
261 self.__dragging=False
262
264 pt = event.GetPosition()
265 item, flags = self.HitTest(pt)
266 if item is not -1:
267 self.Select(item)
268 self.PopupMenu(self.filemenu, pt)
269 else:
270 self.PopupMenu(self.genericmenu, pt)
271
273
274 pt = event.GetPosition();
275 item, flags = self.HitTest(pt)
276 try:
277 self.Select(item)
278 except:
279 pass
280
294
300
302 mw=self.mainwindow
303 if mw.HandleException(exception): return
304 bn=guihelper.basename(path)
305 ext=guihelper.getextension(bn)
306 if len(ext):
307 ext="%s files (*.%s)|*.%s" % (ext.upper(), ext, ext)
308 else:
309 ext="All files|*"
310 with guihelper.WXDialogWrapper(wx.FileDialog(self, "Save File As", defaultFile=bn, wildcard=ext,
311 style=wx.SAVE|wx.OVERWRITE_PROMPT|wx.CHANGE_DIR),
312 True) as (dlg, retcode):
313 if retcode==wx.ID_OK:
314 file(dlg.GetPath(), "wb").write(contents)
315
318
324
333
339
344
355
360
362 self.DeleteAllItems()
363 self.files={}
364 self.path=None
365 self.itemDataMap = self.files
366 self.itemIndexMap = self.files.keys()
367 self.SetItemCount(0)
368
376
378 mw=self.mainwindow
379 if mw.HandleException(exception): return
380 count=self.GetItemCount()
381 self.path=path
382 self.DeleteAllItems()
383 self.files={}
384 index=0
385 for file in result:
386 index=index+1
387 f=guihelper.basename(file)
388 if self.datacolumn:
389 self.files[index]=(f, `result[file]['size']`, result[file]['date'][1], result[file]['data'], file)
390 else:
391 self.files[index]=(f, `result[file]['size']`, result[file]['date'][1], file)
392 self.itemDataMap = self.files
393 self.itemIndexMap = self.files.keys()
394 self.SetItemCount(index)
395 self.SortListItems()
396 if count!=0 and index==0:
397 wx.EVT_PAINT(self, self.OnPaint)
398 elif count==0 and index!=0:
399 self.Unbind(wx.EVT_PAINT)
400
402 index=self.itemIndexMap[item]
403 if self.datacolumn:
404 return self.itemDataMap[index][4]
405 return self.itemDataMap[index][3]
406
408 col=self._col
409 sf=self._colSortFlag[col]
410
411
412 items=[]
413 for k,v in self.itemDataMap.items():
414 if col==1:
415 items.append([int(v[col]),k])
416 else:
417 items.append([v[col],k])
418
419 items.sort()
420 k=[key for value, key in items]
421
422
423 if sf==False:
424 k.reverse()
425
426 self.itemIndexMap=k
427
428
429 self.Refresh()
430
433
435 return (self.sm_dn, self.sm_up)
436
437 - def OnGetItemText(self, item, col):
438 index=self.itemIndexMap[item]
439 s = self.itemDataMap[index][col]
440 return s
441
444
447
449 - def __init__(self, mainwindow, parent, id, style):
450 wx.TreeCtrl.__init__(self, parent, id, style=style)
451 self.parent=parent
452 self.mainwindow=mainwindow
453 wx.EVT_TREE_ITEM_EXPANDED(self, id, self.OnItemExpanded)
454 wx.EVT_TREE_SEL_CHANGED(self,id, self.OnItemSelected)
455 self.dirmenu=wx.Menu()
456 self.dirmenu.Append(guihelper.ID_FV_NEWSUBDIR, "Make subdirectory ...")
457 self.dirmenu.Append(guihelper.ID_FV_NEWFILE, "New File ...")
458 self.dirmenu.AppendSeparator()
459 self.dirmenu.Append(guihelper.ID_FV_BACKUP, "Backup directory ...")
460 self.dirmenu.Append(guihelper.ID_FV_BACKUP_TREE, "Backup entire tree ...")
461 self.dirmenu.Append(guihelper.ID_FV_RESTORE, "Restore ...")
462 self.dirmenu.AppendSeparator()
463 self.dirmenu.Append(guihelper.ID_FV_REFRESH, "Refresh")
464 self.dirmenu.AppendSeparator()
465 self.dirmenu.Append(guihelper.ID_FV_DELETE, "Delete")
466 self.dirmenu.AppendSeparator()
467 self.dirmenu.Append(guihelper.ID_FV_TOTAL_REFRESH, "Refresh Filesystem")
468 self.dirmenu.Append(guihelper.ID_FV_OFFLINEPHONE, "Offline Phone")
469 self.dirmenu.Append(guihelper.ID_FV_REBOOTPHONE, "Reboot Phone")
470 self.dirmenu.Append(guihelper.ID_FV_MODEMMODE, "Go to modem mode")
471
472 self.genericmenu=wx.Menu()
473 self.genericmenu.Append(guihelper.ID_FV_TOTAL_REFRESH, "Refresh Filesystem")
474 self.genericmenu.Append(guihelper.ID_FV_OFFLINEPHONE, "Offline Phone")
475 self.genericmenu.Append(guihelper.ID_FV_REBOOTPHONE, "Reboot Phone")
476 self.genericmenu.Append(guihelper.ID_FV_MODEMMODE, "Go to modem mode")
477 wx.EVT_MENU(self.genericmenu, guihelper.ID_FV_TOTAL_REFRESH, self.OnRefresh)
478 wx.EVT_MENU(self.genericmenu, guihelper.ID_FV_OFFLINEPHONE, parent.OnPhoneOffline)
479 wx.EVT_MENU(self.genericmenu, guihelper.ID_FV_REBOOTPHONE, parent.OnPhoneReboot)
480 wx.EVT_MENU(self.genericmenu, guihelper.ID_FV_MODEMMODE, parent.OnModemMode)
481 wx.EVT_MENU(self.dirmenu, guihelper.ID_FV_NEWSUBDIR, self.OnNewSubdir)
482 wx.EVT_MENU(self.dirmenu, guihelper.ID_FV_NEWFILE, self.OnNewFile)
483 wx.EVT_MENU(self.dirmenu, guihelper.ID_FV_DELETE, self.OnDirDelete)
484 wx.EVT_MENU(self.dirmenu, guihelper.ID_FV_BACKUP, self.OnBackupDirectory)
485 wx.EVT_MENU(self.dirmenu, guihelper.ID_FV_BACKUP_TREE, self.OnBackupTree)
486 wx.EVT_MENU(self.dirmenu, guihelper.ID_FV_RESTORE, self.OnRestore)
487 wx.EVT_MENU(self.dirmenu, guihelper.ID_FV_REFRESH, self.OnDirRefresh)
488 wx.EVT_MENU(self.dirmenu, guihelper.ID_FV_TOTAL_REFRESH, self.OnRefresh)
489 wx.EVT_MENU(self.dirmenu, guihelper.ID_FV_OFFLINEPHONE, parent.OnPhoneOffline)
490 wx.EVT_MENU(self.dirmenu, guihelper.ID_FV_REBOOTPHONE, parent.OnPhoneReboot)
491 wx.EVT_MENU(self.dirmenu, guihelper.ID_FV_MODEMMODE, parent.OnModemMode)
492 wx.EVT_RIGHT_DOWN(self, self.OnRightDown)
493 wx.EVT_RIGHT_UP(self, self.OnRightUp)
494 self.image_list=wx.ImageList(16, 16)
495 self.img_dir=self.image_list.Add(wx.ArtProvider_GetBitmap(guihelper.ART_FOLDER,
496 wx.ART_OTHER,
497 (16, 16)))
498 self.img_dir_open=self.image_list.Add(wx.ArtProvider_GetBitmap(guihelper.ART_FOLDER_OPEN,
499 wx.ART_OTHER,
500 (16, 16)))
501 self.SetImageList(self.image_list)
502 self.add_files=[]
503 self.add_target=""
504 self.droptarget=fileview.MyFileDropTarget(self, True, True)
505 self.SetDropTarget(self.droptarget)
506 self.ResetView()
507
509 self.first_time=True
510 self.DeleteAllItems()
511 self.root=self.AddRoot("/")
512 self.item=self.root
513 self.SetPyData(self.root, None)
514 self.SetItemHasChildren(self.root, True)
515 self.SetItemImage(self.root, self.img_dir)
516 self.SetItemImage(self.root, self.img_dir_open, which=wx.TreeItemIcon_Expanded)
517 self.SetPyData(self.AppendItem(self.root, "Retrieving..."), None)
518 self.selections=[]
519 self.dragging=False
520 self.skip_dir_list=0
521
536
538 target=self
539 t=self.mainwindow.GetCurrentActiveWidget()
540 if isinstance(t, FileSystemDirectoryView):
541
542 target=t
543
544 item, flags = self.HitTest((x, y))
545 selections = self.GetSelections()
546 if item.IsOk():
547 if selections != [item]:
548 self.UnselectAll()
549 self.SelectItem(item)
550 return wx._misc.DragCopy
551 elif selections:
552 self.UnselectAll()
553 return wx._misc.DragNone
554
556 self.selections = self.GetSelections()
557 self.UnselectAll()
558
560 self.UnselectAll()
561 for i in self.selections:
562 self.SelectItem(i)
563 self.selections=[]
564
569
573
575 mw=self.mainwindow
576 if not len(self.add_files):
577 return
578 for file in self.add_files:
579 if file is None:
580 continue
581 if len(self.add_target):
582 path=self.add_target+"/"+os.path.basename(file)
583 else:
584 path=os.path.basename(file)
585 contents=open(file, "rb").read()
586 mw.MakeCall( gui.Request(mw.wt.writefile, path, contents),
587 gui.Callback(self.OnAddFilesResults, self.add_target) )
588 self.add_files.remove(file)
589
590 break
591
600
602 pt = event.GetPosition();
603 item, flags = self.HitTest(pt)
604 if item.IsOk():
605 self.SelectItem(item)
606 self.PopupMenu(self.dirmenu, pt)
607 else:
608 self.SelectItem(self.item)
609 self.PopupMenu(self.genericmenu, pt)
610
614
616 if not self.dragging and not self.first_time:
617 item=self.GetSelection()
618 if item.IsOk() and item != self.item:
619 path=self.itemtopath(item)
620 self.parent.ShowFiles(path)
621 if not self.skip_dir_list:
622 self.OnDirListing(path)
623 self.item=item
624
626 if not self.skip_dir_list:
627 item=event.GetItem()
628 if self.first_time:
629 self.GetFullFS()
630 else:
631 path=self.itemtopath(item)
632 self.OnDirListing(path)
633
635 new_item=self.AppendItem(location, name)
636 self.SetPyData(new_item, None)
637 self.SetItemImage(new_item, self.img_dir)
638 self.SetItemImage(new_item, self.img_dir_open, which=wx.TreeItemIcon_Expanded)
639
640 if self.GetChildrenCount(location, False) == 1 and not self.IsExpanded(location):
641 self.skip_dir_list+=1
642 self.Expand(location)
643 self.Collapse(location)
644 self.skip_dir_list-=1
645 return new_item
646
648
649 if self.GetChildrenCount(parent, False) == 1:
650 self.Collapse(parent)
651 self.Delete(item)
652
659
661 mw=self.mainwindow
662 mw.OnBusyEnd()
663 if mw.HandleException(exception):
664 self.Collapse(self.root)
665 return
666 self.first_time=False
667 self.skip_dir_list+=1
668 self.SelectItem(self.root)
669 self.DeleteChildren(self.root)
670 keys=result.keys()
671 keys.sort()
672
673 for k in keys:
674 path, dir=os.path.split(k)
675 item=self.pathtoitem(path)
676 self.AddDirectory(item, dir)
677 self.skip_dir_list-=1
678 self.parent.ShowFiles("")
679
684
686 mw=self.mainwindow
687 if mw.HandleException(exception): return
688 item=self.pathtoitem(path)
689 l=[]
690 child,cookie=self.GetFirstChild(item)
691 for dummy in range(0,self.GetChildrenCount(item,False)):
692 l.append(child)
693 child,cookie=self.GetNextChild(item,cookie)
694
695 sort=False
696 for file in result:
697 children=True
698 f=guihelper.basename(file)
699 found=None
700 for i in l:
701 if self.GetItemText(i)==f:
702 found=i
703 break
704 if found is None:
705
706
707 found=self.AddDirectory(item, f)
708 self.OnDirListing(file)
709 sort=True
710 for i in l:
711 if not result.has_key(self.itemtopath(i)):
712 self.RemoveDirectory(item, i)
713 if sort:
714 self.SortChildren(item)
715
729
731 mw=self.mainwindow
732 if mw.HandleException(exception): return
733 path, dir=os.path.split(new_path)
734 item=self.pathtoitem(path)
735 self.AddDirectory(item, dir)
736 self.SortChildren(item)
737 self.Expand(item)
738
739 self.OnDirListing(path)
740
755
760
766
777
780
783
789
791 mw=self.mainwindow
792 if mw.HandleException(exception): return
793 bn=guihelper.basename(path)
794 if len(bn)<1:
795 bn="root"
796 bn+=".zip"
797 ext="Zip files|*.zip|All Files|*"
798 with guihelper.WXDialogWrapper(wx.FileDialog(self, "Save File As", defaultFile=bn, wildcard=ext,
799 style=wx.SAVE|wx.OVERWRITE_PROMPT|wx.CHANGE_DIR),
800 True) as (dlg, retcode):
801 if retcode==wx.ID_OK:
802 file(dlg.GetPath(), "wb").write(backup)
803
805 ext="Zip files|*.zip|All Files|*"
806 path=self.itemtopath(self.GetSelection())
807 bn=guihelper.basename(path)
808 if len(bn)<1:
809 bn="root"
810 bn+=".zip"
811 ext="Zip files|*.zip|All Files|*"
812 with guihelper.WXDialogWrapper(wx.FileDialog(self, "Open backup file", defaultFile=bn, wildcard=ext,
813 style=wx.OPEN|wx.HIDE_READONLY|wx.CHANGE_DIR),
814 True) as (dlg, retcode):
815 if retcode==wx.ID_OK:
816 name=dlg.GetPath()
817 if not zipfile.is_zipfile(name):
818 with guihelper.WXDialogWrapper(guiwidgets.AlertDialogWithHelp(self.mainwindow, name+" is not a valid zipfile.", "Zip file required",
819 lambda _: wx.GetApp().displayhelpid(helpids.ID_NOT_A_ZIPFILE),
820 style=wx.OK|wx.ICON_ERROR),
821 True):
822 return
823 zipf=zipfile.ZipFile(name, "r")
824 xx=zipf.testzip()
825 if xx is not None:
826 with guihelper.WXDialogWrapper(guiwidgets.AlertDialogWithHelp(self.mainwindow, name+" has corrupted contents. Use a repair utility to fix it",
827 "Zip file corrupted",
828 lambda _: wx.GetApp().displayhelpid(helpids.ID_ZIPFILE_CORRUPTED),
829 style=wx.OK|wx.ICON_ERROR),
830 True):
831 return
832
833 RestoreDialog(self.mainwindow, "Restore files", zipf, path, self.OnRestoreOK).Show(True)
834
847
849 mw=self.mainwindow
850 if mw.HandleException(exception): return
851 ok=filter(lambda s: s[0], results)
852 fail=filter(lambda s: not s[0], results)
853
854
855 if len(parentdir):
856 dirs=[]
857 for _, name in results:
858 while(len(name)>len(parentdir)):
859 name=guihelper.dirname(name)
860 if name not in dirs:
861 dirs.append(name)
862 dirs.sort()
863 for d in dirs:
864 self.OnDirListing(d)
865
866 self.OnDirListing(parentdir)
867
868 if len(ok) and len(fail)==0:
869 dlg=wx.MessageDialog(mw, "All files restored ok", "All files restored",
870 wx.OK|wx.ICON_INFORMATION)
871 dlg.Show(True)
872 return
873 if len(fail) and len(ok)==0:
874 wx.MessageBox("All files failed to restore", "No files restored",
875 wx.OK|wx.ICON_ERROR)
876 return
877
878 op="Failed to restore some files. Check the log for reasons.:\n\n"
879 for s,n in fail:
880 op+=" "+n+"\n"
881 wx.MessageBox(op, "Some restores failed", wx.OK|wx.ICON_ERROR)
882
887
890
892 if item==self.root: return ""
893 res=self.GetItemText(item)
894 while True:
895 parent=self.GetItemParent(item)
896 if parent==self.root:
897 return res
898 item=parent
899 res=self.GetItemText(item)+"/"+res
900
901 assert False
902 return ""
903
905 if path=="": return self.root
906 dirs=path.split('/')
907 node=self.root
908 for n in range(0, len(dirs)):
909 foundnode=None
910 child,cookie=self.GetFirstChild(node)
911 for dummy in range(0, self.GetChildrenCount(node, False)):
912 d=self.GetItemText(child)
913 if d==dirs[n]:
914 node=child
915 foundnode=node
916 break
917 child,cookie=self.GetNextChild(node,cookie)
918 if foundnode is not None:
919 continue
920
921 node=self.AppendItem(node, dirs[n])
922 self.SetPyData(node, None)
923 return node
924
926 """A dialog that lists all the files that will be restored"""
927
928 - def __init__(self, parent, title, zipf, path, okcb):
929 """Constructor
930
931 @param path: Placed before names in the archive. Should not include a
932 trailing slash.
933 """
934 wx.Dialog.__init__(self, parent, -1, title, style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
935 vbs=wx.BoxSizer(wx.VERTICAL)
936 vbs.Add( wx.StaticText(self, -1, "Choose files to restore"), 0, wx.ALIGN_CENTRE|wx.ALL, 5)
937
938 nl=zipf.namelist()
939 nl.sort()
940
941 prefix=path
942 if len(prefix)=="/" or prefix=="":
943 prefix=""
944 else:
945 prefix+="/"
946
947 nnl=map(lambda i: prefix+i, nl)
948
949 self.clb=wx.CheckListBox(self, -1, choices=nnl, style=wx.LB_SINGLE|wx.LB_HSCROLL|wx.LB_NEEDED_SB, size=wx.Size(200,300))
950
951 for i in range(len(nnl)):
952 self.clb.Check(i, True)
953
954 vbs.Add( self.clb, 1, wx.EXPAND|wx.ALL, 5)
955
956 vbs.Add(wx.StaticLine(self, -1, style=wx.LI_HORIZONTAL), 0, wx.EXPAND|wx.ALL, 5)
957
958 vbs.Add(self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.HELP), 0, wx.ALIGN_CENTER|wx.ALL, 5)
959
960 self.SetSizer(vbs)
961 self.SetAutoLayout(True)
962 vbs.Fit(self)
963
964 wx.EVT_BUTTON(self, wx.ID_HELP, lambda _: wx.GetApp().displayhelpid(helpids.ID_RESTOREDIALOG))
965 wx.EVT_BUTTON(self, wx.ID_OK, self.OnOK)
966 self.okcb=okcb
967 self.zipf=zipf
968 self.nl=zip(nl, nnl)
969 self.path=path
970
972 names=[]
973 for i in range(len(self.nl)):
974 if self.clb.IsChecked(i):
975 names.append(self.nl[i])
976 self.okcb(self.zipf, names, self.path)
977 self.Show(False)
978 self.Destroy()
979