1
2
3
4
5
6
7
8
9
10
11
12 """Most of the graphical user interface elements making up BitPim"""
13
14
15 from __future__ import with_statement
16 import contextlib
17 import os
18 import sys
19 import time
20 import copy
21 import StringIO
22 import getpass
23 import sha,md5
24 import gzip
25 import base64
26 import thread
27 import Queue
28 import shutil
29 import platform
30
31
32 import wx
33 import wx.html
34 import wx.lib.intctrl
35 import wx.lib.newevent
36 import wx.lib.mixins.listctrl as listmix
37 import wx.lib.stattext as stattext
38 from wx.lib.masked import NumCtrl
39
40
41 import apsw
42 import common
43 import version
44 import helpids
45 import comscan
46 import usbscan
47 import comdiagnose
48 import analyser
49 import guihelper
50 import pubsub
51 import bphtml
52 import bitflingscan
53 import aggregatedisplay
54 import phone_media_codec
55 import pubsub
56 import widgets
57 import phones
58 import setphone_wizard
59 import data_recording
60 import xyaptu
61 import serial
62
63
64
65
66
67 BitFlingCertificateVerificationEvent, EVT_BITFLINGCERTIFICATEVERIFICATION = wx.lib.newevent.NewEvent()
68
69
70
71
72
73
74
75 -class LogWindow(wx.Panel, widgets.BitPimWidget):
76
77 theanalyser=None
78
80 wx.Panel.__init__(self,parent, -1)
81
82 self.tb=wx.TextCtrl(self, 1, style=wx.TE_MULTILINE| wx.TE_RICH2|wx.TE_DONTWRAP|wx.TE_READONLY)
83 f=wx.Font(10, wx.MODERN, wx.NORMAL, wx.NORMAL )
84 ta=wx.TextAttr(font=f)
85 self.tb.SetDefaultStyle(ta)
86 self.sizer=wx.BoxSizer(wx.VERTICAL)
87 self.sizer.Add(self.tb, 1, wx.EXPAND)
88 self.SetSizer(self.sizer)
89 self.SetAutoLayout(True)
90 self.sizer.Fit(self)
91 wx.EVT_IDLE(self, self.OnIdle)
92 wx.EVT_SHOW(self, self.OnShow)
93 self.outstandingtext=StringIO.StringIO()
94
95 wx.EVT_KEY_UP(self.tb, self.OnKeyUp)
96
99
102
106
108 self.tb.SetInsertionPoint(0)
109 self.tb.SetInsertionPointEnd()
110 self.tb.Refresh()
111
113 if self.outstandingtext.tell():
114
115 newt=self.outstandingtext.getvalue()
116 self.outstandingtext.seek(0)
117 self.outstandingtext.truncate()
118 self.tb.AppendText(newt)
119
120 - def log(self, str, nl=True):
121 now=time.time()
122 t=time.localtime(now)
123 self.outstandingtext.write("%d:%02d:%02d.%03d " % ( t[3], t[4], t[5], int((now-int(now))*1000)))
124 self.outstandingtext.write(str)
125 if nl:
126 self.outstandingtext.write("\n")
127
128 - def logdata(self, str, data, klass=None):
129 o=self.outstandingtext
130 self.log(str, nl=False)
131 if data is not None:
132 o.write(" Data - "+`len(data)`+" bytes\n")
133 if klass is not None:
134 try:
135 o.write("<#! %s.%s !#>\n" % (klass.__module__, klass.__name__))
136 except:
137 klass=klass.__class__
138 o.write("<#! %s.%s !#>\n" % (klass.__module__, klass.__name__))
139 o.write(common.datatohexstring(data))
140 o.write("\n")
141
161
163 """return the log text"""
164 return self.tb.GetValue()
165
166
167
168
169
170
172
173 sources= ( ('PhoneBook', 'phonebook'),
174 ('Calendar', 'calendar'),
175 ('Wallpaper', 'wallpaper'),
176 ('Ringtone', 'ringtone'),
177 ('Memo', 'memo'),
178 ('Todo', 'todo'),
179 ('SMS', 'sms'),
180 ('Call History', 'call_history'),
181 ('Play List', 'playlist'),
182 ('T9 User DB','t9_udb'))
183
184
185 actions = ( ("Get", "read"), )
186
187 NOTREQUESTED=0
188 MERGE=1
189 OVERWRITE=2
190
191
192 types= ( ("Add", MERGE),
193 ("Replace All", OVERWRITE))
194 typename={ MERGE: 'MERGE',
195 OVERWRITE: 'OVERWRITE',
196 NOTREQUESTED: 'NOTREQUESTED',
197 }
198
199 HELPID=helpids.ID_GET_PHONE_DATA
200
201 - def __init__(self, frame, title, id=-1):
202 wx.Dialog.__init__(self, frame, id, title,
203 style=wx.CAPTION|wx.SYSTEM_MENU|wx.DEFAULT_DIALOG_STYLE)
204 gs=wx.FlexGridSizer(2+len(self.sources), 1+len(self.types),5 ,10)
205 gs.AddGrowableCol(1)
206 gs.AddMany( [
207 (wx.StaticText(self, -1, "Source"), 0, wx.EXPAND),])
208
209 for pretty,_ in self.types:
210 gs.Add(wx.StaticText(self, -1, pretty), 0, wx.ALIGN_CENTRE)
211
212 self._widgets={}
213 for desc, source in self.sources:
214 _cb=wx.CheckBox(self, wx.NewId(), desc)
215 _cb.exclusive=False
216 wx.EVT_CHECKBOX(self, _cb.GetId(), self.DoOkStatus)
217 gs.Add(_cb, 0, wx.EXPAND)
218 self._widgets[source]={ 'cb': _cb,
219 'rb': {},
220 }
221 first=True
222 for tdesc,tval in self.types:
223 if first:
224 style=wx.RB_GROUP
225 first=0
226 else:
227 style=0
228 _rb=wx.RadioButton(self, -1, "", style=style)
229 if self._dowesupport(source, self.actions[0][1], tval):
230 wx.EVT_RADIOBUTTON(self, _rb.GetId(), self.OnOptionSelected)
231 else:
232 _rb.SetValue(False)
233 _rb.Enable(False)
234 gs.Add(_rb, 0, wx.ALIGN_CENTRE)
235 self._widgets[source]['rb'][tval]=_rb
236
237 bs=wx.BoxSizer(wx.VERTICAL)
238 bs.Add(gs, 0, wx.EXPAND|wx.ALL, 10)
239 bs.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 7)
240
241 but=self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.HELP)
242 self._btn_ok=self.FindWindowById(wx.ID_OK)
243 bs.Add(but, 0, wx.EXPAND|wx.ALL, 10)
244
245 self.SetSizer(bs)
246 self.SetAutoLayout(True)
247 bs.Fit(self)
248
249 wx.EVT_BUTTON(self, wx.ID_HELP, self.OnHelp)
250
252 _w=self._widgets[sourcetype]
253 if not _w['cb'].GetValue():
254
255 return self.NOTREQUESTED
256 for _typeval,_rb in _w['rb'].items():
257 if _rb.GetValue():
258 return _typeval
259
260 raise ValueError
261
264
267
270
273
276
279
283 return self._setting("call_history")
288
291
292
293 _notsupported=(
294
295 ('calendar', 'read', MERGE),
296 ('wallpaper', 'read', MERGE),
297 ('ringtone', 'read', MERGE),
298 ('memo', 'read', MERGE),
299 ('todo', 'read', MERGE),
300 ('playlist', 'read', MERGE),
301 ('t9_udb', 'read', MERGE))
302
307
336
341
343 if w.exclusive:
344
345 for _w in self._widgets.values():
346 if _w['cb'] is not w:
347 _w['cb'].SetValue(False)
348 else:
349
350 for _w in self._widgets.values():
351 if _w['cb'] is not w and \
352 _w['cb'].exclusive:
353 _w['cb'].SetValue(False)
354
356
357
358 _rb=evt.GetEventObject()
359 for _w1 in self._widgets.values():
360 if _rb in _w1['rb'].values():
361 _w1['cb'].SetValue(True)
362
363 self.DoOkStatus()
364 return
365
367
368 if evt and evt.IsChecked():
369 enable=True
370 self._check_for_exclusive(evt.GetEventObject())
371 else:
372 enable=False
373 for _w in self._widgets.values():
374 if _w['cb'].GetValue():
375 enable=True
376 break
377 self._btn_ok.Enable(enable)
378 if evt is not None:
379 evt.Skip()
380
393
394
395
396
397
398
400 phonemodels=phones.phonemodels
401 update_choices=('Never', 'Daily', 'Weekly', 'Monthly')
402 setme="<setme>"
403 ID_DIRBROWSE=wx.NewId()
404 ID_COMBROWSE=wx.NewId()
405 ID_RETRY=wx.NewId()
406 ID_BITFLING=wx.NewId()
407 - def __init__(self, mainwindow, frame, title="BitPim Settings", id=-1):
408 wx.Dialog.__init__(self, frame, id, title,
409 style=wx.CAPTION|wx.SYSTEM_MENU|wx.DEFAULT_DIALOG_STYLE)
410 self.mw=mainwindow
411
412 self.bitflingresponsequeues={}
413
414 gs=wx.GridBagSizer(10, 10)
415 gs.AddGrowableCol(1)
416 _row=0
417
418 gs.Add( wx.StaticText(self, -1, "Read Only"), pos=(_row,0), flag=wx.ALIGN_CENTER_VERTICAL)
419 self.safemode=wx.CheckBox(self, wx.NewId(), "Block writing anything to the phone")
420 gs.Add( self.safemode, pos=(_row,1), flag=wx.ALIGN_CENTER_VERTICAL)
421 _row+=1
422
423
424 gs.Add( wx.StaticText(self, -1, "Disk storage"), pos=(_row,0), flag=wx.ALIGN_CENTER_VERTICAL)
425 gs.Add(wx.StaticText(self, -1, self.mw.config.Read('path', '<Unknown>')),
426 pos=(_row,1), flag=wx.ALIGN_CENTER_VERTICAL)
427 _row+=1
428 gs.Add(wx.StaticText(self, -1, 'Config File'), pos=(_row,0),
429 flag=wx.ALIGN_CENTER_VERTICAL)
430 gs.Add(wx.StaticText(self, -1, self.mw.config.Read('config')),
431 pos=(_row,1), flag=wx.ALIGN_CENTER_VERTICAL)
432 _row+=1
433
434
435 gs.Add( wx.StaticText(self, -1, "Phone Type"), pos=(_row,0), flag=wx.ALIGN_CENTER_VERTICAL)
436 keys=self.phonemodels
437 keys.sort()
438 self.phonebox=wx.ComboBox(self, -1, "LG-VX4400", style=wx.CB_DROPDOWN|wx.CB_READONLY,choices=keys)
439 self.phonebox.SetValue("LG-VX4400")
440 gs.Add( self.phonebox, pos=(_row,1), flag=wx.ALIGN_CENTER_VERTICAL)
441 _phone_btn=wx.Button(self, -1, 'Phone Wizard...')
442 wx.EVT_BUTTON(self, _phone_btn.GetId(), self.OnPhoneWizard)
443 gs.Add(_phone_btn, pos=(_row, 2), flag=wx.ALIGN_CENTER_VERTICAL)
444 _row+=1
445
446
447 gs.Add( wx.StaticText(self, -1, "Com Port"), pos=(_row,0), flag=wx.ALIGN_CENTER_VERTICAL)
448 self.commbox=wx.TextCtrl(self, -1, self.setme, size=(200,-1))
449 gs.Add( self.commbox, pos=(_row,1), flag=wx.ALIGN_CENTER_VERTICAL)
450 gs.Add( wx.Button(self, self.ID_COMBROWSE, "Browse ..."), pos=(_row,2), flag=wx.ALIGN_CENTER_VERTICAL)
451 _row+=1
452
453 gs.Add(wx.StaticText(self, -1, 'Com Timeout (sec)'), pos=(_row, 0),
454 flag=wx.ALIGN_CENTER_VERTICAL)
455 self.commtimeout=NumCtrl(self, -1,
456 integerWidth=2, fractionWidth=1,
457 allowNegative=False)
458 gs.Add(self.commtimeout, pos=(_row, 1), flag=wx.ALIGN_CENTER_VERTICAL)
459 _row+=1
460
461
462 gs.Add(wx.StaticText(self, -1, 'Check for Update'), pos=(_row,0), flag=wx.ALIGN_CENTER_VERTICAL)
463 self.updatebox=wx.ComboBox(self, -1, self.update_choices[0],
464 style=wx.CB_DROPDOWN|wx.CB_READONLY,
465 choices=self.update_choices)
466 gs.Add(self.updatebox, pos=(_row,1), flag=wx.ALIGN_CENTER_VERTICAL)
467 _row+=1
468
469
470 gs.Add(wx.StaticText(self, -1, 'Startup'), pos=(_row,0),
471 flag=wx.ALIGN_CENTER_VERTICAL)
472 self.startup=wx.CheckBox(self, wx.NewId(), 'Always start with the Today tab')
473 gs.Add(self.startup, pos=(_row,1), flag=wx.ALIGN_CENTER_VERTICAL)
474 _row+=1
475
476
477 if guihelper.IsMSWindows():
478 gs.Add(wx.StaticText(self, -1, 'Task Bar Icon'), pos=(_row,0),
479 flag=wx.ALIGN_CENTER_VERTICAL)
480 self.taskbaricon=wx.CheckBox(self, wx.NewId(),
481 'Place BitPim Icon in the System Tray when Minimized')
482 gs.Add(self.taskbaricon, pos=(_row, 1), flag=wx.ALIGN_CENTER_VERTICAL)
483 wx.EVT_CHECKBOX(self, self.taskbaricon.GetId(),
484 self.OnTaskbarChkbox)
485 _row+=1
486 self.taskbaricon1=wx.CheckBox(self, wx.NewId(),
487 'Place BitPim Icon in the System Tray when Closed')
488 self.taskbaricon1.Enable(False)
489 gs.Add(self.taskbaricon1, pos=(_row, 1), flag=wx.ALIGN_CENTER_VERTICAL)
490 _row+=1
491 else:
492 self.taskbaricon=None
493
494
495 gs.Add(wx.StaticText(self, -1, 'Autodetect at Startup'), pos=(_row,0),
496 flag=wx.ALIGN_CENTER_VERTICAL)
497 self.autodetect_start=wx.CheckBox(self, wx.NewId(),
498 'Detect phone at bitpim startup')
499 gs.Add(self.autodetect_start, pos=(_row, 1), flag=wx.ALIGN_CENTER_VERTICAL)
500 _row+=1
501
502 gs.Add(wx.StaticText(self, -1, 'SplashScreen Time (sec)'),
503 pos=(_row, 0),
504 flag=wx.ALIGN_CENTER_VERTICAL)
505 self.splashscreen=NumCtrl(self, -1,
506 integerWidth=2, fractionWidth=1,
507 allowNegative=False)
508 gs.Add(self.splashscreen, pos=(_row, 1), flag=wx.ALIGN_CENTER_VERTICAL)
509 _row+=1
510
511 if __debug__:
512 gs.Add(wx.StaticText(self, -1, 'Developer Console'),
513 pos=(_row,0),
514 flag=wx.ALIGN_CENTER_VERTICAL)
515 self.dev_console=wx.CheckBox(self, wx.NewId(),
516 'Display Developer Console')
517 gs.Add(self.dev_console, pos=(_row, 1),
518 flag=wx.ALIGN_CENTER_VERTICAL)
519 _row+=1
520
521 if bitflingscan.IsBitFlingEnabled():
522 self.SetupBitFlingCertVerification()
523 gs.Add( wx.StaticText( self, -1, "BitFling"), pos=(_row,0), flag=wx.ALIGN_CENTER_VERTICAL)
524 self.bitflingenabled=wx.CheckBox(self, self.ID_BITFLING, "Enabled")
525 gs.Add(self.bitflingenabled, pos=(_row,1), flag=wx.ALIGN_CENTER_VERTICAL)
526 gs.Add( wx.Button(self, self.ID_BITFLING, "Settings ..."), pos=(_row,2), flag=wx.ALIGN_CENTER_VERTICAL)
527 wx.EVT_BUTTON(self, self.ID_BITFLING, self.OnBitFlingSettings)
528 wx.EVT_CHECKBOX(self, self.ID_BITFLING, self.ApplyBitFlingSettings)
529 if self.mw.config.Read("bitfling/password","<unconfigured>") \
530 == "<unconfigured>":
531 self.mw.config.WriteInt("bitfling/enabled", 0)
532 self.bitflingenabled.SetValue(False)
533 self.bitflingenabled.Enable(False)
534 else:
535 self.bitflingenabled=None
536
537 bs=wx.BoxSizer(wx.VERTICAL)
538 bs.Add(gs, 0, wx.EXPAND|wx.ALL, 10)
539 bs.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 7)
540
541 but=self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.HELP)
542 bs.Add(but, 0, wx.CENTER|wx.ALL, 10)
543
544 wx.EVT_BUTTON(self, wx.ID_HELP, self.OnHelp)
545 wx.EVT_BUTTON(self, self.ID_COMBROWSE, self.OnComBrowse)
546 wx.EVT_BUTTON(self, wx.ID_OK, self.OnOK)
547
548 self.setdefaults()
549
550 self.SetSizer(bs)
551 self.SetAutoLayout(True)
552 bs.Fit(self)
553
554
555 set_size("ConfigDialog", self, screenpct=-1, aspect=3.5)
556
557 wx.EVT_CLOSE(self, self.OnClose)
558
561
566
569
583
585 if self.bitflingenabled is not None:
586 if self.bitflingenabled.GetValue():
587 bitflingscan.flinger.configure(self.mw.config.Read("bitfling/username", "<unconfigured>"),
588 bitflingscan.decode(self.mw.config.Read("bitfling/password",
589 "<unconfigured>")),
590 self.mw.config.Read("bitfling/host", "<unconfigured>"),
591 self.mw.config.ReadInt("bitfling/port", 12652))
592 else:
593 bitflingscan.flinger.unconfigure()
594
604
610
612 """Handle a certificate verification from any thread
613
614 The request is handed to the main gui thread, and then we wait for the
615 results"""
616 print thread.get_ident(),"dispatchVerifyBitFlingCert called"
617 q=self.bitflingresponsequeues.get(thread.get_ident(), None)
618 if q is None:
619 q=Queue.Queue()
620 self.bitflingresponsequeues[thread.get_ident()]=q
621 print thread.get_ident(), "Posting BitFlingCertificateVerificationEvent"
622 wx.PostEvent(self, BitFlingCertificateVerificationEvent(addr=addr, key=key, q=q))
623 print thread.get_ident(), "After posting BitFlingCertificateVerificationEvent, waiting for response"
624 res, exc = q.get()
625 print thread.get_ident(), "Got response", res, exc
626 if exc is not None:
627 ex=exc[1]
628 ex.gui_exc_info=exc[2]
629 raise ex
630 return res
631
633 """Receive the event in the main gui thread for cert verification
634
635 We unpack the parameters, call the verification method"""
636 print "_wrapVerifyBitFlingCert"
637
638 addr, hostkey, q = evt.addr, evt.key, evt.q
639 self.VerifyBitFlingCert(addr, hostkey, q)
640
642 print "VerifyBitFlingCert for", addr, "type",key.get_name()
643
644
645 fingerprint=common.hexify(key.get_fingerprint())
646
647 existing=wx.GetApp().config.Read("bitfling/certificates/%s" % (addr[0],), "")
648 if len(existing):
649 fp=existing
650 if fp==fingerprint:
651 q.put( (True, None) )
652 return
653
654 print "asking user"
655 dlg=AcceptCertificateDialog(None, wx.GetApp().config, addr, fingerprint, q)
656 dlg.ShowModal()
657
662
664 if evt.IsChecked():
665 self.taskbaricon1.Enable(True)
666 else:
667 self.taskbaricon1.SetValue(False)
668 self.taskbaricon1.Enable(False)
669
671 if len(self.mw.config.Read("lgvx4400port")):
672 self.commbox.SetValue(self.mw.config.Read("lgvx4400port", ""))
673 self.commtimeout.SetValue(self.mw.config.ReadFloat('commtimeout', 3.0))
674 if self.mw.config.Read("phonetype", "") in self.phonemodels:
675 self.phonebox.SetValue(self.mw.config.Read("phonetype"))
676 if self.bitflingenabled is not None:
677 self.bitflingenabled.SetValue(self.mw.config.ReadInt("bitfling/enabled", 0))
678 self.ApplyBitFlingSettings()
679 self.safemode.SetValue(self.mw.config.ReadInt("Safemode", 0))
680 self.updatebox.SetValue(self.mw.config.Read("updaterate",
681 self.update_choices[0]))
682 self.startup.SetValue(self.mw.config.ReadInt("startwithtoday", 0))
683 if self.taskbaricon:
684 if self.mw.config.ReadInt('taskbaricon', 0):
685 self.taskbaricon.SetValue(True)
686 self.taskbaricon1.Enable(True)
687 self.taskbaricon1.SetValue(self.mw.config.ReadInt('taskbaricon1', 0))
688 else:
689 self.taskbaricon.SetValue(False)
690 self.taskbaricon1.SetValue(False)
691 self.taskbaricon1.Enable(False)
692 self.autodetect_start.SetValue(self.mw.config.ReadInt("autodetectstart", 0))
693 self.splashscreen.SetValue(self.mw.config.ReadInt('splashscreentime', 2500)/1000.0)
694 if __debug__:
695 self.dev_console.SetValue(self.mw.config.ReadInt('console', 0))
696
701
703 path=self.mw.config.Read('path')
704 self.mw.configpath=path
705 self.mw.commportsetting=str(self.commbox.GetValue())
706 self.mw.config.Write("lgvx4400port", self.mw.commportsetting)
707 self.mw.config.WriteFloat('commtimeout',
708 float(self.commtimeout.GetValue()))
709 if self.mw.wt is not None:
710 self.mw.wt.clearcomm()
711
712 commparm={}
713 commparm['retryontimeout']=self.mw.config.ReadInt("commretryontimeout", False)
714 commparm['timeout']=self.mw.config.ReadFloat('commtimeout', 3.0)
715 commparm['hardwareflow']=self.mw.config.ReadInt('commhardwareflow', False)
716 commparm['softwareflow']=self.mw.config.ReadInt('commsoftwareflow', False)
717 commparm['baud']=self.mw.config.ReadInt('commbaud', 115200)
718 self.mw.commparams=commparm
719
720 self.mw.config.Write("phonetype", self.phonebox.GetValue())
721
722
723
724
725 mod=phones.module(self.phonebox.GetValue())
726 exec("import "+mod)
727 self.mw.phonemodule=eval(mod)
728 self.mw.phoneprofile=self.mw.phonemodule.Profile()
729 pubsub.publish(pubsub.PHONE_MODEL_CHANGED, self.mw.phonemodule)
730
731 if self.bitflingenabled is not None:
732 self.mw.bitflingenabled=self.bitflingenabled.GetValue()
733 self.mw.config.WriteInt("bitfling/enabled", self.mw.bitflingenabled)
734
735 self.mw.config.WriteInt("SafeMode", self.safemode.GetValue())
736 if self.safemode.GetValue():
737 wx.GetApp().SAFEMODE=True
738 wx.GetApp().ApplySafeMode()
739
740 self.mw.config.Write('updaterate', self.updatebox.GetValue())
741
742 self.mw.config.WriteInt('startwithtoday', self.startup.GetValue())
743
744 if self.taskbaricon:
745 self.mw.config.WriteInt('taskbaricon', self.taskbaricon.GetValue())
746 self.mw.config.WriteInt('taskbaricon1', self.taskbaricon1.GetValue())
747 else:
748 self.mw.config.WriteInt('taskbaricon', 0)
749 self.mw.config.WriteInt('taskbaricon1', 0)
750
751 self.mw.config.WriteInt('autodetectstart', self.autodetect_start.GetValue())
752
753 self.mw.config.WriteInt('splashscreentime',
754 int(self.splashscreen.GetValue()*1000))
755
756 if __debug__:
757 self.mw.config.WriteInt('console',
758 self.dev_console.GetValue())
759
760 self.mw.config.Flush()
761
762 self.mw.SetPhoneModelStatus()
763
764 self.mw.update_cache_path()
765
782
789
791 save_size("ConfigDialog", self.GetRect())
792
803
804
805
806
807
809 ID_LISTBOX=1
810 ID_TEXTBOX=2
811 ID_REFRESH=3
812 ID_SASH=4
813 ID_SAVE=5
814
815 - def __init__(self, parent, selectedphone, id=-1, title="Choose a comm port", defaultport="auto", sashposition=0):
816 wx.Dialog.__init__(self, parent, id, title, style=wx.CAPTION|wx.SYSTEM_MENU|wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
817 self.parent=parent
818 self.port=defaultport
819 self.sashposition=sashposition
820 self.selectedphone=selectedphone
821
822 p=self
823
824
825 splitter=wx.SplitterWindow(p, self.ID_SASH, style=wx.SP_3D|wx.SP_LIVE_UPDATE)
826 self.lb=wx.ListBox(splitter, self.ID_LISTBOX, style=wx.LB_SINGLE|wx.LB_HSCROLL|wx.LB_NEEDED_SB)
827 self.tb=wx.html.HtmlWindow(splitter, self.ID_TEXTBOX, size=wx.Size(400,400))
828
829
830 splitter.SetMinimumPaneSize(100)
831 splitter.SplitHorizontally(self.lb, self.tb, sashposition)
832
833
834 buttsizer=wx.GridSizer(1, 5)
835 buttsizer.Add(wx.Button(p, wx.ID_OK, "OK"), 0, wx.ALL, 10)
836 buttsizer.Add(wx.Button(p, self.ID_REFRESH, "Refresh"), 0, wx.ALL, 10)
837 buttsizer.Add(wx.Button(p, self.ID_SAVE, "Save..."), 0, wx.ALL, 10)
838 buttsizer.Add(wx.Button(p, wx.ID_HELP, "Help"), 0, wx.ALL, 10)
839 buttsizer.Add(wx.Button(p, wx.ID_CANCEL, "Cancel"), 0, wx.ALL, 10)
840
841
842 vbs=wx.BoxSizer(wx.VERTICAL)
843 vbs.Add(splitter, 1, wx.EXPAND)
844 vbs.Add(buttsizer, 0, wx.CENTER)
845
846
847 p.SetSizer(vbs)
848 p.SetAutoLayout(True)
849 vbs.Fit(p)
850
851
852 wx.CallAfter(self.OnRefresh)
853
854
855 wx.EVT_BUTTON(self, wx.ID_CANCEL, self.OnCancel)
856 wx.EVT_BUTTON(self, wx.ID_HELP, self.OnHelp)
857 wx.EVT_BUTTON(self, self.ID_REFRESH, self.OnRefresh)
858 wx.EVT_BUTTON(self, self.ID_SAVE, self.OnSave)
859 wx.EVT_BUTTON(self, wx.ID_OK, self.OnOk)
860 wx.EVT_LISTBOX(self, self.ID_LISTBOX, self.OnListBox)
861 wx.EVT_LISTBOX_DCLICK(self, self.ID_LISTBOX, self.OnListBox)
862 wx.EVT_SPLITTER_SASH_POS_CHANGED(self, self.ID_SASH, self.OnSashChange)
863
864
865 set_size("CommDialog", self, screenpct=60)
866 wx.EVT_CLOSE(self, self.OnClose)
867
869 self.sashposition=self.FindWindowById(self.ID_SASH).GetSashPosition()
870
898
900
901 p=self.portinfo[self.lb.GetSelection()]
902 if p[1] is None:
903 self.FindWindowById(wx.ID_OK).Enable(False)
904 else:
905 self.port=p[1]
906 self.FindWindowById(wx.ID_OK).Enable(True)
907 self.tb.SetPage(p[2])
908
909
911 html=StringIO.StringIO()
912
913 print >>html, "<html><head><title>BitPim port listing - %s</title></head>" % (time.ctime(), )
914 print >>html, "<body><h1>BitPim port listing - %s</h1><table>" % (time.ctime(),)
915
916 for long,actual,desc in self.portinfo:
917 if actual is None or actual=="auto": continue
918 print >>html, '<tr bgcolor="#77ff77"><td colspan=2>%s</td><td>%s</td></tr>' % (long,actual)
919 print >>html, "<tr><td colspan=3>%s</td></tr>" % (desc,)
920 print >>html, "<tr><td colspan=3><hr></td></tr>"
921 print >>html, "</table></body></html>"
922 with guihelper.WXDialogWrapper(wx.FileDialog(self, "Save port details as", defaultFile="bitpim-ports.html", wildcard="HTML files (*.html)|*.html",
923 style=wx.SAVE|wx.OVERWRITE_PROMPT|wx.CHANGE_DIR),
924 True) as (dlg, retcode):
925 if retcode==wx.ID_OK:
926 file(dlg.GetPath(), "wt").write(html.getvalue())
927
931
933 self.saveSize()
934 self.EndModal(wx.ID_OK)
935
938
943
946
949
950
951
952
953
954
956
957 - def __init__(self, parent, config, addr, fingerprint, q):
958 parent=self.FindAGoodParent(parent)
959 wx.Dialog.__init__(self, parent, -1, "Accept certificate?", style=wx.CAPTION|wx.SYSTEM_MENU|wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
960 self.config=config
961 self.q=q
962 self.addr=addr
963 self.fingerprint=fingerprint
964 hbs=wx.BoxSizer(wx.HORIZONTAL)
965 hbs.Add(wx.StaticText(self, -1, "Host:"), 0, wx.ALL, 5)
966 hbs.Add(wx.StaticText(self, -1, addr[0]), 0, wx.ALL, 5)
967 hbs.Add(wx.StaticText(self, -1, " Fingerprint:"), 0, wx.ALL, 5)
968 hbs.Add(wx.StaticText(self, -1, fingerprint), 1, wx.ALL, 5)
969 vbs=wx.BoxSizer(wx.VERTICAL)
970 vbs.Add(hbs, 0, wx.EXPAND|wx.ALL, 5)
971 vbs.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 7)
972 but=self.CreateButtonSizer(wx.YES|wx.NO|wx.HELP)
973 vbs.Add(but, 0, wx.ALIGN_CENTER|wx.ALL, 10)
974
975 self.SetSizer(vbs)
976 vbs.Fit(self)
977
978 wx.EVT_BUTTON(self, wx.ID_YES, self.OnYes)
979 wx.EVT_BUTTON(self, wx.ID_NO, self.OnNo)
980 wx.EVT_BUTTON(self, wx.ID_CANCEL, self.OnNo)
981
982
983
985 wx.GetApp().config.Write("bitfling/certificates/%s" % (self.addr[0],), self.fingerprint)
986 wx.GetApp().config.Flush()
987 if self.IsModal():
988 self.EndModal(wx.ID_YES)
989 else:
990 self.Show(False)
991 wx.CallAfter(self.Destroy)
992 print "returning true from AcceptCertificateDialog"
993 self.q.put( (True, None) )
994
996 if self.IsModal():
997 self.EndModal(wx.ID_NO)
998 else:
999 self.Show(False)
1000 wx.CallAfter(self.Destroy)
1001 print "returning false from AcceptCertificateDialog"
1002 self.q.put( (False, None) )
1003
1005 win=wx.Window_FindFocus()
1006 while win is not None:
1007 try:
1008 if win.IsModal():
1009 print "FindAGoodParent is",win
1010 return win
1011 except AttributeError:
1012 parent=win.GetParent()
1013 win=parent
1014 return suggestion
1015
1016
1017
1018
1019
1021
1022 ID_USERNAME=wx.NewId()
1023 ID_PASSWORD=wx.NewId()
1024 ID_HOST=wx.NewId()
1025 ID_PORT=wx.NewId()
1026 ID_TEST=wx.NewId()
1027 passwordsentinel="@+_-3@<,"
1028
1030 wx.Dialog.__init__(self, parent, -1, "Edit BitFling settings", style=wx.CAPTION|wx.SYSTEM_MENU|wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
1031 self.config=config
1032 gs=wx.FlexGridSizer(1, 2, 5, 5)
1033 gs.AddGrowableCol(1)
1034 gs.AddMany([
1035 (wx.StaticText(self, -1, "Username"), 0, wx.ALIGN_CENTER_VERTICAL),
1036 (wx.TextCtrl(self, self.ID_USERNAME), 1, wx.EXPAND),
1037 (wx.StaticText(self, -1, "Password"), 0, wx.ALIGN_CENTER_VERTICAL),
1038 (wx.TextCtrl(self, self.ID_PASSWORD, style=wx.TE_PASSWORD), 1, wx.EXPAND),
1039 (wx.StaticText(self, -1, "Host"), 0, wx.ALIGN_CENTER_VERTICAL),
1040 (wx.TextCtrl(self, self.ID_HOST), 1, wx.EXPAND),
1041 (wx.StaticText(self, -1, "Port"), 0, wx.ALIGN_CENTER_VERTICAL),
1042 (wx.lib.intctrl.IntCtrl(self, self.ID_PORT, value=12652, min=1, max=65535), 0)
1043 ])
1044 vbs=wx.BoxSizer(wx.VERTICAL)
1045 vbs.Add(gs, 0, wx.EXPAND|wx.ALL, 5)
1046 vbs.Add((1,1), 1, wx.EXPAND)
1047 vbs.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 10)
1048
1049 gs=wx.GridSizer(1,4, 5,5)
1050 gs.Add(wx.Button(self, wx.ID_OK, "OK"))
1051 gs.Add(wx.Button(self, self.ID_TEST, "Test"))
1052 gs.Add(wx.Button(self, wx.ID_HELP, "Help"))
1053 gs.Add(wx.Button(self, wx.ID_CANCEL, "Cancel"))
1054 vbs.Add(gs, 0, wx.ALIGN_CENTER|wx.ALL, 10)
1055 self.SetSizer(vbs)
1056 vbs.Fit(self)
1057 set_size("BitFlingConfigDialog", self, -20, 0.5)
1058
1059
1060 wx.EVT_BUTTON(self, self.ID_TEST, self.OnTest)
1061
1062
1063 defaultuser="user"
1064 try:
1065 defaultuser=getpass.getuser()
1066 except:
1067 pass
1068 self.FindWindowById(self.ID_USERNAME).SetValue(config.Read("bitfling/username", defaultuser))
1069 if len(config.Read("bitfling/password", "")):
1070 self.FindWindowById(self.ID_PASSWORD).SetValue(self.passwordsentinel)
1071 self.FindWindowById(self.ID_HOST).SetValue(config.Read("bitfling/host", ""))
1072 self.FindWindowById(self.ID_PORT).SetValue(config.ReadInt("bitfling/port", 12652))
1073
1075 res=wx.Dialog.ShowModal(self)
1076 save_size("BitFlingConfigDialog", self.GetRect())
1077 return res
1078
1087
1089 "Copy settings from dialog fields into config object"
1090 username,pwd,host,port=self.GetSettings()
1091 self.config.Write("bitfling/username", username)
1092 self.config.Write("bitfling/password", bitflingscan.encode(pwd))
1093 self.config.Write("bitfling/host", host)
1094 self.config.WriteInt("bitfling/port", port)
1095
1098
1111
1112
1113
1114
1115
1116
1117 basename=common.basename
1118 stripext=common.stripext
1119 getext=common.getext
1120
1121
1122
1123
1124
1125
1154
1155
1156
1157
1158 import StringIO
1159
1161 - def __init__(self, parent, exception, title="Exception"):
1162 wx.Dialog.__init__(self, parent, title=title, style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.THICK_FRAME|wx.MAXIMIZE_BOX, size=(740, 580))
1163 self.maintext=wx.TextCtrl(self, style=wx.TE_MULTILINE|wx.TE_READONLY|wx.TE_RICH2|wx.HSCROLL)
1164 vbs=wx.BoxSizer(wx.VERTICAL)
1165 vbs.Add(self.maintext, 1, wx.EXPAND|wx.ALL, 5)
1166
1167 buttsizer=wx.GridSizer(1, 4)
1168 buttsizer.Add(wx.Button(self, wx.ID_CANCEL, "Abort BitPim"), 0, wx.ALL, 10)
1169 buttsizer.Add(wx.Button(self, wx.ID_HELP, "Help"), 0, wx.ALL, 10)
1170 buttsizer.Add(wx.Button(self, wx.ID_OK, "Continue"), 0, wx.ALL, 10)
1171 _id=wx.NewId()
1172 buttsizer.Add(wx.Button(self, _id, "Create Trouble Report"), 0, wx.ALL, 10)
1173
1174 vbs.Add(buttsizer, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
1175
1176 wx.EVT_BUTTON(self, wx.ID_CANCEL, self.abort)
1177 wx.EVT_BUTTON(self, wx.ID_HELP, lambda _: wx.GetApp().displayhelpid(helpids.ID_EXCEPTION_DIALOG))
1178 wx.EVT_BUTTON(self, _id, self.OnCreateReport)
1179
1180 self.SetSizer(vbs)
1181 self._text=""
1182 self.addexception(exception)
1183
1185 import os
1186 os._exit(1)
1187
1189 s=StringIO.StringIO()
1190 s.write("BitPim version: "+version.versionstring+"-"+version.vendor+"\nAn unexpected exception has occurred.\nPlease see the help for details on what to do.\n\n")
1191 if hasattr(exception, 'gui_exc_info'):
1192 s.write(common.formatexception(exception.gui_exc_info))
1193 else:
1194 s.write("Exception with no extra info.\n%s\n" % (exception.str(),))
1195 self._text=s.getvalue()
1196 self.maintext.SetValue(self._text)
1197
1198 - def getexceptiontext(self):
1200
1215
1217 with contextlib.closing(gzip.GzipFile(vals['filename'], 'wb')) as _s:
1218 _s.write('BitPim Trouble Report\n')
1219 _s.write(time.asctime()+'\n')
1220 _s.write('BitPim Version: %s - %s\n'%(version.versionstring, version.vendor))
1221 _s.write('Platorm: %s, Architecture: %s %s, Dist: %s %s %s\n'%\
1222 ((platform.platform(),)+platform.architecture()+\
1223 platform.dist()))
1224
1225 try:
1226 _model=self.GetParent().phonemodule.Phone.desc
1227 except:
1228 _model='Not Available'
1229 _s.write('Phone Model: %s\n'%_model)
1230 _s.write('Name: %s\n'%vals['name'])
1231 _s.write('email: %s\n'%vals['email'])
1232 _s.write('Description: %s\n'%vals['description'])
1233 _s.write('Exception:\n%s\n'%self._text)
1234
1235 try:
1236 _log=self.GetParent().tree.lw.GetValue()
1237 except:
1238
1239 _log='Not Available'
1240 _s.write('BitPim Log:\n%s\n'%_log)
1241
1242 try:
1243 _log=self.GetParent().tree.lwdata.GetValue()
1244 except:
1245 _log='Not Available'
1246 _s.write('BitPim Protocol Data:\n%s\n'%_log)
1247
1249
1250 _default_filename='bpbug.gz'
1252 wx.Dialog.__init__(self, parent, -1, 'BitPim Trouble Report',
1253 style=wx.CAPTION|wx.SYSTEM_MENU|wx.DEFAULT_DIALOG_STYLE)
1254
1255 gs=wx.GridBagSizer(10, 10)
1256 gs.AddGrowableCol(1)
1257 _width=300
1258 _row=0
1259
1260 gs.Add( wx.StaticText(self, -1, "Name:"), pos=(_row,0),
1261 flag=wx.ALIGN_CENTER_VERTICAL)
1262 self._name=wx.TextCtrl(self, -1, '', size=(_width,-1))
1263 gs.Add(self._name, pos=(_row, 1), flag=wx.ALIGN_CENTER_VERTICAL)
1264 _row+=1
1265
1266 gs.Add( wx.StaticText(self, -1, "email:"), pos=(_row,0), flag=wx.ALIGN_CENTER_VERTICAL)
1267 self._email=wx.TextCtrl(self, -1, '', size=(_width,-1))
1268 gs.Add(self._email, pos=(_row, 1), flag=wx.ALIGN_CENTER_VERTICAL)
1269 _row+=1
1270
1271 gs.Add( wx.StaticText(self, -1, "File Name:"), pos=(_row,0), flag=wx.ALIGN_CENTER_VERTICAL)
1272 self._filename=wx.TextCtrl(self, -1, self._default_filename,
1273 size=(_width,-1))
1274 gs.Add(self._filename, pos=(_row, 1), flag=wx.ALIGN_CENTER_VERTICAL)
1275 _browseid=wx.NewId()
1276 gs.Add(wx.Button(self, _browseid, 'Browse ...'), pos=(_row, 2),
1277 flag=wx.ALIGN_CENTER_VERTICAL)
1278 _row+=1
1279
1280 gs.Add(wx.StaticText(self, -1, 'Trouble Description:'), pos=(_row, 0),
1281 flag=wx.ALIGN_CENTER_VERTICAL)
1282 self._desc=wx.TextCtrl(self, -1, '',
1283 style=wx.TE_MULTILINE|wx.TE_BESTWRAP,
1284 size=(_width, 100))
1285 gs.Add(self._desc, pos=(_row, 1), flag=wx.ALIGN_CENTER_VERTICAL)
1286 _row+=1
1287
1288
1289 bs=wx.BoxSizer(wx.VERTICAL)
1290 bs.Add(gs, 0, wx.EXPAND|wx.ALL, 10)
1291 bs.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 7)
1292
1293 but=self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.HELP)
1294 bs.Add(but, 0, wx.CENTER|wx.ALL, 10)
1295
1296 wx.EVT_BUTTON(self, wx.ID_HELP, self.OnHelp)
1297 wx.EVT_BUTTON(self, _browseid, self.OnBrowse)
1298
1299 self.SetSizer(bs)
1300 self.SetAutoLayout(True)
1301 bs.Fit(self)
1302
1321
1322
1323
1324
1325 BUFFERED=0
1326 -class StatusText(stattext.GenStaticText):
1327
1328 red=None
1329 green=None
1330 yellow=None
1331 - def __init__(self, parent, ID, label,
1332 pos = wx.DefaultPosition, size = wx.DefaultSize,
1333 style = 0,
1334 name = "statustext"):
1335
1336 self._text_margin=5
1337
1338 self._status_size=1.0
1339
1340 if StatusText.red is None:
1341 StatusText.red=wx.RED
1342 StatusText.green=wx.GREEN
1343 StatusText.yellow=wx.NamedColour('YELLOW')
1344 self._stat=StatusText.green
1345 super(StatusText, self).__init__(parent, ID, label,
1346 pos=pos, style=style, name=name)
1347 - def DoGetBestSize(self):
1348 """
1349 Overridden base class virtual. Determines the best size of
1350 the control based on the label size and the current font.
1351 """
1352 _s=super(StatusText, self).DoGetBestSize()
1353 _s.SetWidth(_s.GetWidth()+_s.GetHeight()*self._status_size+\
1354 self._text_margin)
1355 self.CacheBestSize(_s)
1356 return _s
1357 - def _draw_status(self, dc, w, h):
1358
1359 dc.BeginDrawing()
1360 dc.SetBrush(wx.Brush(self._stat, wx.SOLID))
1361 _r=(h*self._status_size)/2
1362 dc.DrawCircle(_r, h/2, _r)
1363 dc.EndDrawing
1364
1365 - def OnPaint(self, event):
1366 if BUFFERED:
1367 dc = wx.BufferedPaintDC(self)
1368 else:
1369 dc = wx.PaintDC(self)
1370 width, height = self.GetClientSize()
1371 if not width or not height:
1372 return
1373
1374 if BUFFERED:
1375 clr = self.GetBackgroundColour()
1376 backBrush = wx.Brush(clr, wx.SOLID)
1377 if wx.Platform == "__WXMAC__" and clr == self.defBackClr:
1378
1379 backBrush.MacSetTheme(1)
1380 dc.SetBackground(backBrush)
1381 dc.Clear()
1382 self._draw_status(dc, width, height)
1383 dc.SetTextForeground(self.GetForegroundColour())
1384 dc.SetFont(self.GetFont())
1385 label = self.GetLabel()
1386 style = self.GetWindowStyleFlag()
1387 y = 0
1388 x=height*self._status_size+self._text_margin
1389 for line in label.split('\n'):
1390 if line == '':
1391 w, h = self.GetTextExtent('W')
1392 else:
1393 w, h = self.GetTextExtent(line)
1394 if style & wx.ALIGN_RIGHT:
1395 x = width - w
1396 if style & wx.ALIGN_CENTER:
1397 x = (width - w)/2
1398 dc.DrawText(line, x, y)
1399 y += h
1400
1401 - def SetLabel(self, label, status=None):
1402 if status:
1403 self._stat=status
1404 super(StatusText, self).SetLabel(label)
1405 - def SetStatus(self, status):
1406 self._stat=status
1407 self.Refresh()
1408
1409 SB_Phone_Set=0
1410 SB_Phone_Detected=1
1411 SB_Phone_Unavailable=2
1413 __total_panes=3
1414 __version_index=2
1415 __phone_model_index=2
1416 __app_status_index=0
1417 __gauge_index=1
1418 __major_progress_index=2
1419 __minor_progress_index=2
1420 __help_str_index=2
1421 __general_pane=2
1422 __pane_width=[70, 180, -1]
1423
1425 wx.StatusBar.__init__(self, parent, id)
1426 self.__major_progress_text=self.__version_text=self.__phone_text=''
1427 self.sizechanged=False
1428 wx.EVT_SIZE(self, self.OnSize)
1429 wx.EVT_IDLE(self, self.OnIdle)
1430 self.gauge=wx.Gauge(self, 1000, 1)
1431 self._status=StatusText(self, -1, '', style=wx.ST_NO_AUTORESIZE)
1432 self._phone_model=StatusText(self, -1, '', style=wx.ST_NO_AUTORESIZE)
1433 self.SetFieldsCount(self.__total_panes)
1434 self.SetStatusWidths(self.__pane_width)
1435
1436
1438 self.sizechanged=True
1439
1451
1453 self.sizechanged = False
1454 rect=self.GetFieldRect(self.__gauge_index)
1455 self.gauge.SetPosition(wx.Point(rect.x+2, rect.y+2))
1456 self.gauge.SetSize(wx.Size(rect.width-4, rect.height-4))
1457 rect=self.GetFieldRect(self.__app_status_index)
1458 self._status.SetPosition(wx.Point(rect.x+2, rect.y+2))
1459 self._status.SetSize(wx.Size(rect.width-4, rect.height-4))
1460 rect=self.GetFieldRect(self.__phone_model_index)
1461 self._phone_model.SetPosition(wx.Point(rect.x+rect.width/2+2, rect.y+2))
1462 self._phone_model.SetSize(wx.Size(rect.width/2-4, rect.height-4))
1463
1474
1476 if len(desc) and max:
1477 self.__major_progress_text="%d/%d %s" % (pos+1, max, desc)
1478 else:
1479 self.__major_progress_text=desc
1480 self.progressminor(0,1)
1481
1500 s='BitPim '+current
1501 if len(latest):
1502 s+='/Latest '+latest
1503 else:
1504 s+='/Latest <Unknown>'
1505 self.__version_text=s
1506 self.__set_version_phone_text()
1508 self.SetStatusText(self.__version_text, self.__version_index)
1509
1510
1511
1512
1513
1515 """A dialog box with Ok button and a help button"""
1516 - def __init__(self, parent, message, caption, helpfn, style=wx.DEFAULT_DIALOG_STYLE, icon=wx.ICON_EXCLAMATION):
1517 wx.Dialog.__init__(self, parent, -1, caption, style=style|wx.DEFAULT_DIALOG_STYLE)
1518
1519 p=self
1520
1521
1522 hbs=wx.BoxSizer(wx.HORIZONTAL)
1523 hbs.Add(wx.StaticBitmap(p, -1, wx.ArtProvider_GetBitmap(self.icontoart(icon), wx.ART_MESSAGE_BOX)), 0, wx.CENTER|wx.ALL, 10)
1524 hbs.Add(wx.StaticText(p, -1, message), 1, wx.CENTER|wx.ALL, 10)
1525
1526
1527 buttsizer=self.CreateButtonSizer(wx.HELP|style)
1528
1529
1530 vbs=wx.BoxSizer(wx.VERTICAL)
1531 vbs.Add(hbs, 1, wx.EXPAND|wx.ALL, 10)
1532 vbs.Add(buttsizer, 0, wx.CENTER|wx.ALL, 10)
1533
1534
1535 self.SetSizer(vbs)
1536 self.SetAutoLayout(True)
1537 vbs.Fit(self)
1538
1539 wx.EVT_BUTTON(self, wx.ID_HELP, helpfn)
1540
1542 if id&wx.ICON_EXCLAMATION:
1543 return wx.ART_WARNING
1544 if id&wx.ICON_INFORMATION:
1545 return wx.ART_INFORMATION
1546
1547
1548 return wx.ART_INFORMATION
1549
1550
1551
1552
1553
1555 """A dialog box with user supplied buttons"""
1556 - def __init__(self, parent, message, caption, buttons, helpfn=None,
1557 style=wx.DEFAULT_DIALOG_STYLE, icon=wx.ICON_EXCLAMATION):
1558 """Constructor
1559
1560 @param message: Text displayed in body of dialog
1561 @param caption: Title of dialog
1562 @param buttons: A list of tuples. Each tuple is a string and an integer id.
1563 The result of calling ShowModal() is the id
1564 @param helpfn: The function called if the user presses the help button (wx.ID_HELP)
1565 """
1566 wx.Dialog.__init__(self, parent, -1, caption, style=style)
1567
1568 p=self
1569
1570
1571 hbs=wx.BoxSizer(wx.HORIZONTAL)
1572 hbs.Add(wx.StaticBitmap(p, -1, wx.ArtProvider_GetBitmap(self.icontoart(icon), wx.ART_MESSAGE_BOX)), 0, wx.CENTER|wx.ALL, 10)
1573 hbs.Add(wx.StaticText(p, -1, message), 1, wx.CENTER|wx.ALL, 10)
1574
1575
1576 buttsizer=wx.BoxSizer(wx.HORIZONTAL)
1577 for label,id in buttons:
1578 buttsizer.Add( wx.Button(self, id, label), 0, wx.ALL|wx.ALIGN_CENTER, 5)
1579 if id!=wx.ID_HELP:
1580 wx.EVT_BUTTON(self, id, self.OnButton)
1581 else:
1582 wx.EVT_BUTTON(self, wx.ID_HELP, helpfn)
1583
1584
1585 vbs=wx.BoxSizer(wx.VERTICAL)
1586 vbs.Add(hbs, 1, wx.EXPAND|wx.ALL, 10)
1587 vbs.Add(buttsizer, 0, wx.CENTER|wx.ALL, 10)
1588
1589
1590 self.SetSizer(vbs)
1591 self.SetAutoLayout(True)
1592 vbs.Fit(self)
1593
1596
1598 if id&wx.ICON_EXCLAMATION:
1599 return wx.ART_WARNING
1600 if id&wx.ICON_INFORMATION:
1601 return wx.ART_INFORMATION
1602
1603
1604 return wx.ART_INFORMATION
1605
1606
1607
1608
1609
1610
1611 -def set_size(confname, window, screenpct=50, aspect=1.0):
1612 """Sets remembered/calculated dimensions/position for window
1613
1614 @param confname: subkey to store/get this windows's settings from
1615 @param window: the window object itself
1616 @param screenpct: percentage of the screen the window should occupy.
1617 If this value is negative then the window will not be resized,
1618 only repositioned (unless the current size is silly)
1619 @param aspect: aspect ratio. If greater than one then it is
1620 how much wider than tall the window is, and if less
1621 than one then the other way round
1622 """
1623 confobj=wx.GetApp().config
1624
1625
1626 confname="windows/"+confname
1627
1628
1629 screenSize = wx.GetClientDisplayRect()
1630 if (aspect >= 1):
1631 newWidth = screenSize.width * abs(screenpct) / 100
1632 newHeight = screenSize.height * abs(screenpct) / aspect / 100
1633 else:
1634 newWidth = screenSize.width * abs(screenpct) * aspect / 100
1635 newHeight = screenSize.height * abs(screenpct) / 100
1636
1637 if screenpct<=0:
1638 rs_width,rs_height=window.GetSizeTuple()
1639 else:
1640
1641 rs_width = confobj.ReadInt(confname + "/width", int(newWidth))
1642 rs_height = confobj.ReadInt(confname + "/height", int(newHeight))
1643
1644
1645
1646 unconfigured=-65245
1647
1648 rs_x = confobj.ReadInt(confname + "/x", unconfigured)
1649 rs_y = confobj.ReadInt(confname + "/y", unconfigured)
1650
1651
1652 if rs_height < 96:
1653 rs_height = newHeight
1654 if rs_width < 96:
1655 rs_width = newWidth
1656
1657
1658
1659
1660 rs_aspect = rs_width/rs_height
1661 if rs_aspect >= 1:
1662 if rs_width > screenSize.width:
1663 rs_width = screenSize.width
1664 if rs_height > (screenSize.height):
1665 rs_height = (screenSize.height / rs_aspect) - screenSize.y
1666 else:
1667 if rs_width > screenSize.width:
1668 rs_width = screenSize.width * rs_aspect
1669 if rs_height > screenSize.height - screenSize.y:
1670 rs_height = screenSize.height - screenSize.y
1671
1672
1673 if rs_x!=unconfigured and rs_x > screenSize.width:
1674 rs_x = screenSize.width - 50
1675 if rs_x!=unconfigured and rs_x + rs_width < screenSize.x:
1676 rs_x = screenSize.x
1677 if rs_y!=unconfigured and rs_y > screenSize.height:
1678 rs_y = screenSize.height - 50
1679 if rs_y!=unconfigured and rs_y + rs_height < screenSize.y:
1680 rs_y = screenSize.y
1681
1682
1683 if screenpct<=0 and (rs_width,rs_height)==window.GetSizeTuple():
1684
1685 if rs_x!=unconfigured and rs_y!=unconfigured:
1686 print "setting %s to position %d, %d" % (confname, rs_x, rs_y)
1687 window.SetPosition(wx.Point(rs_x, rs_y))
1688 else:
1689 if rs_x==unconfigured or rs_y==unconfigured:
1690 print "setting %s to size %d x %d" % (confname, rs_width, rs_height)
1691 window.SetSize(wx.Size(rs_width, rs_height))
1692 else:
1693 print "setting %s to position %d, %d - size %d x %d" % (confname, rs_x, rs_y, rs_width, rs_height)
1694 window.SetDimensions(rs_x, rs_y, rs_width, rs_height)
1695
1697 """Saves size to config. L{set_size}
1698
1699 @param confname: Same string as in set_size
1700 @param myRect: Window size you want remembered, typically window.GetRect()
1701 """
1702 confobj=wx.GetApp().config
1703
1704 confname="windows/"+confname
1705
1706 x = myRect.x
1707 y = myRect.y
1708 width = myRect.width
1709 height = myRect.height
1710
1711 confobj.WriteInt(confname + "/x", x)
1712 confobj.WriteInt(confname + "/y", y)
1713 confobj.WriteInt(confname + "/width", width)
1714 confobj.WriteInt(confname + "/height", height)
1715 confobj.Flush()
1716
1718 """ display log string and progress bar at the same time
1719 """
1720 - def __init__(self, title, message, maximum=100, parent=None,
1721 style=wx.PD_AUTO_HIDE|wx.PD_APP_MODAL):
1725 - def Update(self, value, newmsg='', skip=None):
1728 - def log(self, msgstr):
1730
1762
1764 Current_Data=0
1765 Historical_Data=1
1766 _Historical_Date=1
1767 _Historical_Event=2
1768 - def __init__(self, parent, caption='Historical Data Selection',
1769 current_choice=Current_Data,
1770 historical_date=None,
1771 historical_events=None):
1772 super(HistoricalDataDialog, self).__init__(parent, -1, caption)
1773 vbs=wx.BoxSizer(wx.VERTICAL)
1774 hbs=wx.BoxSizer(wx.HORIZONTAL)
1775 self.data_selector=wx.RadioBox(self, wx.NewId(),
1776 'Data Selection:',
1777 choices=('Current', 'Historical Date',
1778 'Historical Event'),
1779 style=wx.RA_SPECIFY_ROWS)
1780 self.data_selector.SetSelection(current_choice)
1781 wx.EVT_RADIOBOX(self, self.data_selector.GetId(), self.OnSelectData)
1782 hbs.Add(self.data_selector, 0, wx.ALL, 5)
1783 static_bs=wx.StaticBoxSizer(wx.StaticBox(self, -1,
1784 'Historical Date:'),
1785 wx.VERTICAL)
1786 self.data_date=wx.DatePickerCtrl(self,
1787 style=wx.DP_DROPDOWN | wx.DP_SHOWCENTURY)
1788 if historical_date is not None:
1789 self.data_date.SetValue(wx.DateTimeFromTimeT(historical_date))
1790 self.data_date.Enable(current_choice==self._Historical_Date)
1791 static_bs.Add(self.data_date, 1, wx.EXPAND, 0)
1792 hbs.Add(static_bs, 0, wx.ALL, 5)
1793
1794 static_bs=wx.StaticBoxSizer(wx.StaticBox(self, -1, 'Historical Events:'),
1795 wx.VERTICAL)
1796 self.hist_events=wx.ListBox(self, -1, style=wx.LB_SINGLE)
1797 if historical_events:
1798 self._populate_historical_events(historical_events)
1799 self.hist_events.Enable(current_choice==self._Historical_Event)
1800 static_bs.Add(self.hist_events, 1, wx.EXPAND, 0)
1801 hbs.Add(static_bs, 0, wx.ALL, 5)
1802
1803 vbs.Add(hbs, 1, wx.EXPAND|wx.ALL, 5)
1804 vbs.Add(wx.StaticLine(self), 0, wx.EXPAND|wx.ALL, 5)
1805 vbs.Add(self.CreateButtonSizer(wx.OK|wx.CANCEL), 0,
1806 wx.ALIGN_CENTER|wx.ALL, 5)
1807 self.SetSizer(vbs)
1808 self.SetAutoLayout(True)
1809 vbs.Fit(self)
1810
1814
1836
1838 keys=historical_events.keys()
1839 keys.sort()
1840 keys.reverse()
1841 for k in keys:
1842
1843 self.hist_events.Append('%s %02d-Adds %02d-Dels %02d-Mods'%\
1844 (time.strftime('%b %d, %y %H:%M:%S',
1845 time.localtime(k)),
1846 historical_events[k]['add'],
1847 historical_events[k]['del'],
1848 historical_events[k]['mod']),
1849 k)
1850
1851
1853 - def __init__(self, parent, column_info):
1854 self.lcparent=parent
1855 wx.ListCtrl.__init__(self, self.lcparent, wx.NewId(), style=wx.LC_REPORT|wx.LC_VIRTUAL)
1856 index=0
1857 self.column_type=[]
1858 for info in column_info:
1859 text, width, int_sort=info
1860 self.InsertColumn(index, text, width=width)
1861 self.column_type.append(int_sort)
1862 index+=1
1863 self.handle_paint=False
1864 listmix.ColumnSorterMixin.__init__(self, index)
1865 self.font=wx.TheFontList.FindOrCreateFont(10, family=wx.SWISS, style=wx.NORMAL, weight=wx.NORMAL)
1866 self.image_list=wx.ImageList(16, 16)
1867 a={"sm_up":"GO_UP","sm_dn":"GO_DOWN","w_idx":"WARNING","e_idx":"ERROR","i_idx":"QUESTION"}
1868 for k,v in a.items():
1869 s="self.%s= self.image_list.Add(wx.ArtProvider_GetBitmap(wx.ART_%s,wx.ART_TOOLBAR,(16,16)))" % (k,v)
1870 exec(s)
1871 self.SetImageList(self.image_list, wx.IMAGE_LIST_SMALL)
1872
1874 col=self._col
1875 sf=self._colSortFlag[col]
1876
1877
1878 items=[]
1879 for k,v in self.itemDataMap.items():
1880 if self.column_type[col]:
1881 items.append([int(v[col]),k])
1882 else:
1883 items.append([v[col],k])
1884
1885 items.sort()
1886 k=[key for value, key in items]
1887
1888
1889 if sf==False:
1890 k.reverse()
1891
1892 self.itemIndexMap=k
1893
1894
1895 self.Refresh()
1896
1899
1901 return (self.sm_dn, self.sm_up)
1902
1903 - def OnGetItemText(self, item, col):
1904 index=self.itemIndexMap[item]
1905 s = self.itemDataMap[index][col]
1906 return s
1907
1910
1913
1915 index=self.itemIndexMap[item]
1916 return self.itemPyDataMap[index]
1917
1919 item=self.GetTopItem()
1920 while item!=-1:
1921 self.Select(item)
1922 item=self.GetNextItem(item)
1923
1924 - def ResetView(self, display_data, data_keys):
1925 self.itemDataMap = display_data
1926 self.itemIndexMap = display_data.keys()
1927 self.itemPyDataMap = data_keys
1928 count=len(self.lcparent.nodes)
1929 self.SetItemCount(count)
1930 self.SortListItems()
1931 if count==0 and not self.handle_paint:
1932 wx.EVT_PAINT(self, self.OnPaint)
1933 self.handle_paint=True
1934 elif count!=0 and self.handle_paint:
1935 self.Unbind(wx.EVT_PAINT)
1936 self.handle_paint=False
1937
1939 w,h=self.GetSize()
1940 self.Refresh()
1941 dc=wx.PaintDC(self)
1942 dc.BeginDrawing()
1943 dc.SetFont(self.font)
1944 x,y= dc.GetTextExtent("There are no items to show in this view")
1945
1946 xx=(w-x)/2
1947 if xx<0:
1948 xx=0
1949 dc.DrawText("There are no items to show in this view", xx, h/3)
1950 dc.EndDrawing()
1951
1953 sels_idx={}
1954 index=0
1955 sels_idx[index]=self.GetFirstSelected()
1956
1957 while sels_idx[index]!=-1:
1958 index+=1
1959 sels_idx[index]=self.GetNextSelected(sels_idx[index-1])
1960 del sels_idx[index]
1961 return sels_idx
1962
1964 """
1965 A dialog to ask for and provide the file name for a Data Recording file
1966 """
1968 super(DRRecFileDialog, self).__init__(parent, -1,
1969 'BitPim Data Recording')
1970 vbs=wx.BoxSizer(wx.VERTICAL)
1971 fgs=wx.GridBagSizer(5, 5)
1972 fgs.Add(wx.StaticText(self, -1, 'File Name:'), pos=(0,0),
1973 flag=wx.EXPAND|wx.ALL)
1974 self._file_name=wx.TextCtrl(self, -1, 'bitpim.dat')
1975 fgs.Add(self._file_name, pos=(0, 1), flag=wx.EXPAND|wx.ALL)
1976 _brw_btn=wx.Button(self, -1, 'Browse')
1977 fgs.Add(_brw_btn, pos=(0, 2), flag=wx.EXPAND|wx.ALL)
1978 wx.EVT_BUTTON(self, _brw_btn.GetId(), self.OnBrowse)
1979 fgs.Add(wx.StaticText(self, -1, 'Open Mode:'), pos=(1,0),
1980 flag=wx.EXPAND|wx.ALL)
1981 self._append=wx.CheckBox(self, -1, 'Append to existing file')
1982 fgs.Add(self._append, pos=(1, 1), flag=wx.EXPAND|wx.ALL)
1983 if __debug__:
1984 _setstart_btn=wx.Button(self, -1, 'Set Start')
1985 wx.EVT_BUTTON(self, _setstart_btn.GetId(), self.OnSetStart)
1986 fgs.Add(_setstart_btn, pos=(1, 2), flag=wx.EXPAND|wx.ALL)
1987 fgs.Add(wx.StaticText(self, -1, 'Status:'), pos=(2,0),
1988 flag=wx.EXPAND|wx.ALL)
1989 self._status=wx.StaticText(self, -1, 'None')
1990 fgs.Add(self._status, pos=(2,1), flag=wx.EXPAND|wx.ALL)
1991 vbs.Add(fgs, 0, wx.EXPAND|wx.ALL, 5)
1992 vbs.Add(wx.StaticLine(self), 0, wx.EXPAND|wx.ALL, 5)
1993 hbs=wx.BoxSizer(wx.HORIZONTAL)
1994 if __debug__:
1995 _btn=wx.Button(self, -1, 'View')
1996 wx.EVT_BUTTON(self,_btn.GetId(), self.OnView)
1997 hbs.Add(_btn, 0, wx.EXPAND|wx.ALL, 5)
1998 _btn=wx.Button(self, -1, 'Record')
1999 wx.EVT_BUTTON(self, _btn.GetId(), self.OnRecord)
2000 hbs.Add(_btn, 0, wx.EXPAND|wx.ALL, 5)
2001 if __debug__:
2002 _btn=wx.Button(self, -1, 'Play')
2003 wx.EVT_BUTTON(self, _btn.GetId(), self.OnPlay)
2004 hbs.Add(_btn, 0, wx.EXPAND|wx.ALL, 5)
2005 _btn=wx.Button(self, -1, 'Stop')
2006 wx.EVT_BUTTON(self, _btn.GetId(), self.OnStop)
2007 hbs.Add(_btn, 0, wx.EXPAND|wx.ALL, 5)
2008 _btn=wx.Button(self, wx.ID_CANCEL, 'Close')
2009 hbs.Add(_btn, 0, wx.EXPAND|wx.ALL, 5)
2010 vbs.Add(hbs, 0, wx.EXPAND|wx.ALL, 5)
2011
2012 self._update_status()
2013
2014 self.SetSizer(vbs)
2015 self.SetAutoLayout(True)
2016 vbs.Fit(self)
2017
2032
2034 _dlg=wx.FileDialog(self)
2035 _dlg.SetPath(self._file_name.GetValue())
2036 with guihelper.WXDialogWrapper(_dlg, True) as (_dlg, retcode):
2037 if retcode==wx.ID_OK:
2038 self._file_name.SetValue(_dlg.GetPath())
2039
2043
2047
2051
2055
2066
2067
2068 _license="""The BitPim code is under the GNU General Public License as detailed
2069 below. Specific permission is granted for this code to be linked to
2070 OpenSSL (this is necessary because the OpenSSL license is not
2071 GPL-compatible).
2072
2073 In addition, as a special exception, the BitPim copyright holders
2074 give permission to link the code of this program with the OpenSSL
2075 library (or with modified versions of OpenSSL), and distribute
2076 linked combinations including the two. You must obey the GNU
2077 General Public License in all respects for all of the code used
2078 other than OpenSSL. If you modify any files, you may extend this
2079 exception to your version of the file, but you are not obligated to
2080 do so. If you do not wish to do so, delete this exception statement
2081 from your version.
2082
2083 Please also note that some code is taken from other projects with a
2084 GPL compatible license. This is noted in the specific files.
2085
2086 BitPim also uses several other components with GPL compatible
2087 licenses. The online help details those components, credits the
2088 authors and details the licenses.
2089 ---------------------------------------------------------------------
2090 This program is free software; you can redistribute it and/or modify
2091 it under the terms of the GNU General Public License version 2 as published by
2092 the Free Software Foundation.
2093
2094 This program is distributed in the hope that it will be useful,
2095 but WITHOUT ANY WARRANTY; without even the implied warranty of
2096 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2097 GNU General Public License for more details. Also see the BitPim Help for more details
2098 """
2099
2100 _copyright="""(C) 2003-2007 The code in BitPim is copyright by several people. Please note the
2101 comments at the top of each file, as well as version control history.
2102 """
2103 _description=""" BitPim is a program that allows you to view and manipulate data on many CDMA phones
2104 from LG, Samsung, Sanyo and other manufacturers. This includes the PhoneBook,
2105 Calendar, WallPapers, RingTones (functionality varies by phone) and the
2106 Filesystem for most Qualcomm CDMA chipset based phones. To see when phones will
2107 be supported, which ones are already supported and which features are supported,
2108 see online help.
2109
2110 [%s]
2111 """
2113 """return a CSV string of various software components being used by BitPim"""
2114 _res=[]
2115 _str=[]
2116
2117 _str.append('Python %s'%sys.version.split()[0])
2118 _str.append('wxPython %s'%wx.version())
2119 _res.append(', '.join(_str))
2120 _str=[]
2121 _str.append('APSW %s'%apsw.apswversion())
2122 _str.append('SQLITE %s'%apsw.sqlitelibversion())
2123 _res.append(', '.join(_str))
2124 _str=[]
2125 _str.append('serial %s'%serial.VERSION)
2126
2127 try:
2128 _pywin32ver=file(os.path.join(sys.prefix,'lib','site-packages', 'pywin32.version.txt'),
2129 'rt').read()[:-1]
2130 _str.append('pywin32 %s'%_pywin32ver)
2131 except:
2132 pass
2133 _res.append(', '.join(_str))
2134 return '\n'.join(_res)
2135
2153
2154
2156 """A generic print dialog from which other can subclass for their own use"""
2157 _template_filename=None
2158 _style_filename=None
2159
2160 - def __init__(self, widget, mainwindow, config, title):
2161 super(PrintDialog, self).__init__(mainwindow, -1, title)
2162 self._widget=widget
2163 self._xcp=self._html=self._dns=None
2164 self._tmp_file=common.gettempfilename("htm")
2165
2166 vbs=wx.BoxSizer(wx.VERTICAL)
2167
2168 self._create_contents(vbs)
2169
2170 self._create_buttons(vbs)
2171
2172 self.SetSizer(vbs)
2173 self.SetAutoLayout(True)
2174 vbs.Fit(self)
2175
2176 - def _create_contents(self, vbs):
2177
2178 raise NotImplementedError
2179
2196
2198
2199 self._dns={ 'common': __import__('common') }
2200 self._dns['guihelper']=__import__('guihelper')
2201 self._dns['pagebreakstr']='<div style="page-break-before:always"/>'
2202
2204 raise NotImplementedError
2205
2233
2234
2238 - def OnPageSetup(self, _):
2239 wx.GetApp().htmlprinter.PageSetup()
2244 with guihelper.WXDialogWrapper(wx.FileDialog(self, wildcard="Web Page (*.htm;*.html)|*.htm;*html",
2245 style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT),
2246 True) as (_dlg, retcode):
2247 if retcode==wx.ID_OK:
2248 self._gen_print_data()
2249 file(_dlg.GetPath(), 'wt').write(self._html)
2251 try:
2252
2253 os.remove(self._tmp_file)
2254 except:
2255 pass
2256 self.EndModal(wx.ID_CANCEL)
2257
2258
2260
2261 _template_filename='sms.xy'
2262 _title='SMS Print'
2263 _item_name='SMS Messages'
2264
2265 - def __init__(self, smswidget, mainwindow, config):
2270
2271 - def _create_contents(self, vbs):
2272 rbs=wx.StaticBoxSizer(wx.StaticBox(self, -1, self._item_name), wx.VERTICAL)
2273 lsel=len(self._sel_data)
2274 lall=len(self._data)
2275 self.rows_selected=wx.RadioButton(self, wx.NewId(), "Selected (%d)" % (lsel,), style=wx.RB_GROUP)
2276 self.rows_all=wx.RadioButton(self, wx.NewId(), "All (%d)" % (lall,))
2277 if lsel==0:
2278 self.rows_selected.Enable(False)
2279 self.rows_selected.SetValue(0)
2280 self.rows_all.SetValue(1)
2281 rbs.Add(self.rows_selected, 0, wx.EXPAND|wx.ALL, 2)
2282 rbs.Add(self.rows_all, 0, wx.EXPAND|wx.ALL, 2)
2283 vbs.Add(rbs, 0, wx.EXPAND|wx.ALL, 5)
2284
2290
2302
2303
2308