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