Package gui :: Module settingsDialogs
[hide private]
[frames] | no frames]

Source Code for Module gui.settingsDialogs

   1  #settingsDialogs.py 
   2  #A part of NonVisual Desktop Access (NVDA) 
   3  #Copyright (C) 2006-2007 NVDA Contributors <http://www.nvda-project.org/> 
   4  #This file is covered by the GNU General Public License. 
   5  #See the file COPYING for more details. 
   6   
   7  import glob 
   8  import os 
   9  import copy 
  10  import wx 
  11  import winUser 
  12  import logHandler 
  13  from synthDriverHandler import * 
  14  import config 
  15  import languageHandler 
  16  import speech 
  17  import gui 
  18  import globalVars 
  19  from logHandler import log 
  20  import nvwave 
  21  import speechDictHandler 
  22  import appModuleHandler 
  23  import queueHandler 
  24  import braille 
  25  import core 
  26  import keyboardHandler 
  27  import characterProcessing 
28 29 -class SettingsDialog(wx.Dialog):
30 """A settings dialog. 31 A settings dialog consists of one or more settings controls and OK and Cancel buttons. 32 Action may be taken in response to the OK or Cancel buttons. 33 34 To use this dialog: 35 * Set L{title} to the title of the dialog. 36 * Override L{makeSettings} to populate a given sizer with the settings controls. 37 * Optionally, override L{postInit} to perform actions after the dialog is created, such as setting the focus. 38 * Optionally, extend one or both of L{onOk} or L{onCancel} to perform actions in response to the OK or Cancel buttons, respectively. 39 40 @ivar title: The title of the dialog. 41 @type title: str 42 """ 43
44 - class MultiInstanceError(RuntimeError): pass
45 46 _hasInstance=False 47 48 title = "" 49
50 - def __new__(cls, *args, **kwargs):
51 if SettingsDialog._hasInstance: 52 raise SettingsDialog.MultiInstanceError("Only one instance of SettingsDialog can exist at a time") 53 obj = super(SettingsDialog, cls).__new__(cls, *args, **kwargs) 54 SettingsDialog._hasInstance=True 55 return obj
56
57 - def __init__(self, parent):
58 """ 59 @param parent: The parent for this dialog; C{None} for no parent. 60 @type parent: wx.Window 61 """ 62 super(SettingsDialog, self).__init__(parent, wx.ID_ANY, self.title) 63 mainSizer=wx.BoxSizer(wx.VERTICAL) 64 self.settingsSizer=wx.BoxSizer(wx.VERTICAL) 65 self.makeSettings(self.settingsSizer) 66 mainSizer.Add(self.settingsSizer,border=20,flag=wx.LEFT|wx.RIGHT|wx.TOP) 67 buttonSizer=self.CreateButtonSizer(wx.OK|wx.CANCEL) 68 mainSizer.Add(buttonSizer,border=20,flag=wx.LEFT|wx.RIGHT|wx.BOTTOM) 69 mainSizer.Fit(self) 70 self.SetSizer(mainSizer) 71 self.Bind(wx.EVT_BUTTON,self.onOk,id=wx.ID_OK) 72 self.Bind(wx.EVT_BUTTON,self.onCancel,id=wx.ID_CANCEL) 73 self.postInit()
74
75 - def __del__(self):
77
78 - def makeSettings(self, sizer):
79 """Populate the dialog with settings controls. 80 Subclasses must override this method. 81 @param sizer: The sizer to which to add the settings controls. 82 @type sizer: wx.Sizer 83 """ 84 raise NotImplementedError
85
86 - def postInit(self):
87 """Called after the dialog has been created. 88 For example, this might be used to set focus to the desired control. 89 Sub-classes may override this method. 90 """
91
92 - def onOk(self, evt):
93 """Take action in response to the OK button being pressed. 94 Sub-classes may extend this method. 95 This base method should always be called to clean up the dialog. 96 """ 97 self.Destroy()
98
99 - def onCancel(self, evt):
100 """Take action in response to the Cancel button being pressed. 101 Sub-classes may extend this method. 102 This base method should always be called to clean up the dialog. 103 """ 104 self.Destroy()
105
106 -class GeneralSettingsDialog(SettingsDialog):
107 title = _("General settings") 108 LOG_LEVELS = ( 109 (log.INFO, _("info")), 110 (log.DEBUGWARNING, _("debug warning")), 111 (log.IO, _("input/output")), 112 (log.DEBUG, _("debug")) 113 ) 114
115 - def makeSettings(self, settingsSizer):
116 languageSizer=wx.BoxSizer(wx.HORIZONTAL) 117 languageLabel=wx.StaticText(self,-1,label=_("&Language (requires restart to fully take affect):")) 118 languageSizer.Add(languageLabel) 119 languageListID=wx.NewId() 120 self.languageNames=languageHandler.getAvailableLanguages() 121 self.languageList=wx.Choice(self,languageListID,name=_("Language"),choices=[x[1] for x in self.languageNames]) 122 self.languageList.SetToolTip(wx.ToolTip("Choose the language NVDA's messages and user interface should be presented in.")) 123 try: 124 self.oldLanguage=config.conf["general"]["language"] 125 index=[x[0] for x in self.languageNames].index(self.oldLanguage) 126 self.languageList.SetSelection(index) 127 except: 128 pass 129 languageSizer.Add(self.languageList) 130 if globalVars.appArgs.secure: 131 self.languageList.Disable() 132 settingsSizer.Add(languageSizer,border=10,flag=wx.BOTTOM) 133 self.saveOnExitCheckBox=wx.CheckBox(self,wx.NewId(),label=_("&Save configuration on exit")) 134 self.saveOnExitCheckBox.SetValue(config.conf["general"]["saveConfigurationOnExit"]) 135 if globalVars.appArgs.secure: 136 self.saveOnExitCheckBox.Disable() 137 settingsSizer.Add(self.saveOnExitCheckBox,border=10,flag=wx.BOTTOM) 138 self.askToExitCheckBox=wx.CheckBox(self,wx.NewId(),label=_("&Warn before exiting NVDA")) 139 self.askToExitCheckBox.SetValue(config.conf["general"]["askToExit"]) 140 settingsSizer.Add(self.askToExitCheckBox,border=10,flag=wx.BOTTOM) 141 logLevelSizer=wx.BoxSizer(wx.HORIZONTAL) 142 logLevelLabel=wx.StaticText(self,-1,label=_("L&ogging level:")) 143 logLevelSizer.Add(logLevelLabel) 144 logLevelListID=wx.NewId() 145 self.logLevelList=wx.Choice(self,logLevelListID,name=_("Log level"),choices=[name for level, name in self.LOG_LEVELS]) 146 curLevel = log.getEffectiveLevel() 147 for index, (level, name) in enumerate(self.LOG_LEVELS): 148 if level == curLevel: 149 self.logLevelList.SetSelection(index) 150 break 151 else: 152 log.debugWarning("Could not set log level list to current log level") 153 logLevelSizer.Add(self.logLevelList) 154 settingsSizer.Add(logLevelSizer,border=10,flag=wx.BOTTOM) 155 self.startAfterLogonCheckBox = wx.CheckBox(self, wx.ID_ANY, label=_("&Automatically start NVDA after I log on to Windows")) 156 self.startAfterLogonCheckBox.SetValue(config.getStartAfterLogon()) 157 if globalVars.appArgs.secure or not config.isInstalledCopy(): 158 self.startAfterLogonCheckBox.Disable() 159 settingsSizer.Add(self.startAfterLogonCheckBox) 160 self.startOnLogonScreenCheckBox = wx.CheckBox(self, wx.ID_ANY, label=_("Use NVDA on the Windows logon screen (requires administrator privileges)")) 161 self.startOnLogonScreenCheckBox.SetValue(config.getStartOnLogonScreen()) 162 if globalVars.appArgs.secure or not config.isServiceInstalled(): 163 self.startOnLogonScreenCheckBox.Disable() 164 settingsSizer.Add(self.startOnLogonScreenCheckBox) 165 self.copySettingsButton= wx.Button(self, wx.ID_ANY, label=_("Use currently saved settings on the logon and other secure screens (requires administrator privileges)")) 166 self.copySettingsButton.Bind(wx.EVT_BUTTON,self.onCopySettings) 167 if globalVars.appArgs.secure or not config.isServiceInstalled(): 168 self.copySettingsButton.Disable() 169 settingsSizer.Add(self.copySettingsButton)
170
171 - def postInit(self):
172 self.languageList.SetFocus()
173
174 - def onCopySettings(self,evt):
175 for packageType in ('appModules','globalPlugins','brailleDisplayDrivers','synthDrivers'): 176 if len(os.listdir(os.path.join(globalVars.appArgs.configPath,packageType)))>0: 177 if gui.messageBox( 178 _("Custom plugins were detected in your user settings directory. Copying these to the system profile could be a security risk. Do you still wish to copy your settings?"), 179 _("Warning"),wx.YES|wx.NO|wx.ICON_WARNING,self 180 )==wx.NO: 181 return 182 break 183 if not config.setSystemConfigToCurrentConfig(): 184 gui.messageBox(_("Error copying NVDA user settings"),_("Error"),wx.OK|wx.ICON_ERROR,self) 185 else: 186 gui.messageBox(_("Successfully copied NVDA user settings"),_("Success"),wx.OK|wx.ICON_INFORMATION,self)
187
188 - def onOk(self,evt):
189 newLanguage=[x[0] for x in self.languageNames][self.languageList.GetSelection()] 190 if newLanguage!=self.oldLanguage: 191 try: 192 languageHandler.setLanguage(newLanguage) 193 except: 194 log.error("languageHandler.setLanguage", exc_info=True) 195 gui.messageBox(_("Error in %s language file")%newLanguage,_("Language Error"),wx.OK|wx.ICON_WARNING,self) 196 return 197 config.conf["general"]["language"]=newLanguage 198 config.conf["general"]["saveConfigurationOnExit"]=self.saveOnExitCheckBox.IsChecked() 199 config.conf["general"]["askToExit"]=self.askToExitCheckBox.IsChecked() 200 logLevel=self.LOG_LEVELS[self.logLevelList.GetSelection()][0] 201 config.conf["general"]["loggingLevel"]=logHandler.levelNames[logLevel] 202 logHandler.setLogLevelFromConfig() 203 if self.startAfterLogonCheckBox.IsEnabled(): 204 config.setStartAfterLogon(self.startAfterLogonCheckBox.GetValue()) 205 if self.startOnLogonScreenCheckBox.IsEnabled(): 206 try: 207 config.setStartOnLogonScreen(self.startOnLogonScreenCheckBox.GetValue()) 208 except (WindowsError, RuntimeError): 209 gui.messageBox(_("This change requires administrator privileges."), _("Insufficient Privileges"), style=wx.OK | wx.ICON_ERROR, parent=self) 210 if self.oldLanguage!=newLanguage: 211 if gui.messageBox( 212 _("For the new language to take effect, the configuration must be saved and NVDA must be restarted. Press enter to save and restart NVDA, or cancel to manually save and exit at a later time."), 213 _("Language Configuration Change"),wx.OK|wx.CANCEL|wx.ICON_WARNING,self 214 )==wx.OK: 215 config.save() 216 queueHandler.queueFunction(queueHandler.eventQueue,core.restart) 217 super(GeneralSettingsDialog, self).onOk(evt)
218
219 -class SynthesizerDialog(SettingsDialog):
220 title = _("Synthesizer") 221
222 - def makeSettings(self, settingsSizer):
223 synthListSizer=wx.BoxSizer(wx.HORIZONTAL) 224 synthListLabel=wx.StaticText(self,-1,label=_("&Synthesizer:")) 225 synthListID=wx.NewId() 226 driverList=getSynthList() 227 self.synthNames=[x[0] for x in driverList] 228 options=[x[1] for x in driverList] 229 self.synthList=wx.Choice(self,synthListID,choices=options) 230 try: 231 index=self.synthNames.index(getSynth().name) 232 self.synthList.SetSelection(index) 233 except: 234 pass 235 synthListSizer.Add(synthListLabel) 236 synthListSizer.Add(self.synthList) 237 settingsSizer.Add(synthListSizer,border=10,flag=wx.BOTTOM) 238 deviceListSizer=wx.BoxSizer(wx.HORIZONTAL) 239 deviceListLabel=wx.StaticText(self,-1,label=_("Output &device:")) 240 deviceListID=wx.NewId() 241 deviceNames=nvwave.getOutputDeviceNames() 242 self.deviceList=wx.Choice(self,deviceListID,choices=deviceNames) 243 try: 244 selection = deviceNames.index(config.conf["speech"]["outputDevice"]) 245 except ValueError: 246 selection = 0 247 self.deviceList.SetSelection(selection) 248 deviceListSizer.Add(deviceListLabel) 249 deviceListSizer.Add(self.deviceList) 250 settingsSizer.Add(deviceListSizer,border=10,flag=wx.BOTTOM)
251
252 - def postInit(self):
253 self.synthList.SetFocus()
254
255 - def onOk(self,evt):
256 config.conf["speech"]["outputDevice"]=self.deviceList.GetStringSelection() 257 newSynth=self.synthNames[self.synthList.GetSelection()] 258 if not setSynth(newSynth): 259 gui.messageBox(_("Could not load the %s synthesizer.")%newSynth,_("Synthesizer Error"),wx.OK|wx.ICON_WARNING,self) 260 return 261 super(SynthesizerDialog, self).onOk(evt)
262
263 -class SynthSettingChanger(object):
264 """Functor which acts as calback for GUI events.""" 265
266 - def __init__(self,setting):
267 self.setting=setting
268
269 - def __call__(self,evt):
270 val=evt.GetSelection() 271 setattr(getSynth(),self.setting.name,val)
272
273 -class StringSynthSettingChanger(SynthSettingChanger):
274 """Same as L{SynthSettingChanger} but handles combobox events."""
275 - def __init__(self,setting,dialog):
276 self.dialog=dialog 277 super(StringSynthSettingChanger,self).__init__(setting)
278
279 - def __call__(self,evt):
280 if self.setting.name=="voice": 281 # Cancel speech first so that the voice will change immediately instead of the change being queued. 282 speech.cancelSpeech() 283 changeVoice(getSynth(),getattr(self.dialog,"_%ss"%self.setting.name)[evt.GetSelection()].ID) 284 self.dialog.updateVoiceSettings(changedSetting=self.setting.name) 285 else: 286 setattr(getSynth(),self.setting.name,getattr(self.dialog,"_%ss"%self.setting.name)[evt.GetSelection()].ID)
287
288 -class VoiceSettingsSlider(wx.Slider):
289
290 - def __init__(self,*args, **kwargs):
291 super(VoiceSettingsSlider,self).__init__(*args,**kwargs) 292 self.Bind(wx.EVT_CHAR, self.onSliderChar)
293
294 - def SetValue(self,i):
295 super(VoiceSettingsSlider, self).SetValue(i) 296 evt = wx.CommandEvent(wx.wxEVT_COMMAND_SLIDER_UPDATED,self.GetId()) 297 evt.SetInt(i) 298 self.ProcessEvent(evt) 299 # HACK: Win events don't seem to be sent for certain explicitly set values, 300 # so send our own win event. 301 # This will cause duplicates in some cases, but NVDA will filter them out. 302 winUser.user32.NotifyWinEvent(winUser.EVENT_OBJECT_VALUECHANGE,self.Handle,winUser.OBJID_CLIENT,winUser.CHILDID_SELF)
303
304 - def onSliderChar(self, evt):
305 key = evt.KeyCode 306 if key == wx.WXK_UP: 307 newValue = min(self.Value + self.LineSize, self.Max) 308 elif key == wx.WXK_DOWN: 309 newValue = max(self.Value - self.LineSize, self.Min) 310 elif key == wx.WXK_PRIOR: 311 newValue = min(self.Value + self.PageSize, self.Max) 312 elif key == wx.WXK_NEXT: 313 newValue = max(self.Value - self.PageSize, self.Min) 314 elif key == wx.WXK_HOME: 315 newValue = self.Max 316 elif key == wx.WXK_END: 317 newValue = self.Min 318 else: 319 evt.Skip() 320 return 321 self.SetValue(newValue)
322
323 -class VoiceSettingsDialog(SettingsDialog):
324 title = _("Voice settings") 325 326 @classmethod
327 - def _setSliderStepSizes(cls, slider, setting):
328 slider.SetLineSize(setting.minStep) 329 slider.SetPageSize(setting.largeStep)
330
331 - def makeSettingControl(self,setting):
332 """Constructs appropriate GUI controls for given L{SynthSetting} such as label and slider. 333 @param setting: Setting to construct controls for 334 @type setting: L{SynthSetting} 335 @returns: WXSizer containing newly created controls. 336 @rtype: L{wx.BoxSizer} 337 """ 338 sizer=wx.BoxSizer(wx.HORIZONTAL) 339 label=wx.StaticText(self,wx.ID_ANY,label="%s:"%setting.i18nName) 340 slider=VoiceSettingsSlider(self,wx.ID_ANY,minValue=0,maxValue=100,name="%s:"%setting.i18nName) 341 setattr(self,"%sSlider"%setting.name,slider) 342 slider.Bind(wx.EVT_SLIDER,SynthSettingChanger(setting)) 343 self._setSliderStepSizes(slider,setting) 344 slider.SetValue(getattr(getSynth(),setting.name)) 345 sizer.Add(label) 346 sizer.Add(slider) 347 if self.lastControl: 348 slider.MoveAfterInTabOrder(self.lastControl) 349 self.lastControl=slider 350 return sizer
351
352 - def makeStringSettingControl(self,setting):
353 """Same as L{makeSettingControl} but for string settings. Returns sizer with label and combobox.""" 354 sizer=wx.BoxSizer(wx.HORIZONTAL) 355 label=wx.StaticText(self,wx.ID_ANY,label="%s:"%setting.i18nName) 356 synth=getSynth() 357 setattr(self,"_%ss"%setting.name,getattr(synth,"available%ss"%setting.name.capitalize()).values()) 358 l=getattr(self,"_%ss"%setting.name)### 359 lCombo=wx.Choice(self,wx.ID_ANY,name="%s:"%setting.i18nName,choices=[x.name for x in l]) 360 setattr(self,"%sList"%setting.name,lCombo) 361 try: 362 cur=getattr(synth,setting.name) 363 i=[x.ID for x in l].index(cur) 364 lCombo.SetSelection(i) 365 except ValueError: 366 pass 367 lCombo.Bind(wx.EVT_CHOICE,StringSynthSettingChanger(setting,self)) 368 sizer.Add(label) 369 sizer.Add(lCombo) 370 if self.lastControl: 371 lCombo.MoveAfterInTabOrder(self.lastControl) 372 self.lastControl=lCombo 373 return sizer
374
375 - def makeBooleanSettingControl(self,setting):
376 """Same as L{makeSettingControl} but for boolean settings. Returns checkbox.""" 377 checkbox=wx.CheckBox(self,wx.ID_ANY,label=setting.i18nName) 378 setattr(self,"%sCheckbox"%setting.name,checkbox) 379 checkbox.Bind(wx.EVT_CHECKBOX, 380 lambda evt: setattr(getSynth(),setting.name,evt.IsChecked())) 381 checkbox.SetValue(getattr(getSynth(),setting.name)) 382 if self.lastControl: 383 checkbox.MoveAfterInTabOrder(self.lastControl) 384 self.lastControl=checkbox 385 return checkbox
386
387 - def makeSettings(self, settingsSizer):
388 self.sizerDict={} 389 self.lastControl=None 390 #Create controls for Synth Settings 391 self.updateVoiceSettings() 392 self.autoLanguageSwitchingCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Automatic language switching (when supported)")) 393 self.autoLanguageSwitchingCheckbox.SetValue(config.conf["speech"]["autoLanguageSwitching"]) 394 settingsSizer.Add(self.autoLanguageSwitchingCheckbox,border=10,flag=wx.BOTTOM) 395 self.autoDialectSwitchingCheckbox=wx.CheckBox(self,wx.NewId(),label=_("Automatic dialect switching (when supported)")) 396 self.autoDialectSwitchingCheckbox.SetValue(config.conf["speech"]["autoDialectSwitching"]) 397 settingsSizer.Add(self.autoDialectSwitchingCheckbox,border=10,flag=wx.BOTTOM) 398 sizer=wx.BoxSizer(wx.HORIZONTAL) 399 sizer.Add(wx.StaticText(self,wx.ID_ANY,label=_("Punctuation/symbol &level:"))) 400 symbolLevelLabels=characterProcessing.SPEECH_SYMBOL_LEVEL_LABELS 401 self.symbolLevelList=wx.Choice(self,wx.ID_ANY,choices=[symbolLevelLabels[level] for level in characterProcessing.CONFIGURABLE_SPEECH_SYMBOL_LEVELS]) 402 curLevel = config.conf["speech"]["symbolLevel"] 403 self.symbolLevelList.SetSelection(characterProcessing.CONFIGURABLE_SPEECH_SYMBOL_LEVELS.index(curLevel)) 404 sizer.Add(self.symbolLevelList) 405 settingsSizer.Add(sizer,border=10,flag=wx.BOTTOM) 406 capPitchChangeLabel=wx.StaticText(self,-1,label=_("Capital pitch change percentage")) 407 settingsSizer.Add(capPitchChangeLabel) 408 self.capPitchChangeEdit=wx.TextCtrl(self,wx.NewId()) 409 self.capPitchChangeEdit.SetValue(str(config.conf["speech"][getSynth().name]["capPitchChange"])) 410 settingsSizer.Add(self.capPitchChangeEdit,border=10,flag=wx.BOTTOM) 411 self.sayCapForCapsCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Say &cap before capitals")) 412 self.sayCapForCapsCheckBox.SetValue(config.conf["speech"][getSynth().name]["sayCapForCapitals"]) 413 settingsSizer.Add(self.sayCapForCapsCheckBox,border=10,flag=wx.BOTTOM) 414 self.beepForCapsCheckBox = wx.CheckBox(self, wx.NewId(), label = _("&Beep for capitals")) 415 self.beepForCapsCheckBox.SetValue(config.conf["speech"][getSynth().name]["beepForCapitals"]) 416 settingsSizer.Add(self.beepForCapsCheckBox,border=10,flag=wx.BOTTOM) 417 self.useSpellingFunctionalityCheckBox = wx.CheckBox(self, wx.NewId(), label = _("Use &spelling functionality if supported")) 418 self.useSpellingFunctionalityCheckBox.SetValue(config.conf["speech"][getSynth().name]["useSpellingFunctionality"]) 419 settingsSizer.Add(self.useSpellingFunctionalityCheckBox,border=10,flag=wx.BOTTOM)
420
421 - def postInit(self):
422 try: 423 setting=getSynth().supportedSettings[0] 424 control=getattr(self,"%sSlider"%setting.name) if isinstance(setting,NumericSynthSetting) else getattr(self,"%sList"%setting.name) 425 control.SetFocus() 426 except IndexError: 427 self.symbolLevelList.SetFocus()
428
429 - def updateVoiceSettings(self, changedSetting=None):
430 """Creates, hides or updates existing GUI controls for all of supported settings.""" 431 synth=getSynth() 432 #firstly check already created options 433 for name,sizer in self.sizerDict.iteritems(): 434 if name == changedSetting: 435 # Changing a setting shouldn't cause that setting itself to disappear. 436 continue 437 if not synth.isSupported(name): 438 self.settingsSizer.Hide(sizer) 439 #Create new controls, update already existing 440 for setting in synth.supportedSettings: 441 if setting.name == changedSetting: 442 # Changing a setting shouldn't cause that setting's own values to change. 443 continue 444 if setting.name in self.sizerDict: #update a value 445 self.settingsSizer.Show(self.sizerDict[setting.name]) 446 if isinstance(setting,NumericSynthSetting): 447 getattr(self,"%sSlider"%setting.name).SetValue(getattr(synth,setting.name)) 448 elif isinstance(setting,BooleanSynthSetting): 449 getattr(self,"%sCheckbox"%setting.name).SetValue(getattr(synth,setting.name)) 450 else: 451 l=getattr(self,"_%ss"%setting.name) 452 lCombo=getattr(self,"%sList"%setting.name) 453 try: 454 cur=getattr(synth,setting.name) 455 i=[x.ID for x in l].index(cur) 456 lCombo.SetSelection(i) 457 except ValueError: 458 pass 459 else: #create a new control 460 if isinstance(setting,NumericSynthSetting): 461 settingMaker=self.makeSettingControl 462 elif isinstance(setting,BooleanSynthSetting): 463 settingMaker=self.makeBooleanSettingControl 464 else: 465 settingMaker=self.makeStringSettingControl 466 s=settingMaker(setting) 467 self.sizerDict[setting.name]=s 468 self.settingsSizer.Insert(len(self.sizerDict)-1,s,border=10,flag=wx.BOTTOM) 469 #Update graphical layout of the dialog 470 self.settingsSizer.Layout()
471
472 - def onCancel(self,evt):
473 #unbind change events for string settings as wx closes combo boxes on cancel 474 for setting in getSynth().supportedSettings: 475 if isinstance(setting,(NumericSynthSetting,BooleanSynthSetting)): continue 476 getattr(self,"%sList"%setting.name).Unbind(wx.EVT_CHOICE) 477 #restore settings 478 getSynth().loadSettings() 479 super(VoiceSettingsDialog, self).onCancel(evt)
480
481 - def onOk(self,evt):
482 getSynth().saveSettings() 483 config.conf["speech"]["autoLanguageSwitching"]=self.autoLanguageSwitchingCheckbox.IsChecked() 484 config.conf["speech"]["autoDialectSwitching"]=self.autoDialectSwitchingCheckbox.IsChecked() 485 config.conf["speech"]["symbolLevel"]=characterProcessing.CONFIGURABLE_SPEECH_SYMBOL_LEVELS[self.symbolLevelList.GetSelection()] 486 capPitchChange=self.capPitchChangeEdit.Value 487 try: 488 capPitchChange=int(capPitchChange) 489 except ValueError: 490 capPitchChange=0 491 config.conf["speech"][getSynth().name]["capPitchChange"]=min(max(capPitchChange,-100),100) 492 config.conf["speech"][getSynth().name]["sayCapForCapitals"]=self.sayCapForCapsCheckBox.IsChecked() 493 config.conf["speech"][getSynth().name]["beepForCapitals"]=self.beepForCapsCheckBox.IsChecked() 494 config.conf["speech"][getSynth().name]["useSpellingFunctionality"]=self.useSpellingFunctionalityCheckBox.IsChecked() 495 super(VoiceSettingsDialog, self).onOk(evt)
496
497 -class KeyboardSettingsDialog(SettingsDialog):
498 title = _("Keyboard Settings") 499
500 - def makeSettings(self, settingsSizer):
501 kbdSizer=wx.BoxSizer(wx.HORIZONTAL) 502 kbdLabel=wx.StaticText(self,-1,label=_("&Keyboard layout:")) 503 kbdSizer.Add(kbdLabel) 504 kbdListID=wx.NewId() 505 layouts=keyboardHandler.KeyboardInputGesture.LAYOUTS 506 self.kbdNames=sorted(layouts) 507 self.kbdList=wx.Choice(self,kbdListID,name=_("Keyboard layout"),choices=[layouts[layout] for layout in self.kbdNames]) 508 try: 509 index=self.kbdNames.index(config.conf['keyboard']['keyboardLayout']) 510 self.kbdList.SetSelection(index) 511 except: 512 log.debugWarning("Could not set Keyboard layout list to current layout",exc_info=True) 513 kbdSizer.Add(self.kbdList) 514 settingsSizer.Add(kbdSizer,border=10,flag=wx.BOTTOM) 515 self.capsAsNVDAModifierCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Use CapsLock as an NVDA modifier key")) 516 self.capsAsNVDAModifierCheckBox.SetValue(config.conf["keyboard"]["useCapsLockAsNVDAModifierKey"]) 517 settingsSizer.Add(self.capsAsNVDAModifierCheckBox,border=10,flag=wx.BOTTOM) 518 self.numpadInsertAsNVDAModifierCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Use numpad Insert as an NVDA modifier key")) 519 self.numpadInsertAsNVDAModifierCheckBox.SetValue(config.conf["keyboard"]["useNumpadInsertAsNVDAModifierKey"]) 520 settingsSizer.Add(self.numpadInsertAsNVDAModifierCheckBox,border=10,flag=wx.BOTTOM) 521 self.extendedInsertAsNVDAModifierCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Use extended Insert as an NVDA modifier key")) 522 self.extendedInsertAsNVDAModifierCheckBox.SetValue(config.conf["keyboard"]["useExtendedInsertAsNVDAModifierKey"]) 523 settingsSizer.Add(self.extendedInsertAsNVDAModifierCheckBox,border=10,flag=wx.BOTTOM) 524 self.charsCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Speak typed &characters")) 525 self.charsCheckBox.SetValue(config.conf["keyboard"]["speakTypedCharacters"]) 526 settingsSizer.Add(self.charsCheckBox,border=10,flag=wx.BOTTOM) 527 self.wordsCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Speak typed &words")) 528 self.wordsCheckBox.SetValue(config.conf["keyboard"]["speakTypedWords"]) 529 settingsSizer.Add(self.wordsCheckBox,border=10,flag=wx.BOTTOM) 530 self.beepLowercaseCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Beep if typing lowercase letters when caps lock is on")) 531 self.beepLowercaseCheckBox.SetValue(config.conf["keyboard"]["beepForLowercaseWithCapslock"]) 532 settingsSizer.Add(self.beepLowercaseCheckBox,border=10,flag=wx.BOTTOM) 533 self.commandKeysCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Speak command &keys")) 534 self.commandKeysCheckBox.SetValue(config.conf["keyboard"]["speakCommandKeys"]) 535 settingsSizer.Add(self.commandKeysCheckBox,border=10,flag=wx.BOTTOM)
536
537 - def postInit(self):
538 self.kbdList.SetFocus()
539
540 - def onOk(self,evt):
541 layout=self.kbdNames[self.kbdList.GetSelection()] 542 config.conf['keyboard']['keyboardLayout']=layout 543 config.conf["keyboard"]["useCapsLockAsNVDAModifierKey"]=self.capsAsNVDAModifierCheckBox.IsChecked() 544 config.conf["keyboard"]["useNumpadInsertAsNVDAModifierKey"]=self.numpadInsertAsNVDAModifierCheckBox.IsChecked() 545 config.conf["keyboard"]["useExtendedInsertAsNVDAModifierKey"]=self.extendedInsertAsNVDAModifierCheckBox.IsChecked() 546 config.conf["keyboard"]["speakTypedCharacters"]=self.charsCheckBox.IsChecked() 547 config.conf["keyboard"]["speakTypedWords"]=self.wordsCheckBox.IsChecked() 548 config.conf["keyboard"]["beepForLowercaseWithCapslock"]=self.beepLowercaseCheckBox.IsChecked() 549 config.conf["keyboard"]["speakCommandKeys"]=self.commandKeysCheckBox.IsChecked() 550 super(KeyboardSettingsDialog, self).onOk(evt)
551
552 -class MouseSettingsDialog(SettingsDialog):
553 title = _("Mouse settings") 554
555 - def makeSettings(self, settingsSizer):
556 self.shapeCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report mouse &shape changes")) 557 self.shapeCheckBox.SetValue(config.conf["mouse"]["reportMouseShapeChanges"]) 558 settingsSizer.Add(self.shapeCheckBox,border=10,flag=wx.BOTTOM) 559 self.mouseTrackingCheckBox=wx.CheckBox(self,wx.ID_ANY,label=_("Enable mouse &tracking")) 560 self.mouseTrackingCheckBox.SetValue(config.conf["mouse"]["enableMouseTracking"]) 561 settingsSizer.Add(self.mouseTrackingCheckBox,border=10,flag=wx.BOTTOM) 562 textUnitSizer=wx.BoxSizer(wx.HORIZONTAL) 563 textUnitLabel=wx.StaticText(self,-1,label=_("Text &unit resolution:")) 564 textUnitSizer.Add(textUnitLabel) 565 import textInfos 566 self.textUnits=[textInfos.UNIT_CHARACTER,textInfos.UNIT_WORD,textInfos.UNIT_LINE,textInfos.UNIT_PARAGRAPH] 567 self.textUnitComboBox=wx.Choice(self,wx.ID_ANY,name=_("text reporting unit"),choices=[textInfos.unitLabels[x] for x in self.textUnits]) 568 try: 569 index=self.textUnits.index(config.conf["mouse"]["mouseTextUnit"]) 570 except: 571 index=0 572 self.textUnitComboBox.SetSelection(index) 573 textUnitSizer.Add(self.textUnitComboBox) 574 settingsSizer.Add(textUnitSizer,border=10,flag=wx.BOTTOM) 575 self.reportObjectRoleCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report &role when mouse enters object")) 576 self.reportObjectRoleCheckBox.SetValue(config.conf["mouse"]["reportObjectRoleOnMouseEnter"]) 577 settingsSizer.Add(self.reportObjectRoleCheckBox,border=10,flag=wx.BOTTOM) 578 self.audioCheckBox=wx.CheckBox(self,wx.NewId(),label=_("play audio coordinates when mouse moves")) 579 self.audioCheckBox.SetValue(config.conf["mouse"]["audioCoordinatesOnMouseMove"]) 580 settingsSizer.Add(self.audioCheckBox,border=10,flag=wx.BOTTOM) 581 self.audioDetectBrightnessCheckBox=wx.CheckBox(self,wx.NewId(),label=_("brightness controls audio coordinates volume")) 582 self.audioDetectBrightnessCheckBox.SetValue(config.conf["mouse"]["audioCoordinates_detectBrightness"]) 583 settingsSizer.Add(self.audioDetectBrightnessCheckBox,border=10,flag=wx.BOTTOM)
584
585 - def postInit(self):
586 self.shapeCheckBox.SetFocus()
587
588 - def onOk(self,evt):
589 config.conf["mouse"]["reportMouseShapeChanges"]=self.shapeCheckBox.IsChecked() 590 config.conf["mouse"]["enableMouseTracking"]=self.mouseTrackingCheckBox.IsChecked() 591 config.conf["mouse"]["mouseTextUnit"]=self.textUnits[self.textUnitComboBox.GetSelection()] 592 config.conf["mouse"]["reportObjectRoleOnMouseEnter"]=self.reportObjectRoleCheckBox.IsChecked() 593 config.conf["mouse"]["audioCoordinatesOnMouseMove"]=self.audioCheckBox.IsChecked() 594 config.conf["mouse"]["audioCoordinates_detectBrightness"]=self.audioDetectBrightnessCheckBox.IsChecked() 595 596 super(MouseSettingsDialog, self).onOk(evt)
597
598 -class ReviewCursorDialog(SettingsDialog):
599 title = _("Review cursor settings") 600
601 - def makeSettings(self, settingsSizer):
602 self.followFocusCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Follow &keyboard focus")) 603 self.followFocusCheckBox.SetValue(config.conf["reviewCursor"]["followFocus"]) 604 settingsSizer.Add(self.followFocusCheckBox,border=10,flag=wx.BOTTOM) 605 self.followCaretCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Follow System &Caret")) 606 self.followCaretCheckBox.SetValue(config.conf["reviewCursor"]["followCaret"]) 607 settingsSizer.Add(self.followCaretCheckBox,border=10,flag=wx.BOTTOM) 608 self.followMouseCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Follow &mouse cursor")) 609 self.followMouseCheckBox.SetValue(config.conf["reviewCursor"]["followMouse"]) 610 settingsSizer.Add(self.followMouseCheckBox,border=10,flag=wx.BOTTOM) 611 self.simpleReviewModeCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Simple review mode")) 612 self.simpleReviewModeCheckBox.SetValue(config.conf["reviewCursor"]["simpleReviewMode"]) 613 settingsSizer.Add(self.simpleReviewModeCheckBox,border=10,flag=wx.BOTTOM)
614
615 - def postInit(self):
616 self.followFocusCheckBox.SetFocus()
617
618 - def onOk(self,evt):
619 config.conf["reviewCursor"]["followFocus"]=self.followFocusCheckBox.IsChecked() 620 config.conf["reviewCursor"]["followCaret"]=self.followCaretCheckBox.IsChecked() 621 config.conf["reviewCursor"]["followMouse"]=self.followMouseCheckBox.IsChecked() 622 config.conf["reviewCursor"]["simpleReviewMode"]=self.simpleReviewModeCheckBox.IsChecked() 623 super(ReviewCursorDialog, self).onOk(evt)
624
625 -class ObjectPresentationDialog(SettingsDialog):
626 title = _("Object presentation") 627 progressLabels = ( 628 ("off", _("off")), 629 ("speak", _("Speak")), 630 ("beep", _("Beep")), 631 ("both", _("Speak and beep")), 632 ) 633
634 - def makeSettings(self, settingsSizer):
635 self.tooltipCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report &tooltips")) 636 self.tooltipCheckBox.SetValue(config.conf["presentation"]["reportTooltips"]) 637 settingsSizer.Add(self.tooltipCheckBox,border=10,flag=wx.BOTTOM) 638 self.balloonCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report &help balloons")) 639 self.balloonCheckBox.SetValue(config.conf["presentation"]["reportHelpBalloons"]) 640 settingsSizer.Add(self.balloonCheckBox,border=10,flag=wx.BOTTOM) 641 self.shortcutCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report object shortcut &keys")) 642 self.shortcutCheckBox.SetValue(config.conf["presentation"]["reportKeyboardShortcuts"]) 643 settingsSizer.Add(self.shortcutCheckBox,border=10,flag=wx.BOTTOM) 644 self.positionInfoCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report object &position information")) 645 self.positionInfoCheckBox.SetValue(config.conf["presentation"]["reportObjectPositionInformation"]) 646 settingsSizer.Add(self.positionInfoCheckBox,border=10,flag=wx.BOTTOM) 647 self.guessPositionInfoCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Guess object &position information when unavailable")) 648 self.guessPositionInfoCheckBox.SetValue(config.conf["presentation"]["guessObjectPositionInformationWhenUnavailable"]) 649 settingsSizer.Add(self.guessPositionInfoCheckBox,border=10,flag=wx.BOTTOM) 650 self.descriptionCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report object &descriptions")) 651 self.descriptionCheckBox.SetValue(config.conf["presentation"]["reportObjectDescriptions"]) 652 settingsSizer.Add(self.descriptionCheckBox,border=10,flag=wx.BOTTOM) 653 progressSizer=wx.BoxSizer(wx.HORIZONTAL) 654 progressLabel=wx.StaticText(self,-1,label=_("Progress &bar output:")) 655 progressSizer.Add(progressLabel) 656 progressListID=wx.NewId() 657 self.progressList=wx.Choice(self,progressListID,name=_("Progress bar output"),choices=[name for setting, name in self.progressLabels]) 658 for index, (setting, name) in enumerate(self.progressLabels): 659 if setting == config.conf["presentation"]["progressBarUpdates"]["progressBarOutputMode"]: 660 self.progressList.SetSelection(index) 661 break 662 else: 663 log.debugWarning("Could not set progress list to current report progress bar updates setting") 664 progressSizer.Add(self.progressList) 665 settingsSizer.Add(progressSizer,border=10,flag=wx.BOTTOM) 666 self.reportBackgroundProgressBarsCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report background progress bars")) 667 self.reportBackgroundProgressBarsCheckBox.SetValue(config.conf["presentation"]["progressBarUpdates"]["reportBackgroundProgressBars"]) 668 settingsSizer.Add(self.reportBackgroundProgressBarsCheckBox,border=10,flag=wx.BOTTOM) 669 self.dynamicContentCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report dynamic &content changes")) 670 self.dynamicContentCheckBox.SetValue(config.conf["presentation"]["reportDynamicContentChanges"]) 671 settingsSizer.Add(self.dynamicContentCheckBox,border=10,flag=wx.BOTTOM)
672
673 - def postInit(self):
674 self.tooltipCheckBox.SetFocus()
675
676 - def onOk(self,evt):
677 config.conf["presentation"]["reportTooltips"]=self.tooltipCheckBox.IsChecked() 678 config.conf["presentation"]["reportHelpBalloons"]=self.balloonCheckBox.IsChecked() 679 config.conf["presentation"]["reportKeyboardShortcuts"]=self.shortcutCheckBox.IsChecked() 680 config.conf["presentation"]["reportObjectPositionInformation"]=self.positionInfoCheckBox.IsChecked() 681 config.conf["presentation"]["guessObjectPositionInformationWhenUnavailable"]=self.guessPositionInfoCheckBox.IsChecked() 682 config.conf["presentation"]["reportObjectDescriptions"]=self.descriptionCheckBox.IsChecked() 683 config.conf["presentation"]["progressBarUpdates"]["progressBarOutputMode"]=self.progressLabels[self.progressList.GetSelection()][0] 684 config.conf["presentation"]["progressBarUpdates"]["reportBackgroundProgressBars"]=self.reportBackgroundProgressBarsCheckBox.IsChecked() 685 config.conf["presentation"]["reportDynamicContentChanges"]=self.dynamicContentCheckBox.IsChecked() 686 super(ObjectPresentationDialog, self).onOk(evt)
687
688 -class BrowseModeDialog(SettingsDialog):
689 title = _("Browse mode") 690
691 - def makeSettings(self, settingsSizer):
692 maxLengthLabel=wx.StaticText(self,-1,label=_("&Maximum number of characters on one line")) 693 settingsSizer.Add(maxLengthLabel) 694 self.maxLengthEdit=wx.TextCtrl(self,wx.NewId()) 695 self.maxLengthEdit.SetValue(str(config.conf["virtualBuffers"]["maxLineLength"])) 696 settingsSizer.Add(self.maxLengthEdit,border=10,flag=wx.BOTTOM) 697 pageLinesLabel=wx.StaticText(self,-1,label=_("&Number of lines per page")) 698 settingsSizer.Add(pageLinesLabel) 699 self.pageLinesEdit=wx.TextCtrl(self,wx.NewId()) 700 self.pageLinesEdit.SetValue(str(config.conf["virtualBuffers"]["linesPerPage"])) 701 settingsSizer.Add(self.pageLinesEdit,border=10,flag=wx.BOTTOM) 702 self.useScreenLayoutCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Use &screen layout (when supported)")) 703 self.useScreenLayoutCheckBox.SetValue(config.conf["virtualBuffers"]["useScreenLayout"]) 704 settingsSizer.Add(self.useScreenLayoutCheckBox,border=10,flag=wx.BOTTOM) 705 self.autoSayAllCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Automatic &Say All on page load")) 706 self.autoSayAllCheckBox.SetValue(config.conf["virtualBuffers"]["autoSayAllOnPageLoad"]) 707 settingsSizer.Add(self.autoSayAllCheckBox,border=10,flag=wx.BOTTOM) 708 self.layoutTablesCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report l&ayout tables")) 709 self.layoutTablesCheckBox.SetValue(config.conf["documentFormatting"]["includeLayoutTables"]) 710 settingsSizer.Add(self.layoutTablesCheckBox,border=10,flag=wx.BOTTOM) 711 712 self.autoPassThroughOnFocusChangeCheckBox=wx.CheckBox(self,wx.ID_ANY,label=_("Automatic focus mode for focus changes")) 713 self.autoPassThroughOnFocusChangeCheckBox.SetValue(config.conf["virtualBuffers"]["autoPassThroughOnFocusChange"]) 714 settingsSizer.Add(self.autoPassThroughOnFocusChangeCheckBox,border=10,flag=wx.BOTTOM) 715 self.autoPassThroughOnCaretMoveCheckBox=wx.CheckBox(self,wx.ID_ANY,label=_("Automatic focus mode for caret movement")) 716 self.autoPassThroughOnCaretMoveCheckBox.SetValue(config.conf["virtualBuffers"]["autoPassThroughOnCaretMove"]) 717 settingsSizer.Add(self.autoPassThroughOnCaretMoveCheckBox,border=10,flag=wx.BOTTOM) 718 self.passThroughAudioIndicationCheckBox=wx.CheckBox(self,wx.ID_ANY,label=_("Audio indication of focus and browse modes")) 719 self.passThroughAudioIndicationCheckBox.SetValue(config.conf["virtualBuffers"]["passThroughAudioIndication"]) 720 settingsSizer.Add(self.passThroughAudioIndicationCheckBox,border=10,flag=wx.BOTTOM)
721
722 - def postInit(self):
723 self.maxLengthEdit.SetFocus()
724
725 - def onOk(self,evt):
726 try: 727 newMaxLength=int(self.maxLengthEdit.GetValue()) 728 except: 729 newMaxLength=0 730 if newMaxLength >=10 and newMaxLength <=250: 731 config.conf["virtualBuffers"]["maxLineLength"]=newMaxLength 732 try: 733 newPageLines=int(self.pageLinesEdit.GetValue()) 734 except: 735 newPageLines=0 736 if newPageLines >=5 and newPageLines <=150: 737 config.conf["virtualBuffers"]["linesPerPage"]=newPageLines 738 config.conf["virtualBuffers"]["useScreenLayout"]=self.useScreenLayoutCheckBox.IsChecked() 739 config.conf["virtualBuffers"]["autoSayAllOnPageLoad"]=self.autoSayAllCheckBox.IsChecked() 740 config.conf["documentFormatting"]["includeLayoutTables"]=self.layoutTablesCheckBox.IsChecked() 741 config.conf["virtualBuffers"]["autoPassThroughOnFocusChange"]=self.autoPassThroughOnFocusChangeCheckBox.IsChecked() 742 config.conf["virtualBuffers"]["autoPassThroughOnCaretMove"]=self.autoPassThroughOnCaretMoveCheckBox.IsChecked() 743 config.conf["virtualBuffers"]["passThroughAudioIndication"]=self.passThroughAudioIndicationCheckBox.IsChecked() 744 super(BrowseModeDialog, self).onOk(evt)
745
746 -class DocumentFormattingDialog(SettingsDialog):
747 title = _("Document formatting") 748
749 - def makeSettings(self, settingsSizer):
750 self.detectFormatAfterCursorCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Announce formatting changes after the cursor (can cause a lag)")) 751 self.detectFormatAfterCursorCheckBox.SetValue(config.conf["documentFormatting"]["detectFormatAfterCursor"]) 752 settingsSizer.Add(self.detectFormatAfterCursorCheckBox,border=10,flag=wx.BOTTOM) 753 self.fontNameCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report font &name")) 754 self.fontNameCheckBox.SetValue(config.conf["documentFormatting"]["reportFontName"]) 755 settingsSizer.Add(self.fontNameCheckBox,border=10,flag=wx.BOTTOM) 756 self.fontSizeCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report font &size")) 757 self.fontSizeCheckBox.SetValue(config.conf["documentFormatting"]["reportFontSize"]) 758 settingsSizer.Add(self.fontSizeCheckBox,border=10,flag=wx.BOTTOM) 759 self.fontAttrsCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report font attri&butes")) 760 self.fontAttrsCheckBox.SetValue(config.conf["documentFormatting"]["reportFontAttributes"]) 761 settingsSizer.Add(self.fontAttrsCheckBox,border=10,flag=wx.BOTTOM) 762 self.alignmentCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report &alignment")) 763 self.alignmentCheckBox.SetValue(config.conf["documentFormatting"]["reportAlignment"]) 764 settingsSizer.Add(self.alignmentCheckBox,border=10,flag=wx.BOTTOM) 765 self.colorCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report &colors")) 766 self.colorCheckBox.SetValue(config.conf["documentFormatting"]["reportColor"]) 767 settingsSizer.Add(self.colorCheckBox,border=10,flag=wx.BOTTOM) 768 self.styleCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report st&yle")) 769 self.styleCheckBox.SetValue(config.conf["documentFormatting"]["reportStyle"]) 770 settingsSizer.Add(self.styleCheckBox,border=10,flag=wx.BOTTOM) 771 self.spellingErrorsCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report spelling errors")) 772 self.spellingErrorsCheckBox.SetValue(config.conf["documentFormatting"]["reportSpellingErrors"]) 773 settingsSizer.Add(self.spellingErrorsCheckBox,border=10,flag=wx.BOTTOM) 774 self.pageCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report &pages")) 775 self.pageCheckBox.SetValue(config.conf["documentFormatting"]["reportPage"]) 776 settingsSizer.Add(self.pageCheckBox,border=10,flag=wx.BOTTOM) 777 self.lineNumberCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report &line numbers")) 778 self.lineNumberCheckBox.SetValue(config.conf["documentFormatting"]["reportLineNumber"]) 779 settingsSizer.Add(self.lineNumberCheckBox,border=10,flag=wx.BOTTOM) 780 # Translators: This message is presented in the document formatting settings dialogue 781 # If this option is selected, NVDA will cound the leading spaces and tabs of a line and speak it. 782 # 783 self.lineIndentationCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report l&ine indentation")) 784 self.lineIndentationCheckBox.SetValue(config.conf["documentFormatting"]["reportLineIndentation"]) 785 settingsSizer.Add(self.lineIndentationCheckBox,border=10,flag=wx.BOTTOM) 786 self.tablesCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report &tables")) 787 self.tablesCheckBox.SetValue(config.conf["documentFormatting"]["reportTables"]) 788 settingsSizer.Add(self.tablesCheckBox,border=10,flag=wx.BOTTOM) 789 self.tableHeadersCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report table row/column h&eaders")) 790 self.tableHeadersCheckBox.SetValue(config.conf["documentFormatting"]["reportTableHeaders"]) 791 settingsSizer.Add(self.tableHeadersCheckBox,border=10,flag=wx.BOTTOM) 792 self.tableCellCoordsCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report table cell c&oordinates")) 793 self.tableCellCoordsCheckBox.SetValue(config.conf["documentFormatting"]["reportTableCellCoords"]) 794 settingsSizer.Add(self.tableCellCoordsCheckBox,border=10,flag=wx.BOTTOM) 795 self.linksCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report &links")) 796 self.linksCheckBox.SetValue(config.conf["documentFormatting"]["reportLinks"]) 797 settingsSizer.Add(self.linksCheckBox,border=10,flag=wx.BOTTOM) 798 self.headingsCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report &headings")) 799 self.headingsCheckBox.SetValue(config.conf["documentFormatting"]["reportHeadings"]) 800 settingsSizer.Add(self.headingsCheckBox,border=10,flag=wx.BOTTOM) 801 self.listsCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report l&ists")) 802 self.listsCheckBox.SetValue(config.conf["documentFormatting"]["reportLists"]) 803 settingsSizer.Add(self.listsCheckBox,border=10,flag=wx.BOTTOM) 804 self.blockQuotesCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report block &quotes")) 805 self.blockQuotesCheckBox.SetValue(config.conf["documentFormatting"]["reportBlockQuotes"]) 806 settingsSizer.Add(self.blockQuotesCheckBox,border=10,flag=wx.BOTTOM) 807 self.landmarksCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Report lan&dmarks")) 808 self.landmarksCheckBox.SetValue(config.conf["documentFormatting"]["reportLandmarks"]) 809 settingsSizer.Add(self.landmarksCheckBox,border=10,flag=wx.BOTTOM)
810
811 - def postInit(self):
812 self.detectFormatAfterCursorCheckBox.SetFocus()
813
814 - def onOk(self,evt):
815 config.conf["documentFormatting"]["detectFormatAfterCursor"]=self.detectFormatAfterCursorCheckBox.IsChecked() 816 config.conf["documentFormatting"]["reportFontName"]=self.fontNameCheckBox.IsChecked() 817 config.conf["documentFormatting"]["reportFontSize"]=self.fontSizeCheckBox.IsChecked() 818 config.conf["documentFormatting"]["reportFontAttributes"]=self.fontAttrsCheckBox.IsChecked() 819 config.conf["documentFormatting"]["reportColor"]=self.colorCheckBox.IsChecked() 820 config.conf["documentFormatting"]["reportAlignment"]=self.alignmentCheckBox.IsChecked() 821 config.conf["documentFormatting"]["reportStyle"]=self.styleCheckBox.IsChecked() 822 config.conf["documentFormatting"]["reportSpellingErrors"]=self.spellingErrorsCheckBox.IsChecked() 823 config.conf["documentFormatting"]["reportPage"]=self.pageCheckBox.IsChecked() 824 config.conf["documentFormatting"]["reportLineNumber"]=self.lineNumberCheckBox.IsChecked() 825 config.conf["documentFormatting"]["reportLineIndentation"]=self.lineIndentationCheckBox.IsChecked() 826 config.conf["documentFormatting"]["reportTables"]=self.tablesCheckBox.IsChecked() 827 config.conf["documentFormatting"]["reportTableHeaders"]=self.tableHeadersCheckBox.IsChecked() 828 config.conf["documentFormatting"]["reportTableCellCoords"]=self.tableCellCoordsCheckBox.IsChecked() 829 config.conf["documentFormatting"]["reportLinks"]=self.linksCheckBox.IsChecked() 830 config.conf["documentFormatting"]["reportHeadings"]=self.headingsCheckBox.IsChecked() 831 config.conf["documentFormatting"]["reportLists"]=self.listsCheckBox.IsChecked() 832 config.conf["documentFormatting"]["reportBlockQuotes"]=self.blockQuotesCheckBox.IsChecked() 833 config.conf["documentFormatting"]["reportLandmarks"]=self.landmarksCheckBox.IsChecked() 834 super(DocumentFormattingDialog, self).onOk(evt)
835
836 -class DictionaryEntryDialog(wx.Dialog):
837
838 - def __init__(self,parent,title=_("Edit dictionary entry")):
839 super(DictionaryEntryDialog,self).__init__(parent,title=title) 840 mainSizer=wx.BoxSizer(wx.VERTICAL) 841 settingsSizer=wx.BoxSizer(wx.VERTICAL) 842 settingsSizer.Add(wx.StaticText(self,-1,label=_("&Pattern"))) 843 self.patternTextCtrl=wx.TextCtrl(self,wx.NewId()) 844 settingsSizer.Add(self.patternTextCtrl) 845 settingsSizer.Add(wx.StaticText(self,-1,label=_("&Replacement"))) 846 self.replacementTextCtrl=wx.TextCtrl(self,wx.NewId()) 847 settingsSizer.Add(self.replacementTextCtrl) 848 settingsSizer.Add(wx.StaticText(self,-1,label=_("&Comment"))) 849 self.commentTextCtrl=wx.TextCtrl(self,wx.NewId()) 850 settingsSizer.Add(self.commentTextCtrl) 851 self.caseSensitiveCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Case &sensitive")) 852 settingsSizer.Add(self.caseSensitiveCheckBox) 853 self.regexpCheckBox=wx.CheckBox(self,wx.NewId(),label=_("Regular &expression")) 854 settingsSizer.Add(self.regexpCheckBox) 855 mainSizer.Add(settingsSizer,border=20,flag=wx.LEFT|wx.RIGHT|wx.TOP) 856 buttonSizer=self.CreateButtonSizer(wx.OK|wx.CANCEL) 857 mainSizer.Add(buttonSizer,border=20,flag=wx.LEFT|wx.RIGHT|wx.BOTTOM) 858 mainSizer.Fit(self) 859 self.SetSizer(mainSizer) 860 self.patternTextCtrl.SetFocus()
861
862 -class DictionaryDialog(SettingsDialog):
863
864 - def __init__(self,parent,title,speechDict):
865 self.title = title 866 self.speechDict = speechDict 867 self.tempSpeechDict=speechDictHandler.SpeechDict() 868 self.tempSpeechDict.extend(self.speechDict) 869 globalVars.speechDictionaryProcessing=False 870 super(DictionaryDialog, self).__init__(parent)
871
872 - def makeSettings(self, settingsSizer):
873 dictListID=wx.NewId() 874 entriesSizer=wx.BoxSizer(wx.VERTICAL) 875 entriesLabel=wx.StaticText(self,-1,label=_("&Dictionary entries")) 876 entriesSizer.Add(entriesLabel) 877 self.dictList=wx.ListCtrl(self,dictListID,style=wx.LC_REPORT|wx.LC_SINGLE_SEL,size=(550,350)) 878 self.dictList.InsertColumn(0,_("Comment"),width=150) 879 self.dictList.InsertColumn(1,_("Pattern"),width=150) 880 self.dictList.InsertColumn(2,_("Replacement"),width=150) 881 self.dictList.InsertColumn(3,_("case"),width=50) 882 self.dictList.InsertColumn(4,_("Regexp"),width=50) 883 self.offOn = (_("off"),_("on")) 884 for entry in self.tempSpeechDict: 885 self.dictList.Append((entry.comment,entry.pattern,entry.replacement,self.offOn[int(entry.caseSensitive)],self.offOn[int(entry.regexp)])) 886 self.editingIndex=-1 887 entriesSizer.Add(self.dictList,proportion=8) 888 settingsSizer.Add(entriesSizer) 889 entryButtonsSizer=wx.BoxSizer(wx.HORIZONTAL) 890 addButtonID=wx.NewId() 891 addButton=wx.Button(self,addButtonID,_("&Add"),wx.DefaultPosition) 892 entryButtonsSizer.Add(addButton) 893 editButtonID=wx.NewId() 894 editButton=wx.Button(self,editButtonID,_("&Edit"),wx.DefaultPosition) 895 entryButtonsSizer.Add(editButton) 896 removeButtonID=wx.NewId() 897 removeButton=wx.Button(self,removeButtonID,_("&Remove"),wx.DefaultPosition) 898 entryButtonsSizer.Add(removeButton) 899 self.Bind(wx.EVT_BUTTON,self.OnAddClick,id=addButtonID) 900 self.Bind(wx.EVT_BUTTON,self.OnEditClick,id=editButtonID) 901 self.Bind(wx.EVT_BUTTON,self.OnRemoveClick,id=removeButtonID) 902 settingsSizer.Add(entryButtonsSizer)
903
904 - def postInit(self):
905 self.dictList.SetFocus()
906
907 - def onCancel(self,evt):
910
911 - def onOk(self,evt):
912 globalVars.speechDictionaryProcessing=True 913 if self.tempSpeechDict!=self.speechDict: 914 del self.speechDict[:] 915 self.speechDict.extend(self.tempSpeechDict) 916 self.speechDict.save() 917 super(DictionaryDialog, self).onOk(evt)
918
919 - def OnAddClick(self,evt):
920 entryDialog=DictionaryEntryDialog(self,title=_("Add Dictionary Entry")) 921 if entryDialog.ShowModal()==wx.ID_OK: 922 self.tempSpeechDict.append(speechDictHandler.SpeechDictEntry(entryDialog.patternTextCtrl.GetValue(),entryDialog.replacementTextCtrl.GetValue(),entryDialog.commentTextCtrl.GetValue(),bool(entryDialog.caseSensitiveCheckBox.GetValue()),bool(entryDialog.regexpCheckBox.GetValue()))) 923 self.dictList.Append((entryDialog.commentTextCtrl.GetValue(),entryDialog.patternTextCtrl.GetValue(),entryDialog.replacementTextCtrl.GetValue(),self.offOn[int(entryDialog.caseSensitiveCheckBox.GetValue())],self.offOn[int(entryDialog.regexpCheckBox.GetValue())])) 924 index=self.dictList.GetFirstSelected() 925 while index>=0: 926 self.dictList.Select(index,on=0) 927 index=self.dictList.GetNextSelected(index) 928 addedIndex=self.dictList.GetItemCount()-1 929 self.dictList.Select(addedIndex) 930 self.dictList.Focus(addedIndex) 931 self.dictList.SetFocus() 932 entryDialog.Destroy()
933
934 - def OnEditClick(self,evt):
935 if self.dictList.GetSelectedItemCount()!=1: 936 return 937 editIndex=self.dictList.GetFirstSelected() 938 if editIndex<0: 939 return 940 entryDialog=DictionaryEntryDialog(self) 941 entryDialog.patternTextCtrl.SetValue(self.tempSpeechDict[editIndex].pattern) 942 entryDialog.replacementTextCtrl.SetValue(self.tempSpeechDict[editIndex].replacement) 943 entryDialog.commentTextCtrl.SetValue(self.tempSpeechDict[editIndex].comment) 944 entryDialog.caseSensitiveCheckBox.SetValue(self.tempSpeechDict[editIndex].caseSensitive) 945 entryDialog.regexpCheckBox.SetValue(self.tempSpeechDict[editIndex].regexp) 946 if entryDialog.ShowModal()==wx.ID_OK: 947 self.tempSpeechDict[editIndex]=speechDictHandler.SpeechDictEntry(entryDialog.patternTextCtrl.GetValue(),entryDialog.replacementTextCtrl.GetValue(),entryDialog.commentTextCtrl.GetValue(),bool(entryDialog.caseSensitiveCheckBox.GetValue()),bool(entryDialog.regexpCheckBox.GetValue())) 948 self.dictList.SetStringItem(editIndex,0,entryDialog.commentTextCtrl.GetValue()) 949 self.dictList.SetStringItem(editIndex,1,entryDialog.patternTextCtrl.GetValue()) 950 self.dictList.SetStringItem(editIndex,2,entryDialog.replacementTextCtrl.GetValue()) 951 self.dictList.SetStringItem(editIndex,3,self.offOn[int(entryDialog.caseSensitiveCheckBox.GetValue())]) 952 self.dictList.SetStringItem(editIndex,4,self.offOn[int(entryDialog.regexpCheckBox.GetValue())]) 953 self.dictList.SetFocus() 954 entryDialog.Destroy()
955
956 - def OnRemoveClick(self,evt):
957 index=self.dictList.GetFirstSelected() 958 while index>=0: 959 self.dictList.DeleteItem(index) 960 del self.tempSpeechDict[index] 961 index=self.dictList.GetNextSelected(index) 962 self.dictList.SetFocus()
963
964 -class BrailleSettingsDialog(SettingsDialog):
965 title = _("Braille Settings") 966
967 - def makeSettings(self, settingsSizer):
968 sizer = wx.BoxSizer(wx.HORIZONTAL) 969 label = wx.StaticText(self, wx.ID_ANY, label=_("Braille &display:")) 970 driverList = braille.getDisplayList() 971 self.displayNames = [driver[0] for driver in driverList] 972 self.displayList = wx.Choice(self, wx.ID_ANY, choices=[driver[1] for driver in driverList]) 973 try: 974 selection = self.displayNames.index(braille.handler.display.name) 975 self.displayList.SetSelection(selection) 976 except: 977 pass 978 sizer.Add(label) 979 sizer.Add(self.displayList) 980 settingsSizer.Add(sizer, border=10, flag=wx.BOTTOM) 981 982 sizer = wx.BoxSizer(wx.HORIZONTAL) 983 label = wx.StaticText(self, wx.ID_ANY, label=_("Translation &table:")) 984 self.tableNames = [table[0] for table in braille.TABLES] 985 self.tableList = wx.Choice(self, wx.ID_ANY, choices=[table[1] for table in braille.TABLES]) 986 try: 987 selection = self.tableNames.index(config.conf["braille"]["translationTable"]) 988 self.tableList.SetSelection(selection) 989 except: 990 pass 991 sizer.Add(label) 992 sizer.Add(self.tableList) 993 settingsSizer.Add(sizer, border=10, flag=wx.BOTTOM) 994 995 self.expandAtCursorCheckBox = wx.CheckBox(self, wx.ID_ANY, label=_("E&xpand to computer braille for the word at the cursor")) 996 self.expandAtCursorCheckBox.SetValue(config.conf["braille"]["expandAtCursor"]) 997 settingsSizer.Add(self.expandAtCursorCheckBox, border=10, flag=wx.BOTTOM) 998 999 sizer = wx.BoxSizer(wx.HORIZONTAL) 1000 label = wx.StaticText(self, wx.ID_ANY, label=_("Cursor blink rate (ms)")) 1001 sizer.Add(label) 1002 self.cursorBlinkRateEdit = wx.TextCtrl(self, wx.ID_ANY) 1003 self.cursorBlinkRateEdit.SetValue(str(config.conf["braille"]["cursorBlinkRate"])) 1004 sizer.Add(self.cursorBlinkRateEdit) 1005 settingsSizer.Add(sizer, border=10, flag=wx.BOTTOM) 1006 1007 sizer = wx.BoxSizer(wx.HORIZONTAL) 1008 label = wx.StaticText(self, wx.ID_ANY, label=_("Message timeout (sec)")) 1009 sizer.Add(label) 1010 self.messageTimeoutEdit = wx.TextCtrl(self, wx.ID_ANY) 1011 self.messageTimeoutEdit.SetValue(str(config.conf["braille"]["messageTimeout"])) 1012 sizer.Add(self.messageTimeoutEdit) 1013 settingsSizer.Add(sizer, border=10, flag=wx.BOTTOM) 1014 1015 sizer = wx.BoxSizer(wx.HORIZONTAL) 1016 label = wx.StaticText(self, wx.ID_ANY, label=_("Braille tethered to:")) 1017 self.tetherValues=[("focus",_("focus")),("review",_("review"))] 1018 self.tetherList = wx.Choice(self, wx.ID_ANY, choices=[x[1] for x in self.tetherValues]) 1019 tetherConfig=braille.handler.tether 1020 selection = (x for x,y in enumerate(self.tetherValues) if y[0]==tetherConfig).next() 1021 try: 1022 self.tetherList.SetSelection(selection) 1023 except: 1024 pass 1025 sizer.Add(label) 1026 sizer.Add(self.tetherList) 1027 settingsSizer.Add(sizer, border=10, flag=wx.BOTTOM)
1028
1029 - def postInit(self):
1030 self.displayList.SetFocus()
1031
1032 - def onOk(self, evt):
1033 display = self.displayNames[self.displayList.GetSelection()] 1034 if not braille.handler.setDisplayByName(display): 1035 gui.messageBox(_("Could not load the %s display.")%display, _("Braille Display Error"), wx.OK|wx.ICON_WARNING, self) 1036 return 1037 config.conf["braille"]["translationTable"] = self.tableNames[self.tableList.GetSelection()] 1038 config.conf["braille"]["expandAtCursor"] = self.expandAtCursorCheckBox.GetValue() 1039 try: 1040 val = int(self.cursorBlinkRateEdit.GetValue()) 1041 except (ValueError, TypeError): 1042 val = None 1043 if 0 <= val <= 2000: 1044 config.conf["braille"]["cursorBlinkRate"] = val 1045 try: 1046 val = int(self.messageTimeoutEdit.GetValue()) 1047 except (ValueError, TypeError): 1048 val = None 1049 if 1 <= val <= 20: 1050 config.conf["braille"]["messageTimeout"] = val 1051 braille.handler.tether = self.tetherValues[self.tetherList.GetSelection()][0] 1052 super(BrailleSettingsDialog, self).onOk(evt)
1053
1054 -class SpeechSymbolsDialog(SettingsDialog):
1055 title = _("Symbol Pronunciation") 1056
1057 - def makeSettings(self, settingsSizer):
1058 try: 1059 symbolProcessor = characterProcessing._localeSpeechSymbolProcessors.fetchLocaleData(languageHandler.getLanguage()) 1060 except LookupError: 1061 symbolProcessor = characterProcessing._localeSpeechSymbolProcessors.fetchLocaleData("en") 1062 self.symbolProcessor = symbolProcessor 1063 symbols = self.symbols = [copy.copy(symbol) for symbol in self.symbolProcessor.computedSymbols.itervalues()] 1064 1065 sizer = wx.BoxSizer(wx.HORIZONTAL) 1066 sizer.Add(wx.StaticText(self, wx.ID_ANY, _("&Symbols"))) 1067 self.symbolsList = wx.ListCtrl(self, wx.ID_ANY, style=wx.LC_REPORT | wx.LC_SINGLE_SEL, size=(360, 350)) 1068 self.symbolsList.InsertColumn(0, _("Symbol"), width=150) 1069 self.symbolsList.InsertColumn(1, _("Replacement"), width=150) 1070 self.symbolsList.InsertColumn(2, _("Level"), width=60) 1071 for symbol in symbols: 1072 item = self.symbolsList.Append((symbol.displayName,)) 1073 self.updateListItem(item, symbol) 1074 self.symbolsList.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.onListItemFocused) 1075 self.symbolsList.Bind(wx.EVT_CHAR, self.onListChar) 1076 sizer.Add(self.symbolsList) 1077 settingsSizer.Add(sizer) 1078 1079 changeSizer = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, _("Change symbol")), wx.VERTICAL) 1080 sizer = wx.BoxSizer(wx.HORIZONTAL) 1081 sizer.Add(wx.StaticText(self, wx.ID_ANY, _("&Replacement"))) 1082 self.replacementEdit = wx.TextCtrl(self, wx.ID_ANY) 1083 self.replacementEdit.Bind(wx.EVT_KILL_FOCUS, self.onSymbolEdited) 1084 sizer.Add(self.replacementEdit) 1085 changeSizer.Add(sizer) 1086 sizer = wx.BoxSizer(wx.HORIZONTAL) 1087 sizer.Add(wx.StaticText(self, wx.ID_ANY, _("&Level"))) 1088 symbolLevelLabels = characterProcessing.SPEECH_SYMBOL_LEVEL_LABELS 1089 self.levelList = wx.Choice(self, wx.ID_ANY,choices=[ 1090 symbolLevelLabels[level] for level in characterProcessing.SPEECH_SYMBOL_LEVELS]) 1091 self.levelList.Bind(wx.EVT_KILL_FOCUS, self.onSymbolEdited) 1092 sizer.Add(self.levelList) 1093 changeSizer.Add(sizer) 1094 settingsSizer.Add(changeSizer) 1095 1096 self.editingItem = None
1097
1098 - def postInit(self):
1099 self.symbolsList.SetFocus()
1100
1101 - def updateListItem(self, item, symbol):
1102 self.symbolsList.SetStringItem(item, 1, symbol.replacement) 1103 self.symbolsList.SetStringItem(item, 2, characterProcessing.SPEECH_SYMBOL_LEVEL_LABELS[symbol.level])
1104
1105 - def onSymbolEdited(self, evt):
1106 if self.editingItem is None: 1107 return 1108 # Update the symbol the user was just editing. 1109 item = self.editingItem 1110 symbol = self.symbols[item] 1111 symbol.replacement = self.replacementEdit.Value 1112 symbol.level = characterProcessing.SPEECH_SYMBOL_LEVELS[self.levelList.Selection] 1113 self.updateListItem(item, symbol)
1114
1115 - def onListItemFocused(self, evt):
1116 # Update the editing controls to reflect the newly selected symbol. 1117 item = evt.GetIndex() 1118 symbol = self.symbols[item] 1119 self.editingItem = item 1120 self.replacementEdit.Value = symbol.replacement 1121 self.levelList.Selection = characterProcessing.SPEECH_SYMBOL_LEVELS.index(symbol.level)
1122
1123 - def onListChar(self, evt):
1124 if evt.KeyCode == wx.WXK_RETURN: 1125 # The enter key should be propagated to the dialog and thus activate the default button, 1126 # but this is broken (wx ticket #3725). 1127 # Therefore, we must catch the enter key here. 1128 # Activate the OK button. 1129 self.ProcessEvent(wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, wx.ID_OK)) 1130 1131 else: 1132 evt.Skip()
1133
1134 - def onOk(self, evt):
1135 self.onSymbolEdited(None) 1136 self.editingItem = None 1137 for symbol in self.symbols: 1138 self.symbolProcessor.updateSymbol(symbol) 1139 try: 1140 self.symbolProcessor.userSymbols.save() 1141 except IOError as e: 1142 log.error("Error saving user symbols info: %s" % e) 1143 characterProcessing._localeSpeechSymbolProcessors.invalidateLocaleData(self.symbolProcessor.locale) 1144 super(SpeechSymbolsDialog, self).onOk(evt)
1145