Module guiwidgets
[hide private]
[frames] | no frames]

Source Code for Module guiwidgets

   1  #!/usr/bin/env python 
   2   
   3  ### BITPIM 
   4  ### 
   5  ### Copyright (C) 2003-2005 Roger Binns <rogerb@rogerbinns.com> 
   6  ### 
   7  ### This program is free software; you can redistribute it and/or modify 
   8  ### it under the terms of the BitPim license as detailed in the LICENSE file. 
   9  ### 
  10  ### $Id: guiwidgets.py 4675 2008-08-12 21:52:12Z djpham $ 
  11   
  12  """Most of the graphical user interface elements making up BitPim""" 
  13   
  14  # standard modules 
  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  # wx. modules 
  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  # my modules 
  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  ### BitFling cert stuff 
  65  ### 
  66   
  67  BitFlingCertificateVerificationEvent, EVT_BITFLINGCERTIFICATEVERIFICATION = wx.lib.newevent.NewEvent() 
  68   
  69   
  70  #### 
  71  #### A simple text widget that does nice pretty logging. 
  72  ####         
  73   
  74       
75 -class LogWindow(wx.Panel, widgets.BitPimWidget):
76 77 theanalyser=None 78
79 - def __init__(self, parent):
80 wx.Panel.__init__(self,parent, -1) 81 # have to use rich2 otherwise fixed width font isn't used on windows 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
97 - def Clear(self):
98 self.tb.Clear()
99
100 - def OnSelectAll(self, _):
101 self.tb.SetSelection(-1, -1)
102
103 - def OnShow(self, show):
104 if show.GetShow(): 105 wx.CallAfter(self.CleanupView)
106
107 - def CleanupView(self):
108 self.tb.SetInsertionPoint(0) 109 self.tb.SetInsertionPointEnd() 110 self.tb.Refresh()
111
112 - def OnIdle(self,_):
113 if self.outstandingtext.tell(): 114 # this code is written to be re-entrant 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
142 - def OnKeyUp(self, evt):
143 keycode=evt.GetKeyCode() 144 if keycode==ord('P') and evt.ControlDown() and evt.AltDown(): 145 # analyse what was selected 146 data=self.tb.GetStringSelection() 147 # or the whole buffer if it was nothing 148 if data is None or len(data)==0: 149 data=self.tb.GetValue() 150 try: 151 self.theanalyser.Show() 152 except: 153 self.theanalyser=None 154 155 if self.theanalyser is None: 156 self.theanalyser=analyser.Analyser(data=data) 157 158 self.theanalyser.Show() 159 self.theanalyser.newdata(data) 160 evt.Skip()
161
162 - def GetValue(self):
163 """return the log text""" 164 return self.tb.GetValue()
165 166 167 ### 168 ### Dialog asking what you want to sync 169 ### 170
171 -class GetPhoneDialog(wx.Dialog):
172 # sync sources ("Pretty Name", "name used to query profile") 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 # actions ("Pretty Name", "name used to query profile") 185 actions = ( ("Get", "read"), ) 186 187 NOTREQUESTED=0 188 MERGE=1 189 OVERWRITE=2 190 191 # type of action ("pretty name", "name used to query profile") 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
251 - def _setting(self, sourcetype):
252 _w=self._widgets[sourcetype] 253 if not _w['cb'].GetValue(): 254 # Not selected 255 return self.NOTREQUESTED 256 for _typeval,_rb in _w['rb'].items(): 257 if _rb.GetValue(): 258 return _typeval 259 # should not get here 260 raise ValueError
261
262 - def GetPhoneBookSetting(self):
263 return self._setting("phonebook")
264
265 - def GetCalendarSetting(self):
266 return self._setting("calendar")
267
268 - def GetWallpaperSetting(self):
269 return self._setting("wallpaper")
270
271 - def GetRingtoneSetting(self):
272 return self._setting("ringtone")
273
274 - def GetMemoSetting(self):
275 return self._setting("memo")
276
277 - def GetTodoSetting(self):
278 return self._setting("todo")
279
280 - def GetSMSSetting(self):
281 return self._setting("sms")
282 - def GetCallHistorySetting(self):
283 return self._setting("call_history")
284 - def GetPlaylistSetting(self):
285 return self._setting('playlist')
286 - def GetT9Setting(self):
287 return self._setting('t9_udb')
288
289 - def OnHelp(self,_):
290 wx.GetApp().displayhelpid(self.HELPID)
291 292 # this is what BitPim itself supports - the phones may support a subset 293 _notsupported=( 294 # ('phonebook', 'read', MERGE), # sort of is 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
303 - def _dowesupport(self, source, action, type):
304 if (source,action,type) in self._notsupported: 305 return False 306 return True
307
308 - def UpdateWithProfile(self, profile):
309 assert len(self.types)==2 310 _action=self.actions[0][1] 311 for source,_w in self._widgets.items(): 312 _cb=_w['cb'] 313 _cb.Enable(False) 314 # are any radio buttons enabled 315 _rb_on=False 316 for _type,_rb in _w['rb'].items(): 317 if self._dowesupport(source, _action, _type) and \ 318 profile.SyncQuery(source, _action, self.typename[_type]): 319 _cb.Enable(True) 320 _cb.exclusive=profile.SyncQuery(source, _action, 'EXCLUSIVE') 321 _rb.Enable(True) 322 _rb_on|=bool(_rb.GetValue()) 323 else: 324 _rb.SetValue(False) 325 _rb.Enable(False) 326 if _cb.IsEnabled(): 327 # make sure at least one radio button is set 328 if not _rb_on: 329 for _rb in _w['rb'].values(): 330 if _rb.IsEnabled(): 331 _rb.SetValue(True) 332 break 333 else: 334 # uncheck of not enabled 335 _cb.SetValue(False)
336
337 - def ShowModal(self):
338 # we ensure the OK button is in the correct state 339 self.DoOkStatus() 340 return wx.Dialog.ShowModal(self)
341
342 - def _check_for_exclusive(self, w):
343 if w.exclusive: 344 # this one is exclusive, turn off all others 345 for _w in self._widgets.values(): 346 if _w['cb'] is not w: 347 _w['cb'].SetValue(False) 348 else: 349 # this one is not exclusive, turn off all exclusive ones 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
355 - def OnOptionSelected(self, evt):
356 # User clicked on an option 357 # Turn on the row to which this option belongs 358 _rb=evt.GetEventObject() 359 for _w1 in self._widgets.values(): 360 if _rb in _w1['rb'].values(): 361 _w1['cb'].SetValue(True) 362 # and turn on the OK button 363 self.DoOkStatus() 364 return
365
366 - def DoOkStatus(self, evt=None):
367 # ensure the OK button is in the right state 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
381 -class SendPhoneDialog(GetPhoneDialog):
382 HELPID=helpids.ID_SEND_PHONE_DATA 383 384 # actions ("Pretty Name", "name used to query profile") 385 actions = ( ("Send", "write"), ) 386
387 - def __init__(self, frame, title, id=-1):
388 GetPhoneDialog.__init__(self, frame, title, id)
389 390 # this is what BitPim itself doesn't supports - the phones may support less 391 _notsupported=( 392 ('call_history', 'write', None),)
393 394 395 ### 396 ### The master config dialog 397 ### 398
399 -class ConfigDialog(wx.Dialog):
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 # safemode 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 # where we store our files 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 # phone type 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 # com port 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 # com timeout 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 # Automatic check for update 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 # always start with the 'Today' tab 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 # whether or not to use TaskBarIcon 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 # whether or not to run autodetect at startup 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 # Splashscreen time 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 # Developer's Console 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 # bitfling 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 # crud at the bottom 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 # Retrieve saved settings... (we only care about position) 555 set_size("ConfigDialog", self, screenpct=-1, aspect=3.5) 556 557 wx.EVT_CLOSE(self, self.OnClose)
558
559 - def OnCancel(self, _):
560 self.saveSize()
561
562 - def OnOK(self, _):
563 self.saveSize() 564 self.EndModal(wx.ID_OK) 565 self.ApplyBitFlingSettings()
566
567 - def OnHelp(self, _):
569
570 - def OnComBrowse(self, _):
571 self.saveSize() 572 if self.mw.wt is not None: 573 self.mw.wt.clearcomm() 574 # remember its size 575 # w=self.mw.config.ReadInt("combrowsewidth", 640) 576 # h=self.mw.config.ReadInt("combrowseheight", 480) 577 p=self.mw.config.ReadInt("combrowsesash", 200) 578 with guihelper.WXDialogWrapper(CommPortDialog(self, common.importas(phones.module(self.phonebox.GetValue())), defaultport=self.commbox.GetValue(), sashposition=p), 579 True) as (dlg, res): 580 self.mw.config.WriteInt("combrowsesash", dlg.sashposition) 581 if res==wx.ID_OK: 582 self.commbox.SetValue(dlg.GetPort())
583
584 - def ApplyBitFlingSettings(self, _=None):
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
595 - def OnBitFlingSettings(self, _):
596 with guihelper.WXDialogWrapper(BitFlingSettingsDialog(None, self.mw.config), 597 True) as (dlg, retcode): 598 if retcode==wx.ID_OK: 599 dlg.SaveSettings() 600 self.ApplyBitFlingSettings() 601 if self.mw.config.Read("bitfling/password","<unconfigured>") \ 602 != "<unconfigured>": 603 self.bitflingenabled.Enable(True)
604
606 "Setup all the voodoo needed for certificate verification to happen, not matter which thread wants it" 607 EVT_BITFLINGCERTIFICATEVERIFICATION(self, self._wrapVerifyBitFlingCert) 608 bitflingscan.flinger.SetCertVerifier(self.dispatchVerifyBitFlingCert) 609 bitflingscan.flinger.setthreadeventloop(wx.SafeYield)
610
611 - def dispatchVerifyBitFlingCert(self, addr, key):
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
632 - def _wrapVerifyBitFlingCert(self, evt):
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
641 - def VerifyBitFlingCert(self, addr, key, q):
642 print "VerifyBitFlingCert for", addr, "type",key.get_name() 643 # ::TODO:: reject if not dsa 644 # get fingerprint 645 fingerprint=common.hexify(key.get_fingerprint()) 646 # do we already know about it? 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 # throw up the dialog 654 print "asking user" 655 dlg=AcceptCertificateDialog(None, wx.GetApp().config, addr, fingerprint, q) 656 dlg.ShowModal()
657
658 - def OnClose(self, evt):
659 self.saveSize()