1# Orca 2# 3# Copyright 2005-2009 Sun Microsystems Inc. 4# 5# This library is free software; you can redistribute it and/or 6# modify it under the terms of the GNU Lesser General Public 7# License as published by the Free Software Foundation; either 8# version 2.1 of the License, or (at your option) any later version. 9# 10# This library is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13# Lesser General Public License for more details. 14# 15# You should have received a copy of the GNU Lesser General Public 16# License along with this library; if not, write to the 17# Free Software Foundation, Inc., Franklin Street, Fifth Floor, 18# Boston MA 02110-1301 USA. 19 20"""Displays a GUI for the user to set Orca preferences.""" 21 22__id__ = "$Id$" 23__version__ = "$Revision$" 24__date__ = "$Date$" 25__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc." 26__license__ = "LGPL" 27 28import os 29from gi.repository import Gdk 30from gi.repository import GLib 31from gi.repository import Gtk 32from gi.repository import GObject 33from gi.repository import Pango 34import pyatspi 35import time 36 37from . import acss 38from . import debug 39from . import guilabels 40from . import messages 41from . import orca 42from . import orca_gtkbuilder 43from . import orca_gui_profile 44from . import orca_state 45from . import orca_platform 46from . import settings 47from . import settings_manager 48from . import input_event 49from . import keybindings 50from . import pronunciation_dict 51from . import braille 52from . import speech 53from . import speechserver 54from . import text_attribute_names 55 56_settingsManager = settings_manager.getManager() 57 58try: 59 import louis 60except ImportError: 61 louis = None 62from .orca_platform import tablesdir 63if louis and not tablesdir: 64 louis = None 65 66(HANDLER, DESCRIP, MOD_MASK1, MOD_USED1, KEY1, CLICK_COUNT1, OLDTEXT1, \ 67 TEXT1, MODIF, EDITABLE) = list(range(10)) 68 69(NAME, IS_SPOKEN, IS_BRAILLED, VALUE) = list(range(4)) 70 71(ACTUAL, REPLACEMENT) = list(range(2)) 72 73# Must match the order of voice types in the GtkBuilder file. 74# 75(DEFAULT, UPPERCASE, HYPERLINK, SYSTEM) = list(range(4)) 76 77# Must match the order that the timeFormatCombo is populated. 78# 79(TIME_FORMAT_LOCALE, TIME_FORMAT_12_HM, TIME_FORMAT_12_HMS, TIME_FORMAT_24_HMS, 80 TIME_FORMAT_24_HMS_WITH_WORDS, TIME_FORMAT_24_HM, 81 TIME_FORMAT_24_HM_WITH_WORDS) = list(range(7)) 82 83# Must match the order that the dateFormatCombo is populated. 84# 85(DATE_FORMAT_LOCALE, DATE_FORMAT_NUMBERS_DM, DATE_FORMAT_NUMBERS_MD, 86 DATE_FORMAT_NUMBERS_DMY, DATE_FORMAT_NUMBERS_MDY, DATE_FORMAT_NUMBERS_YMD, 87 DATE_FORMAT_FULL_DM, DATE_FORMAT_FULL_MD, DATE_FORMAT_FULL_DMY, 88 DATE_FORMAT_FULL_MDY, DATE_FORMAT_FULL_YMD, DATE_FORMAT_ABBREVIATED_DM, 89 DATE_FORMAT_ABBREVIATED_MD, DATE_FORMAT_ABBREVIATED_DMY, 90 DATE_FORMAT_ABBREVIATED_MDY, DATE_FORMAT_ABBREVIATED_YMD) = list(range(16)) 91 92class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper): 93 94 def __init__(self, fileName, windowName, prefsDict): 95 """Initialize the Orca configuration GUI. 96 97 Arguments: 98 - fileName: name of the GtkBuilder file. 99 - windowName: name of the component to get from the GtkBuilder file. 100 - prefsDict: dictionary of preferences to use during initialization 101 """ 102 103 orca_gtkbuilder.GtkBuilderWrapper.__init__(self, fileName, windowName) 104 self.prefsDict = prefsDict 105 106 self._defaultProfile = ['Default', 'default'] 107 108 # Initialize variables to None to keep pylint happy. 109 # 110 self.bbindings = None 111 self.cellRendererText = None 112 self.defaultVoice = None 113 self.disableKeyGrabPref = None 114 self.getTextAttributesView = None 115 self.hyperlinkVoice = None 116 self.initializingSpeech = None 117 self.kbindings = None 118 self.keyBindingsModel = None 119 self.keyBindView = None 120 self.newBinding = None 121 self.pendingKeyBindings = None 122 self.planeCellRendererText = None 123 self.pronunciationModel = None 124 self.pronunciationView = None 125 self.screenHeight = None 126 self.screenWidth = None 127 self.speechFamiliesChoice = None 128 self.speechFamiliesChoices = None 129 self.speechFamiliesModel = None 130 self.speechLanguagesChoice = None 131 self.speechLanguagesChoices = None 132 self.speechLanguagesModel = None 133 self.speechFamilies = [] 134 self.speechServersChoice = None 135 self.speechServersChoices = None 136 self.speechServersModel = None 137 self.speechSystemsChoice = None 138 self.speechSystemsChoices = None 139 self.speechSystemsModel = None 140 self.systemVoice = None 141 self.uppercaseVoice = None 142 self.window = None 143 self.workingFactories = None 144 self.savedGain = None 145 self.savedPitch = None 146 self.savedRate = None 147 self._isInitialSetup = False 148 self.selectedFamilyChoices = {} 149 self.selectedLanguageChoices = {} 150 self.profilesCombo = None 151 self.profilesComboModel = None 152 self.startingProfileCombo = None 153 self._capturedKey = [] 154 self.script = None 155 156 def init(self, script): 157 """Initialize the Orca configuration GUI. Read the users current 158 set of preferences and set the GUI state to match. Setup speech 159 support and populate the combo box lists on the Speech Tab pane 160 accordingly. 161 """ 162 163 self.script = script 164 165 # Restore the default rate/pitch/gain, 166 # in case the user played with the sliders. 167 # 168 try: 169 voices = _settingsManager.getSetting('voices') 170 defaultVoice = voices[settings.DEFAULT_VOICE] 171 except KeyError: 172 defaultVoice = {} 173 try: 174 self.savedGain = defaultVoice[acss.ACSS.GAIN] 175 except KeyError: 176 self.savedGain = 10.0 177 try: 178 self.savedPitch = defaultVoice[acss.ACSS.AVERAGE_PITCH] 179 except KeyError: 180 self.savedPitch = 5.0 181 try: 182 self.savedRate = defaultVoice[acss.ACSS.RATE] 183 except KeyError: 184 self.savedRate = 50.0 185 186 # ***** Key Bindings treeview initialization ***** 187 188 self.keyBindView = self.get_widget("keyBindingsTreeview") 189 190 if self.keyBindView.get_columns(): 191 for column in self.keyBindView.get_columns(): 192 self.keyBindView.remove_column(column) 193 194 self.keyBindingsModel = Gtk.TreeStore( 195 GObject.TYPE_STRING, # Handler name 196 GObject.TYPE_STRING, # Human Readable Description 197 GObject.TYPE_STRING, # Modifier mask 1 198 GObject.TYPE_STRING, # Used Modifiers 1 199 GObject.TYPE_STRING, # Modifier key name 1 200 GObject.TYPE_STRING, # Click count 1 201 GObject.TYPE_STRING, # Original Text of the Key Binding Shown 1 202 GObject.TYPE_STRING, # Text of the Key Binding Shown 1 203 GObject.TYPE_BOOLEAN, # Key Modified by User 204 GObject.TYPE_BOOLEAN) # Row with fields editable or not 205 206 self.planeCellRendererText = Gtk.CellRendererText() 207 208 self.cellRendererText = Gtk.CellRendererText() 209 self.cellRendererText.set_property("ellipsize", Pango.EllipsizeMode.END) 210 211 # HANDLER - invisble column 212 # 213 column = Gtk.TreeViewColumn("Handler", 214 self.planeCellRendererText, 215 text=HANDLER) 216 column.set_resizable(True) 217 column.set_visible(False) 218 column.set_sort_column_id(HANDLER) 219 self.keyBindView.append_column(column) 220 221 # DESCRIP 222 # 223 column = Gtk.TreeViewColumn(guilabels.KB_HEADER_FUNCTION, 224 self.cellRendererText, 225 text=DESCRIP) 226 column.set_resizable(True) 227 column.set_min_width(380) 228 column.set_sort_column_id(DESCRIP) 229 self.keyBindView.append_column(column) 230 231 # MOD_MASK1 - invisble column 232 # 233 column = Gtk.TreeViewColumn("Mod.Mask 1", 234 self.planeCellRendererText, 235 text=MOD_MASK1) 236 column.set_visible(False) 237 column.set_resizable(True) 238 column.set_sort_column_id(MOD_MASK1) 239 self.keyBindView.append_column(column) 240 241 # MOD_USED1 - invisble column 242 # 243 column = Gtk.TreeViewColumn("Use Mod.1", 244 self.planeCellRendererText, 245 text=MOD_USED1) 246 column.set_visible(False) 247 column.set_resizable(True) 248 column.set_sort_column_id(MOD_USED1) 249 self.keyBindView.append_column(column) 250 251 # KEY1 - invisble column 252 # 253 column = Gtk.TreeViewColumn("Key1", 254 self.planeCellRendererText, 255 text=KEY1) 256 column.set_resizable(True) 257 column.set_visible(False) 258 column.set_sort_column_id(KEY1) 259 self.keyBindView.append_column(column) 260 261 # CLICK_COUNT1 - invisble column 262 # 263 column = Gtk.TreeViewColumn("ClickCount1", 264 self.planeCellRendererText, 265 text=CLICK_COUNT1) 266 column.set_resizable(True) 267 column.set_visible(False) 268 column.set_sort_column_id(CLICK_COUNT1) 269 self.keyBindView.append_column(column) 270 271 # OLDTEXT1 - invisble column which will store a copy of the 272 # original keybinding in TEXT1 prior to the Apply or OK 273 # buttons being pressed. This will prevent automatic 274 # resorting each time a cell is edited. 275 # 276 column = Gtk.TreeViewColumn("OldText1", 277 self.planeCellRendererText, 278 text=OLDTEXT1) 279 column.set_resizable(True) 280 column.set_visible(False) 281 column.set_sort_column_id(OLDTEXT1) 282 self.keyBindView.append_column(column) 283 284 # TEXT1 285 # 286 rendererText = Gtk.CellRendererText() 287 rendererText.connect("editing-started", 288 self.editingKey, 289 self.keyBindingsModel) 290 rendererText.connect("editing-canceled", 291 self.editingCanceledKey) 292 rendererText.connect('edited', 293 self.editedKey, 294 self.keyBindingsModel, 295 MOD_MASK1, MOD_USED1, KEY1, CLICK_COUNT1, TEXT1) 296 297 column = Gtk.TreeViewColumn(guilabels.KB_HEADER_KEY_BINDING, 298 rendererText, 299 text=TEXT1, 300 editable=EDITABLE) 301 302 column.set_resizable(True) 303 column.set_sort_column_id(OLDTEXT1) 304 self.keyBindView.append_column(column) 305 306 # MODIF 307 # 308 rendererToggle = Gtk.CellRendererToggle() 309 rendererToggle.connect('toggled', 310 self.keyModifiedToggle, 311 self.keyBindingsModel, 312 MODIF) 313 column = Gtk.TreeViewColumn(guilabels.KB_MODIFIED, 314 rendererToggle, 315 active=MODIF, 316 activatable=EDITABLE) 317 #column.set_visible(False) 318 column.set_resizable(True) 319 column.set_sort_column_id(MODIF) 320 self.keyBindView.append_column(column) 321 322 # EDITABLE - invisble column 323 # 324 rendererToggle = Gtk.CellRendererToggle() 325 rendererToggle.set_property('activatable', False) 326 column = Gtk.TreeViewColumn("Modified", 327 rendererToggle, 328 active=EDITABLE) 329 column.set_visible(False) 330 column.set_resizable(True) 331 column.set_sort_column_id(EDITABLE) 332 self.keyBindView.append_column(column) 333 334 # Populates the treeview with all the keybindings: 335 # 336 self._populateKeyBindings() 337 338 self.window = self.get_widget("orcaSetupWindow") 339 340 self._setKeyEchoItems() 341 342 self.speechSystemsModel = \ 343 self._initComboBox(self.get_widget("speechSystems")) 344 self.speechServersModel = \ 345 self._initComboBox(self.get_widget("speechServers")) 346 self.speechLanguagesModel = \ 347 self._initComboBox(self.get_widget("speechLanguages")) 348 self.speechFamiliesModel = \ 349 self._initComboBox(self.get_widget("speechFamilies")) 350 self._initSpeechState() 351 352 # TODO - JD: Will this ever be the case?? 353 self._isInitialSetup = \ 354 not os.path.exists(_settingsManager.getPrefsDir()) 355 356 appPage = self.script.getAppPreferencesGUI() 357 if appPage: 358 label = Gtk.Label(label=self.script.app.name) 359 self.get_widget("notebook").append_page(appPage, label) 360 361 self._initGUIState() 362 363 def _getACSSForVoiceType(self, voiceType): 364 """Return the ACSS value for the given voice type. 365 366 Arguments: 367 - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM 368 369 Returns the voice dictionary for the given voice type. 370 """ 371 372 if voiceType == DEFAULT: 373 voiceACSS = self.defaultVoice 374 elif voiceType == UPPERCASE: 375 voiceACSS = self.uppercaseVoice 376 elif voiceType == HYPERLINK: 377 voiceACSS = self.hyperlinkVoice 378 elif voiceType == SYSTEM: 379 voiceACSS = self.systemVoice 380 else: 381 voiceACSS = self.defaultVoice 382 383 return voiceACSS 384 385 def writeUserPreferences(self): 386 """Write out the user's generic Orca preferences. 387 """ 388 pronunciationDict = self.getModelDict(self.pronunciationModel) 389 keyBindingsDict = self.getKeyBindingsModelDict(self.keyBindingsModel) 390 self.prefsDict.update(self.script.getPreferencesFromGUI()) 391 _settingsManager.saveSettings(self.script, 392 self.prefsDict, 393 pronunciationDict, 394 keyBindingsDict) 395 396 def _getKeyValueForVoiceType(self, voiceType, key, useDefault=True): 397 """Look for the value of the given key in the voice dictionary 398 for the given voice type. 399 400 Arguments: 401 - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM 402 - key: the key to look for in the voice dictionary. 403 - useDefault: if True, and the key isn't found for the given voice 404 type, the look for it in the default voice dictionary 405 as well. 406 407 Returns the value of the given key, or None if it's not set. 408 """ 409 410 if voiceType == DEFAULT: 411 voice = self.defaultVoice 412 elif voiceType == UPPERCASE: 413 voice = self.uppercaseVoice 414 if key not in voice: 415 if not useDefault: 416 return None 417 voice = self.defaultVoice 418 elif voiceType == HYPERLINK: 419 voice = self.hyperlinkVoice 420 if key not in voice: 421 if not useDefault: 422 return None 423 voice = self.defaultVoice 424 elif voiceType == SYSTEM: 425 voice = self.systemVoice 426 if key not in voice: 427 if not useDefault: 428 return None 429 voice = self.defaultVoice 430 else: 431 voice = self.defaultVoice 432 433 if key in voice: 434 return voice[key] 435 else: 436 return None 437 438 def _getFamilyNameForVoiceType(self, voiceType): 439 """Gets the name of the voice family for the given voice type. 440 441 Arguments: 442 - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM 443 444 Returns the name of the voice family for the given voice type, 445 or None if not set. 446 """ 447 448 familyName = None 449 family = self._getKeyValueForVoiceType(voiceType, acss.ACSS.FAMILY) 450 451 if family and speechserver.VoiceFamily.NAME in family: 452 familyName = family[speechserver.VoiceFamily.NAME] 453 454 return familyName 455 456 def _setFamilyNameForVoiceType(self, voiceType, name, language, dialect, variant): 457 """Sets the name of the voice family for the given voice type. 458 459 Arguments: 460 - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM 461 - name: the name of the voice family to set. 462 - language: the locale of the voice family to set. 463 - dialect: the dialect of the voice family to set. 464 """ 465 466 family = self._getKeyValueForVoiceType(voiceType, 467 acss.ACSS.FAMILY, 468 False) 469 470 voiceACSS = self._getACSSForVoiceType(voiceType) 471 if family: 472 family[speechserver.VoiceFamily.NAME] = name 473 family[speechserver.VoiceFamily.LANG] = language 474 family[speechserver.VoiceFamily.DIALECT] = dialect 475 family[speechserver.VoiceFamily.VARIANT] = variant 476 else: 477 voiceACSS[acss.ACSS.FAMILY] = {} 478 voiceACSS[acss.ACSS.FAMILY][speechserver.VoiceFamily.NAME] = name 479 voiceACSS[acss.ACSS.FAMILY][speechserver.VoiceFamily.LANG] = language 480 voiceACSS[acss.ACSS.FAMILY][speechserver.VoiceFamily.DIALECT] = dialect 481 voiceACSS[acss.ACSS.FAMILY][speechserver.VoiceFamily.VARIANT] = variant 482 voiceACSS['established'] = True 483 484 #settings.voices[voiceType] = voiceACSS 485 486 def _getRateForVoiceType(self, voiceType): 487 """Gets the speaking rate value for the given voice type. 488 489 Arguments: 490 - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM 491 492 Returns the rate value for the given voice type, or None if 493 not set. 494 """ 495 496 return self._getKeyValueForVoiceType(voiceType, acss.ACSS.RATE) 497 498 def _setRateForVoiceType(self, voiceType, value): 499 """Sets the speaking rate value for the given voice type. 500 501 Arguments: 502 - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM 503 - value: the rate value to set. 504 """ 505 506 voiceACSS = self._getACSSForVoiceType(voiceType) 507 voiceACSS[acss.ACSS.RATE] = value 508 voiceACSS['established'] = True 509 #settings.voices[voiceType] = voiceACSS 510 511 def _getPitchForVoiceType(self, voiceType): 512 """Gets the pitch value for the given voice type. 513 514 Arguments: 515 - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM 516 517 Returns the pitch value for the given voice type, or None if 518 not set. 519 """ 520 521 return self._getKeyValueForVoiceType(voiceType, 522 acss.ACSS.AVERAGE_PITCH) 523 524 def _setPitchForVoiceType(self, voiceType, value): 525 """Sets the pitch value for the given voice type. 526 527 Arguments: 528 - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM 529 - value: the pitch value to set. 530 """ 531 532 voiceACSS = self._getACSSForVoiceType(voiceType) 533 voiceACSS[acss.ACSS.AVERAGE_PITCH] = value 534 voiceACSS['established'] = True 535 #settings.voices[voiceType] = voiceACSS 536 537 def _getVolumeForVoiceType(self, voiceType): 538 """Gets the volume (gain) value for the given voice type. 539 540 Arguments: 541 - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM 542 543 Returns the volume (gain) value for the given voice type, or 544 None if not set. 545 """ 546 547 return self._getKeyValueForVoiceType(voiceType, acss.ACSS.GAIN) 548 549 def _setVolumeForVoiceType(self, voiceType, value): 550 """Sets the volume (gain) value for the given voice type. 551 552 Arguments: 553 - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM 554 - value: the volume (gain) value to set. 555 """ 556 557 voiceACSS = self._getACSSForVoiceType(voiceType) 558 voiceACSS[acss.ACSS.GAIN] = value 559 voiceACSS['established'] = True 560 #settings.voices[voiceType] = voiceACSS 561 562 def _setVoiceSettingsForVoiceType(self, voiceType): 563 """Sets the family, rate, pitch and volume GUI components based 564 on the given voice type. 565 566 Arguments: 567 - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM 568 """ 569 570 familyName = self._getFamilyNameForVoiceType(voiceType) 571 self._setSpeechFamiliesChoice(familyName) 572 573 rate = self._getRateForVoiceType(voiceType) 574 if rate is not None: 575 self.get_widget("rateScale").set_value(rate) 576 else: 577 self.get_widget("rateScale").set_value(50.0) 578 579 pitch = self._getPitchForVoiceType(voiceType) 580 if pitch is not None: 581 self.get_widget("pitchScale").set_value(pitch) 582 else: 583 self.get_widget("pitchScale").set_value(5.0) 584 585 volume = self._getVolumeForVoiceType(voiceType) 586 if volume is not None: 587 self.get_widget("volumeScale").set_value(volume) 588 else: 589 self.get_widget("volumeScale").set_value(10.0) 590 591 def _setSpeechFamiliesChoice(self, familyName): 592 """Sets the active item in the families ("Person:") combo box 593 to the given family name. 594 595 Arguments: 596 - familyName: the family name to use to set the active combo box item. 597 """ 598 599 if len(self.speechFamilies) == 0: 600 return 601 602 languageSet = False 603 familySet = False 604 for family in self.speechFamilies: 605 name = family[speechserver.VoiceFamily.NAME] 606 if name == familyName: 607 lang = family[speechserver.VoiceFamily.LANG] 608 dialect = family[speechserver.VoiceFamily.DIALECT] 609 610 if dialect: 611 language = lang + '-' + dialect 612 else: 613 language = lang 614 615 i = 0 616 for languageChoice in self.speechLanguagesChoices: 617 if languageChoice == language: 618 self.get_widget("speechLanguages").set_active(i) 619 self.speechLanguagesChoice = self.speechLanguagesChoices[i] 620 languageSet = True 621 622 self._setupFamilies() 623 624 i = 0 625 for familyChoice in self.speechFamiliesChoices: 626 name = familyChoice[speechserver.VoiceFamily.NAME] 627 if name == familyName: 628 self.get_widget("speechFamilies").set_active(i) 629 self.speechFamiliesChoice = self.speechFamiliesChoices[i] 630 familySet = True 631 break 632 i += 1 633 634 break 635 636 i += 1 637 638 break 639 640 if not languageSet: 641 debug.println(debug.LEVEL_FINEST, 642 "Could not find speech language match for %s" \ 643 % familyName) 644 self.get_widget("speechLanguages").set_active(0) 645 self.speechLanguagesChoice = self.speechLanguagesChoices[0] 646 647 if languageSet: 648 self.selectedLanguageChoices[self.speechServersChoice] = i 649 650 if not familySet: 651 debug.println(debug.LEVEL_FINEST, 652 "Could not find speech family match for %s" \ 653 % familyName) 654 self.get_widget("speechFamilies").set_active(0) 655 self.speechFamiliesChoice = self.speechFamiliesChoices[0] 656 657 if familySet: 658 self.selectedFamilyChoices[self.speechServersChoice, 659 self.speechLanguagesChoice] = i 660 661 def _setupFamilies(self): 662 """Gets the list of voice variants for the current speech server and 663 current language. 664 If there are variants, get the information associated with 665 each voice variant and add an entry for it to the variants 666 GtkComboBox list. 667 """ 668 669 self.speechFamiliesModel.clear() 670 671 currentLanguage = self.speechLanguagesChoice 672 673 i = 0 674 self.speechFamiliesChoices = [] 675 for family in self.speechFamilies: 676 lang = family[speechserver.VoiceFamily.LANG] 677 dialect = family[speechserver.VoiceFamily.DIALECT] 678 679 if dialect: 680 language = lang + '-' + dialect 681 else: 682 language = lang 683 684 if language != currentLanguage: 685 continue 686 687 name = family[speechserver.VoiceFamily.NAME] 688 self.speechFamiliesChoices.append(family) 689 self.speechFamiliesModel.append((i, name)) 690 i += 1 691 692 if i == 0: 693 debug.println(debug.LEVEL_SEVERE, "No speech family was available for %s." % str(currentLanguage)) 694 debug.printStack(debug.LEVEL_FINEST) 695 self.speechFamiliesChoice = None 696 return 697 698 # If user manually selected a family for the current speech server 699 # this choice it's restored. In other case the first family 700 # (usually the default one) is selected 701 # 702 selectedIndex = 0 703 if (self.speechServersChoice, self.speechLanguagesChoice) \ 704 in self.selectedFamilyChoices: 705 selectedIndex = self.selectedFamilyChoices[self.speechServersChoice, 706 self.speechLanguagesChoice] 707 708 self.get_widget("speechFamilies").set_active(selectedIndex) 709 710 def _setSpeechLanguagesChoice(self, languageName): 711 """Sets the active item in the languages ("Language:") combo box 712 to the given language name. 713 714 Arguments: 715 - languageName: the language name to use to set the active combo box item. 716 """ 717 718 print("setSpeechLanguagesChoice") 719 720 if len(self.speechLanguagesChoices) == 0: 721 return 722 723 valueSet = False 724 i = 0 725 for language in self.speechLanguagesChoices: 726 if language == languageName: 727 self.get_widget("speechLanguages").set_active(i) 728 self.speechLanguagesChoice = self.speechLanguagesChoices[i] 729 valueSet = True 730 break 731 i += 1 732 733 if not valueSet: 734 debug.println(debug.LEVEL_FINEST, 735 "Could not find speech language match for %s" \ 736 % languageName) 737 self.get_widget("speechLanguages").set_active(0) 738 self.speechLanguagesChoice = self.speechLanguagesChoices[0] 739 740 if valueSet: 741 self.selectedLanguageChoices[self.speechServersChoice] = i 742 743 self._setupFamilies() 744 745 def _setupVoices(self): 746 """Gets the list of voices for the current speech server. 747 If there are families, get the information associated with 748 each voice family and add an entry for it to the families 749 GtkComboBox list. 750 """ 751 752 self.speechLanguagesModel.clear() 753 754 self.speechFamilies = self.speechServersChoice.getVoiceFamilies() 755 756 self.speechLanguagesChoices = [] 757 758 if len(self.speechFamilies) == 0: 759 debug.println(debug.LEVEL_SEVERE, "No speech voice was available.") 760 debug.printStack(debug.LEVEL_FINEST) 761 self.speechLanguagesChoice = None 762 return 763 764 done = {} 765 i = 0 766 for family in self.speechFamilies: 767 lang = family[speechserver.VoiceFamily.LANG] 768 dialect = family[speechserver.VoiceFamily.DIALECT] 769 if (lang,dialect) in done: 770 continue 771 done[lang,dialect] = True 772 773 if dialect: 774 language = lang + '-' + dialect 775 else: 776 language = lang 777 778 # TODO: get translated language name from CLDR or such 779 msg = language 780 if msg == "": 781 # Unsupported locale 782 msg = "default language" 783 784 self.speechLanguagesChoices.append(language) 785 self.speechLanguagesModel.append((i, msg)) 786 i += 1 787 788 # If user manually selected a language for the current speech server 789 # this choice it's restored. In other case the first language 790 # (usually the default one) is selected 791 # 792 selectedIndex = 0 793 if self.speechServersChoice in self.selectedLanguageChoices: 794 selectedIndex = self.selectedLanguageChoices[self.speechServersChoice] 795 796 self.get_widget("speechLanguages").set_active(selectedIndex) 797 if self.initializingSpeech: 798 self.speechLanguagesChoice = self.speechLanguagesChoices[selectedIndex] 799 800 self._setupFamilies() 801 802 # The family name will be selected as part of selecting the 803 # voice type. Whenever the families change, we'll reset the 804 # voice type selection to the first one ("Default"). 805 # 806 comboBox = self.get_widget("voiceTypesCombo") 807 types = [guilabels.SPEECH_VOICE_TYPE_DEFAULT, 808 guilabels.SPEECH_VOICE_TYPE_UPPERCASE, 809 guilabels.SPEECH_VOICE_TYPE_HYPERLINK, 810 guilabels.SPEECH_VOICE_TYPE_SYSTEM] 811 self.populateComboBox(comboBox, types) 812 comboBox.set_active(DEFAULT) 813 voiceType = comboBox.get_active() 814 self._setVoiceSettingsForVoiceType(voiceType) 815 816 def _setSpeechServersChoice(self, serverInfo): 817 """Sets the active item in the speech servers combo box to the 818 given server. 819 820 Arguments: 821 - serversChoices: the list of available speech servers. 822 - serverInfo: the speech server to use to set the active combo 823 box item. 824 """ 825 826 if len(self.speechServersChoices) == 0: 827 return 828 829 # We'll fallback to whatever we happen to be using in the event 830 # that this preference has never been set. 831 # 832 if not serverInfo: 833 serverInfo = speech.getInfo() 834 835 valueSet = False 836 i = 0 837 for server in self.speechServersChoices: 838 if serverInfo == server.getInfo(): 839 self.get_widget("speechServers").set_active(i) 840 self.speechServersChoice = server 841 valueSet = True 842 break 843 i += 1 844 845 if not valueSet: 846 debug.println(debug.LEVEL_FINEST, 847 "Could not find speech server match for %s" \ 848 % repr(serverInfo)) 849 self.get_widget("speechServers").set_active(0) 850 self.speechServersChoice = self.speechServersChoices[0] 851 852 self._setupVoices() 853 854 def _setupSpeechServers(self): 855 """Gets the list of speech servers for the current speech factory. 856 If there are servers, get the information associated with each 857 speech server and add an entry for it to the speechServers 858 GtkComboBox list. Set the current choice to be the first item. 859 """ 860 861 self.speechServersModel.clear() 862 self.speechServersChoices = \ 863 self.speechSystemsChoice.SpeechServer.getSpeechServers() 864 if len(self.speechServersChoices) == 0: 865 debug.println(debug.LEVEL_SEVERE, "Speech not available.") 866 debug.printStack(debug.LEVEL_FINEST) 867 self.speechServersChoice = None 868 self.speechLanguagesChoices = [] 869 self.speechLanguagesChoice = None 870 self.speechFamiliesChoices = [] 871 self.speechFamiliesChoice = None 872 return 873 874 i = 0 875 for server in self.speechServersChoices: 876 name = server.getInfo()[0] 877 self.speechServersModel.append((i, name)) 878 i += 1 879 880 self._setSpeechServersChoice(self.prefsDict["speechServerInfo"]) 881 882 debug.println( 883 debug.LEVEL_FINEST, 884 "orca_gui_prefs._setupSpeechServers: speechServersChoice: %s" \ 885 % self.speechServersChoice.getInfo()) 886 887 def _setSpeechSystemsChoice(self, systemName): 888 """Set the active item in the speech systems combo box to the 889 given system name. 890 891 Arguments: 892 - factoryChoices: the list of available speech factories (systems). 893 - systemName: the speech system name to use to set the active combo 894 box item. 895 """ 896 897 systemName = systemName.strip("'") 898 899 if len(self.speechSystemsChoices) == 0: 900 self.speechSystemsChoice = None 901 return 902 903 valueSet = False 904 i = 0 905 for speechSystem in self.speechSystemsChoices: 906 name = speechSystem.__name__ 907 if name.endswith(systemName): 908 self.get_widget("speechSystems").set_active(i) 909 self.speechSystemsChoice = self.speechSystemsChoices[i] 910 valueSet = True 911 break 912 i += 1 913 914 if not valueSet: 915 debug.println(debug.LEVEL_FINEST, 916 "Could not find speech system match for %s" \ 917 % systemName) 918 self.get_widget("speechSystems").set_active(0) 919 self.speechSystemsChoice = self.speechSystemsChoices[0] 920 921 self._setupSpeechServers() 922 923 def _setupSpeechSystems(self, factories): 924 """Sets up the speech systems combo box and sets the selection 925 to the preferred speech system. 926 927 Arguments: 928 -factories: the list of known speech factories (working or not) 929 """ 930 self.speechSystemsModel.clear() 931 self.workingFactories = [] 932 for factory in factories: 933 try: 934 servers = factory.SpeechServer.getSpeechServers() 935 if len(servers): 936 self.workingFactories.append(factory) 937 except: 938 debug.printException(debug.LEVEL_FINEST) 939 940 self.speechSystemsChoices = [] 941 if len(self.workingFactories) == 0: 942 debug.println(debug.LEVEL_SEVERE, "Speech not available.") 943 debug.printStack(debug.LEVEL_FINEST) 944 self.speechSystemsChoice = None 945 self.speechServersChoices = [] 946 self.speechServersChoice = None 947 self.speechLanguagesChoices = [] 948 self.speechLanguagesChoice = None 949 self.speechFamiliesChoices = [] 950 self.speechFamiliesChoice = None 951 return 952 953 i = 0 954 for workingFactory in self.workingFactories: 955 self.speechSystemsChoices.append(workingFactory) 956 name = workingFactory.SpeechServer.getFactoryName() 957 self.speechSystemsModel.append((i, name)) 958 i += 1 959 960 if self.prefsDict["speechServerFactory"]: 961 self._setSpeechSystemsChoice(self.prefsDict["speechServerFactory"]) 962 else: 963 self.speechSystemsChoice = None 964 965 debug.println( 966 debug.LEVEL_FINEST, 967 "orca_gui_prefs._setupSpeechSystems: speechSystemsChoice: %s" \ 968 % self.speechSystemsChoice) 969 970 def _initSpeechState(self): 971 """Initialize the various speech components. 972 """ 973 974 voices = self.prefsDict["voices"] 975 self.defaultVoice = acss.ACSS(voices.get(settings.DEFAULT_VOICE)) 976 self.uppercaseVoice = acss.ACSS(voices.get(settings.UPPERCASE_VOICE)) 977 self.hyperlinkVoice = acss.ACSS(voices.get(settings.HYPERLINK_VOICE)) 978 self.systemVoice = acss.ACSS(voices.get(settings.SYSTEM_VOICE)) 979 980 # Just a note on general naming pattern: 981 # 982 # * = The name of the combobox 983 # *Model = the name of the comobox model 984 # *Choices = the Orca/speech python objects 985 # *Choice = a value from *Choices 986 # 987 # Where * = speechSystems, speechServers, speechLanguages, speechFamilies 988 # 989 factories = speech.getSpeechServerFactories() 990 if len(factories) == 0 or not self.prefsDict.get('enableSpeech', True): 991 self.workingFactories = [] 992 self.speechSystemsChoice = None 993 self.speechServersChoices = [] 994 self.speechServersChoice = None 995 self.speechLanguagesChoices = [] 996 self.speechLanguagesChoice = None 997 self.speechFamiliesChoices = [] 998 self.speechFamiliesChoice = None 999 return 1000 1001 try: 1002 speech.init() 1003 except: 1004 self.workingFactories = [] 1005 self.speechSystemsChoice = None 1006 self.speechServersChoices = [] 1007 self.speechServersChoice = None 1008 self.speechLanguagesChoices = [] 1009 self.speechLanguagesChoice = None 1010 self.speechFamiliesChoices = [] 1011 self.speechFamiliesChoice = None 1012 return 1013 1014 # This cascades into systems->servers->voice_type->families... 1015 # 1016 self.initializingSpeech = True 1017 self._setupSpeechSystems(factories) 1018 self.initializingSpeech = False 1019 1020 def _setSpokenTextAttributes(self, view, setAttributes, 1021 state, moveToTop=False): 1022 """Given a set of spoken text attributes, update the model used by the 1023 text attribute tree view. 1024 1025 Arguments: 1026 - view: the text attribute tree view. 1027 - setAttributes: the list of spoken text attributes to update. 1028 - state: the state (True or False) that they all should be set to. 1029 - moveToTop: if True, move these attributes to the top of the list. 1030 """ 1031 1032 model = view.get_model() 1033 view.set_model(None) 1034 1035 [attrList, attrDict] = \ 1036 self.script.utilities.stringToKeysAndDict(setAttributes) 1037 [allAttrList, allAttrDict] = self.script.utilities.stringToKeysAndDict( 1038 _settingsManager.getSetting('allTextAttributes')) 1039 1040 for i in range(0, len(attrList)): 1041 for path in range(0, len(allAttrList)): 1042 localizedKey = text_attribute_names.getTextAttributeName( 1043 attrList[i], self.script) 1044 localizedValue = text_attribute_names.getTextAttributeName( 1045 attrDict[attrList[i]], self.script) 1046 if localizedKey == model[path][NAME]: 1047 thisIter = model.get_iter(path) 1048 model.set_value(thisIter, NAME, localizedKey) 1049 model.set_value(thisIter, IS_SPOKEN, state) 1050 model.set_value(thisIter, VALUE, localizedValue) 1051 if moveToTop: 1052 thisIter = model.get_iter(path) 1053 otherIter = model.get_iter(i) 1054 model.move_before(thisIter, otherIter) 1055 break 1056 1057 view.set_model(model) 1058 1059 def _setBrailledTextAttributes(self, view, setAttributes, state): 1060 """Given a set of brailled text attributes, update the model used 1061 by the text attribute tree view. 1062 1063 Arguments: 1064 - view: the text attribute tree view. 1065 - setAttributes: the list of brailled text attributes to update. 1066 - state: the state (True or False) that they all should be set to. 1067 """ 1068 1069 model = view.get_model() 1070 view.set_model(None) 1071 1072 [attrList, attrDict] = \ 1073 self.script.utilities.stringToKeysAndDict(setAttributes) 1074 [allAttrList, allAttrDict] = self.script.utilities.stringToKeysAndDict( 1075 _settingsManager.getSetting('allTextAttributes')) 1076 1077 for i in range(0, len(attrList)): 1078 for path in range(0, len(allAttrList)): 1079 localizedKey = text_attribute_names.getTextAttributeName( 1080 attrList[i], self.script) 1081 if localizedKey == model[path][NAME]: 1082 thisIter = model.get_iter(path) 1083 model.set_value(thisIter, IS_BRAILLED, state) 1084 break 1085 1086 view.set_model(model) 1087 1088 def _getAppNameForAttribute(self, attributeName): 1089 """Converts the given Atk attribute name into the application's 1090 equivalent. This is necessary because an application or toolkit 1091 (e.g. Gecko) might invent entirely new names for the same text 1092 attributes. 1093 1094 Arguments: 1095 - attribName: The name of the text attribute 1096 1097 Returns the application's equivalent name if found or attribName 1098 otherwise. 1099 """ 1100 1101 return self.script.utilities.getAppNameForAttribute(attributeName) 1102 1103 def _updateTextDictEntry(self): 1104 """The user has updated the text attribute list in some way. Update 1105 the "enabledSpokenTextAttributes" and "enabledBrailledTextAttributes" 1106 preference strings to reflect the current state of the corresponding 1107 text attribute lists. 1108 """ 1109 1110 model = self.getTextAttributesView.get_model() 1111 spokenAttrStr = "" 1112 brailledAttrStr = "" 1113 noRows = model.iter_n_children(None) 1114 for path in range(0, noRows): 1115 localizedKey = model[path][NAME] 1116 key = text_attribute_names.getTextAttributeKey(localizedKey) 1117 1118 # Convert the normalized, Atk attribute name back into what 1119 # the app/toolkit uses. 1120 # 1121 key = self._getAppNameForAttribute(key) 1122 1123 localizedValue = model[path][VALUE] 1124 value = text_attribute_names.getTextAttributeKey(localizedValue) 1125 1126 if model[path][IS_SPOKEN]: 1127 spokenAttrStr += key + ":" + value + "; " 1128 if model[path][IS_BRAILLED]: 1129 brailledAttrStr += key + ":" + value + "; " 1130 1131 self.prefsDict["enabledSpokenTextAttributes"] = spokenAttrStr 1132 self.prefsDict["enabledBrailledTextAttributes"] = brailledAttrStr 1133 1134 def contractedBrailleToggled(self, checkbox): 1135 grid = self.get_widget('contractionTableGrid') 1136 grid.set_sensitive(checkbox.get_active()) 1137 self.prefsDict["enableContractedBraille"] = checkbox.get_active() 1138 1139 def contractionTableComboChanged(self, combobox): 1140 model = combobox.get_model() 1141 myIter = combobox.get_active_iter() 1142 self.prefsDict["brailleContractionTable"] = model[myIter][1] 1143 1144 def flashPersistenceToggled(self, checkbox): 1145 grid = self.get_widget('flashMessageDurationGrid') 1146 grid.set_sensitive(not checkbox.get_active()) 1147 self.prefsDict["flashIsPersistent"] = checkbox.get_active() 1148 1149 def textAttributeSpokenToggled(self, cell, path, model): 1150 """The user has toggled the state of one of the text attribute 1151 checkboxes to be spoken. Update our model to reflect this, then 1152 update the "enabledSpokenTextAttributes" preference string. 1153 1154 Arguments: 1155 - cell: the cell that changed. 1156 - path: the path of that cell. 1157 - model: the model that the cell is part of. 1158 """ 1159 1160 thisIter = model.get_iter(path) 1161 model.set(thisIter, IS_SPOKEN, not model[path][IS_SPOKEN]) 1162 self._updateTextDictEntry() 1163 1164 def textAttributeBrailledToggled(self, cell, path, model): 1165 """The user has toggled the state of one of the text attribute 1166 checkboxes to be brailled. Update our model to reflect this, 1167 then update the "enabledBrailledTextAttributes" preference string. 1168 1169 Arguments: 1170 - cell: the cell that changed. 1171 - path: the path of that cell. 1172 - model: the model that the cell is part of. 1173 """ 1174 1175 thisIter = model.get_iter(path) 1176 model.set(thisIter, IS_BRAILLED, not model[path][IS_BRAILLED]) 1177 self._updateTextDictEntry() 1178 1179 def textAttrValueEdited(self, cell, path, new_text, model): 1180 """The user has edited the value of one of the text attributes. 1181 Update our model to reflect this, then update the 1182 "enabledSpokenTextAttributes" and "enabledBrailledTextAttributes" 1183 preference strings. 1184 1185 Arguments: 1186 - cell: the cell that changed. 1187 - path: the path of that cell. 1188 - new_text: the new text attribute value string. 1189 - model: the model that the cell is part of. 1190 """ 1191 1192 thisIter = model.get_iter(path) 1193 model.set(thisIter, VALUE, new_text) 1194 self._updateTextDictEntry() 1195 1196 def textAttrCursorChanged(self, widget): 1197 """Set the search column in the text attribute tree view 1198 depending upon which column the user currently has the cursor in. 1199 """ 1200 1201 [path, focusColumn] = self.getTextAttributesView.get_cursor() 1202 if focusColumn: 1203 noColumns = len(self.getTextAttributesView.get_columns()) 1204 for i in range(0, noColumns): 1205 col = self.getTextAttributesView.get_column(i) 1206 if focusColumn == col: 1207 self.getTextAttributesView.set_search_column(i) 1208 break 1209 1210 def _createTextAttributesTreeView(self): 1211 """Create the text attributes tree view. The view is the 1212 textAttributesTreeView GtkTreeView widget. The view will consist 1213 of a list containing three columns: 1214 IS_SPOKEN - a checkbox whose state indicates whether this text 1215 attribute will be spoken or not. 1216 NAME - the text attribute name. 1217 VALUE - if set, (and this attributes is enabled for speaking), 1218 then this attribute will be spoken unless it equals 1219 this value. 1220 """ 1221 1222 self.getTextAttributesView = self.get_widget("textAttributesTreeView") 1223 1224 if self.getTextAttributesView.get_columns(): 1225 for column in self.getTextAttributesView.get_columns(): 1226 self.getTextAttributesView.remove_column(column) 1227 1228 model = Gtk.ListStore(GObject.TYPE_STRING, 1229 GObject.TYPE_BOOLEAN, 1230 GObject.TYPE_BOOLEAN, 1231 GObject.TYPE_STRING) 1232 1233 # Initially setup the list store model based on the values of all 1234 # the known text attributes. 1235 # 1236 [allAttrList, allAttrDict] = self.script.utilities.stringToKeysAndDict( 1237 _settingsManager.getSetting('allTextAttributes')) 1238 for i in range(0, len(allAttrList)): 1239 thisIter = model.append() 1240 localizedKey = text_attribute_names.getTextAttributeName( 1241 allAttrList[i], self.script) 1242 localizedValue = text_attribute_names.getTextAttributeName( 1243 allAttrDict[allAttrList[i]], self.script) 1244 model.set_value(thisIter, NAME, localizedKey) 1245 model.set_value(thisIter, IS_SPOKEN, False) 1246 model.set_value(thisIter, IS_BRAILLED, False) 1247 model.set_value(thisIter, VALUE, localizedValue) 1248 1249 self.getTextAttributesView.set_model(model) 1250 1251 # Attribute Name column (NAME). 1252 column = Gtk.TreeViewColumn(guilabels.TEXT_ATTRIBUTE_NAME) 1253 column.set_min_width(250) 1254 column.set_resizable(True) 1255 renderer = Gtk.CellRendererText() 1256 column.pack_end(renderer, True) 1257 column.add_attribute(renderer, 'text', NAME) 1258 self.getTextAttributesView.insert_column(column, 0) 1259 1260 # Attribute Speak column (IS_SPOKEN). 1261 speakAttrColumnLabel = guilabels.PRESENTATION_SPEAK 1262 column = Gtk.TreeViewColumn(speakAttrColumnLabel) 1263 renderer = Gtk.CellRendererToggle() 1264 column.pack_start(renderer, False) 1265 column.add_attribute(renderer, 'active', IS_SPOKEN) 1266 renderer.connect("toggled", 1267 self.textAttributeSpokenToggled, 1268 model) 1269 self.getTextAttributesView.insert_column(column, 1) 1270 column.clicked() 1271 1272 # Attribute Mark in Braille column (IS_BRAILLED). 1273 markAttrColumnLabel = guilabels.PRESENTATION_MARK_IN_BRAILLE 1274 column = Gtk.TreeViewColumn(markAttrColumnLabel) 1275 renderer = Gtk.CellRendererToggle() 1276 column.pack_start(renderer, False) 1277 column.add_attribute(renderer, 'active', IS_BRAILLED) 1278 renderer.connect("toggled", 1279 self.textAttributeBrailledToggled, 1280 model) 1281 self.getTextAttributesView.insert_column(column, 2) 1282 column.clicked() 1283 1284 # Attribute Value column (VALUE) 1285 column = Gtk.TreeViewColumn(guilabels.PRESENTATION_PRESENT_UNLESS) 1286 renderer = Gtk.CellRendererText() 1287 renderer.set_property('editable', True) 1288 column.pack_end(renderer, True) 1289 column.add_attribute(renderer, 'text', VALUE) 1290 renderer.connect("edited", self.textAttrValueEdited, model) 1291 1292 self.getTextAttributesView.insert_column(column, 4) 1293 1294 # Check all the enabled (spoken) text attributes. 1295 # 1296 self._setSpokenTextAttributes( 1297 self.getTextAttributesView, 1298 _settingsManager.getSetting('enabledSpokenTextAttributes'), 1299 True, True) 1300 1301 # Check all the enabled (brailled) text attributes. 1302 # 1303 self._setBrailledTextAttributes( 1304 self.getTextAttributesView, 1305 _settingsManager.getSetting('enabledBrailledTextAttributes'), 1306 True) 1307 1308 # Connect a handler for when the user changes columns within the 1309 # view, so that we can adjust the search column for item lookups. 1310 # 1311 self.getTextAttributesView.connect("cursor_changed", 1312 self.textAttrCursorChanged) 1313 1314 def pronActualValueEdited(self, cell, path, new_text, model): 1315 """The user has edited the value of one of the actual strings in 1316 the pronunciation dictionary. Update our model to reflect this. 1317 1318 Arguments: 1319 - cell: the cell that changed. 1320 - path: the path of that cell. 1321 - new_text: the new pronunciation dictionary actual string. 1322 - model: the model that the cell is part of. 1323 """ 1324 1325 thisIter = model.get_iter(path) 1326 model.set(thisIter, ACTUAL, new_text) 1327 1328 def pronReplacementValueEdited(self, cell, path, new_text, model): 1329 """The user has edited the value of one of the replacement strings 1330 in the pronunciation dictionary. Update our model to reflect this. 1331 1332 Arguments: 1333 - cell: the cell that changed. 1334 - path: the path of that cell. 1335 - new_text: the new pronunciation dictionary replacement string. 1336 - model: the model that the cell is part of. 1337 """ 1338 1339 thisIter = model.get_iter(path) 1340 model.set(thisIter, REPLACEMENT, new_text) 1341 1342 def pronunciationFocusChange(self, widget, event, isFocused): 1343 """Callback for the pronunciation tree's focus-{in,out}-event signal.""" 1344 1345 _settingsManager.setSetting('usePronunciationDictionary', not isFocused) 1346 1347 def pronunciationCursorChanged(self, widget): 1348 """Set the search column in the pronunciation dictionary tree view 1349 depending upon which column the user currently has the cursor in. 1350 """ 1351 1352 [path, focusColumn] = self.pronunciationView.get_cursor() 1353 if focusColumn: 1354 noColumns = len(self.pronunciationView.get_columns()) 1355 for i in range(0, noColumns): 1356 col = self.pronunciationView.get_column(i) 1357 if focusColumn == col: 1358 self.pronunciationView.set_search_column(i) 1359 break 1360 1361 def _createPronunciationTreeView(self): 1362 """Create the pronunciation dictionary tree view. The view is the 1363 pronunciationTreeView GtkTreeView widget. The view will consist 1364 of a list containing two columns: 1365 ACTUAL - the actual text string (word). 1366 REPLACEMENT - the string that is used to pronounce that word. 1367 """ 1368 1369 self.pronunciationView = self.get_widget("pronunciationTreeView") 1370 1371 if self.pronunciationView.get_columns(): 1372 for column in self.pronunciationView.get_columns(): 1373 self.pronunciationView.remove_column(column) 1374 1375 model = Gtk.ListStore(GObject.TYPE_STRING, 1376 GObject.TYPE_STRING) 1377 1378 # Initially setup the list store model based on the values of all 1379 # existing entries in the pronunciation dictionary -- unless it's 1380 # the default script. 1381 # 1382 if not self.script.app: 1383 _profile = self.prefsDict.get('activeProfile')[1] 1384 pronDict = _settingsManager.getPronunciations(_profile) 1385 else: 1386 pronDict = pronunciation_dict.pronunciation_dict 1387 for pronKey in sorted(pronDict.keys()): 1388 thisIter = model.append() 1389 try: 1390 actual, replacement = pronDict[pronKey] 1391 except: 1392 # Try to do something sensible for the previous format of 1393 # pronunciation dictionary entries. See bug #464754 for 1394 # more details. 1395 # 1396 actual = pronKey 1397 replacement = pronDict[pronKey] 1398 model.set(thisIter, 1399 ACTUAL, actual, 1400 REPLACEMENT, replacement) 1401 1402 self.pronunciationView.set_model(model) 1403 1404 # Pronunciation Dictionary actual string (word) column (ACTUAL). 1405 column = Gtk.TreeViewColumn(guilabels.DICTIONARY_ACTUAL_STRING) 1406 column.set_min_width(250) 1407 column.set_resizable(True) 1408 renderer = Gtk.CellRendererText() 1409 renderer.set_property('editable', True) 1410 column.pack_end(renderer, True) 1411 column.add_attribute(renderer, 'text', ACTUAL) 1412 renderer.connect("edited", self.pronActualValueEdited, model) 1413 self.pronunciationView.insert_column(column, 0) 1414 1415 # Pronunciation Dictionary replacement string column (REPLACEMENT) 1416 column = Gtk.TreeViewColumn(guilabels.DICTIONARY_REPLACEMENT_STRING) 1417 renderer = Gtk.CellRendererText() 1418 renderer.set_property('editable', True) 1419 column.pack_end(renderer, True) 1420 column.add_attribute(renderer, 'text', REPLACEMENT) 1421 renderer.connect("edited", self.pronReplacementValueEdited, model) 1422 self.pronunciationView.insert_column(column, 1) 1423 1424 self.pronunciationModel = model 1425 1426 # Connect a handler for when the user changes columns within the 1427 # view, so that we can adjust the search column for item lookups. 1428 # 1429 self.pronunciationView.connect("cursor_changed", 1430 self.pronunciationCursorChanged) 1431 1432 self.pronunciationView.connect( 1433 "focus_in_event", self.pronunciationFocusChange, True) 1434 self.pronunciationView.connect( 1435 "focus_out_event", self.pronunciationFocusChange, False) 1436 1437 def _initGUIState(self): 1438 """Adjust the settings of the various components on the 1439 configuration GUI depending upon the users preferences. 1440 """ 1441 1442 prefs = self.prefsDict 1443 1444 # Speech pane. 1445 # 1446 enable = prefs["enableSpeech"] 1447 self.get_widget("speechSupportCheckButton").set_active(enable) 1448 self.get_widget("speechOptionsGrid").set_sensitive(enable) 1449 1450 enable = prefs["onlySpeakDisplayedText"] 1451 self.get_widget("onlySpeakDisplayedTextCheckButton").set_active(enable) 1452 self.get_widget("contextOptionsGrid").set_sensitive(not enable) 1453 1454 if prefs["verbalizePunctuationStyle"] == \ 1455 settings.PUNCTUATION_STYLE_NONE: 1456 self.get_widget("noneButton").set_active(True) 1457 elif prefs["verbalizePunctuationStyle"] == \ 1458 settings.PUNCTUATION_STYLE_SOME: 1459 self.get_widget("someButton").set_active(True) 1460 elif prefs["verbalizePunctuationStyle"] == \ 1461 settings.PUNCTUATION_STYLE_MOST: 1462 self.get_widget("mostButton").set_active(True) 1463 else: 1464 self.get_widget("allButton").set_active(True) 1465 1466 if prefs["speechVerbosityLevel"] == settings.VERBOSITY_LEVEL_BRIEF: 1467 self.get_widget("speechBriefButton").set_active(True) 1468 else: 1469 self.get_widget("speechVerboseButton").set_active(True) 1470 1471 self.get_widget("onlySpeakDisplayedTextCheckButton").set_active( 1472 prefs["onlySpeakDisplayedText"]) 1473 1474 self.get_widget("enableSpeechIndentationCheckButton").set_active(\ 1475 prefs["enableSpeechIndentation"]) 1476 1477 self.get_widget("speakBlankLinesCheckButton").set_active(\ 1478 prefs["speakBlankLines"]) 1479 self.get_widget("speakMultiCaseStringsAsWordsCheckButton").set_active(\ 1480 prefs["speakMultiCaseStringsAsWords"]) 1481 self.get_widget("speakNumbersAsDigitsCheckButton").set_active( 1482 prefs.get("speakNumbersAsDigits", settings.speakNumbersAsDigits)) 1483 self.get_widget("enableTutorialMessagesCheckButton").set_active(\ 1484 prefs["enableTutorialMessages"]) 1485 self.get_widget("enablePauseBreaksCheckButton").set_active(\ 1486 prefs["enablePauseBreaks"]) 1487 self.get_widget("enablePositionSpeakingCheckButton").set_active(\ 1488 prefs["enablePositionSpeaking"]) 1489 self.get_widget("enableMnemonicSpeakingCheckButton").set_active(\ 1490 prefs["enableMnemonicSpeaking"]) 1491 self.get_widget("speakMisspelledIndicatorCheckButton").set_active( 1492 prefs.get("speakMisspelledIndicator", settings.speakMisspelledIndicator)) 1493 self.get_widget("speakDescriptionCheckButton").set_active( 1494 prefs.get("speakDescription", settings.speakDescription)) 1495 self.get_widget("speakContextBlockquoteCheckButton").set_active( 1496 prefs.get("speakContextBlockquote", settings.speakContextList)) 1497 self.get_widget("speakContextLandmarkCheckButton").set_active( 1498 prefs.get("speakContextLandmark", settings.speakContextLandmark)) 1499 self.get_widget("speakContextNonLandmarkFormCheckButton").set_active( 1500 prefs.get("speakContextNonLandmarkForm", settings.speakContextNonLandmarkForm)) 1501 self.get_widget("speakContextListCheckButton").set_active( 1502 prefs.get("speakContextList", settings.speakContextList)) 1503 self.get_widget("speakContextPanelCheckButton").set_active( 1504 prefs.get("speakContextPanel", settings.speakContextPanel)) 1505 self.get_widget("speakContextTableCheckButton").set_active( 1506 prefs.get("speakContextTable", settings.speakContextTable)) 1507 1508 enable = prefs.get("messagesAreDetailed", settings.messagesAreDetailed) 1509 self.get_widget("messagesAreDetailedCheckButton").set_active(enable) 1510 1511 enable = prefs.get("useColorNames", settings.useColorNames) 1512 self.get_widget("useColorNamesCheckButton").set_active(enable) 1513 1514 enable = prefs.get("readFullRowInGUITable", settings.readFullRowInGUITable) 1515 self.get_widget("readFullRowInGUITableCheckButton").set_active(enable) 1516 1517 enable = prefs.get("readFullRowInDocumentTable", settings.readFullRowInDocumentTable) 1518 self.get_widget("readFullRowInDocumentTableCheckButton").set_active(enable) 1519 1520 enable = prefs.get("readFullRowInSpreadSheet", settings.readFullRowInSpreadSheet) 1521 self.get_widget("readFullRowInSpreadSheetCheckButton").set_active(enable) 1522 1523 style = prefs.get("capitalizationStyle", settings.capitalizationStyle) 1524 combobox = self.get_widget("capitalizationStyle") 1525 options = [guilabels.CAPITALIZATION_STYLE_NONE, 1526 guilabels.CAPITALIZATION_STYLE_ICON, 1527 guilabels.CAPITALIZATION_STYLE_SPELL] 1528 self.populateComboBox(combobox, options) 1529 if style == settings.CAPITALIZATION_STYLE_ICON: 1530 value = guilabels.CAPITALIZATION_STYLE_ICON 1531 elif style == settings.CAPITALIZATION_STYLE_SPELL: 1532 value = guilabels.CAPITALIZATION_STYLE_SPELL 1533 else: 1534 value = guilabels.CAPITALIZATION_STYLE_NONE 1535 combobox.set_active(options.index(value)) 1536 1537 combobox2 = self.get_widget("dateFormatCombo") 1538 sdtime = time.strftime 1539 ltime = time.localtime 1540 self.populateComboBox(combobox2, 1541 [sdtime(messages.DATE_FORMAT_LOCALE, ltime()), 1542 sdtime(messages.DATE_FORMAT_NUMBERS_DM, ltime()), 1543 sdtime(messages.DATE_FORMAT_NUMBERS_MD, ltime()), 1544 sdtime(messages.DATE_FORMAT_NUMBERS_DMY, ltime()), 1545 sdtime(messages.DATE_FORMAT_NUMBERS_MDY, ltime()), 1546 sdtime(messages.DATE_FORMAT_NUMBERS_YMD, ltime()), 1547 sdtime(messages.DATE_FORMAT_FULL_DM, ltime()), 1548 sdtime(messages.DATE_FORMAT_FULL_MD, ltime()), 1549 sdtime(messages.DATE_FORMAT_FULL_DMY, ltime()), 1550 sdtime(messages.DATE_FORMAT_FULL_MDY, ltime()), 1551 sdtime(messages.DATE_FORMAT_FULL_YMD, ltime()), 1552 sdtime(messages.DATE_FORMAT_ABBREVIATED_DM, ltime()), 1553 sdtime(messages.DATE_FORMAT_ABBREVIATED_MD, ltime()), 1554 sdtime(messages.DATE_FORMAT_ABBREVIATED_DMY, ltime()), 1555 sdtime(messages.DATE_FORMAT_ABBREVIATED_MDY, ltime()), 1556 sdtime(messages.DATE_FORMAT_ABBREVIATED_YMD, ltime()) 1557 ]) 1558 1559 indexdate = DATE_FORMAT_LOCALE 1560 dateFormat = self.prefsDict["presentDateFormat"] 1561 if dateFormat == messages.DATE_FORMAT_LOCALE: 1562 indexdate = DATE_FORMAT_LOCALE 1563 elif dateFormat == messages.DATE_FORMAT_NUMBERS_DM: 1564 indexdate = DATE_FORMAT_NUMBERS_DM 1565 elif dateFormat == messages.DATE_FORMAT_NUMBERS_MD: 1566 indexdate = DATE_FORMAT_NUMBERS_MD 1567 elif dateFormat == messages.DATE_FORMAT_NUMBERS_DMY: 1568 indexdate = DATE_FORMAT_NUMBERS_DMY 1569 elif dateFormat == messages.DATE_FORMAT_NUMBERS_MDY: 1570 indexdate = DATE_FORMAT_NUMBERS_MDY 1571 elif dateFormat == messages.DATE_FORMAT_NUMBERS_YMD: 1572 indexdate = DATE_FORMAT_NUMBERS_YMD 1573 elif dateFormat == messages.DATE_FORMAT_FULL_DM: 1574 indexdate = DATE_FORMAT_FULL_DM 1575 elif dateFormat == messages.DATE_FORMAT_FULL_MD: 1576 indexdate = DATE_FORMAT_FULL_MD 1577 elif dateFormat == messages.DATE_FORMAT_FULL_DMY: 1578 indexdate = DATE_FORMAT_FULL_DMY 1579 elif dateFormat == messages.DATE_FORMAT_FULL_MDY: 1580 indexdate = DATE_FORMAT_FULL_MDY 1581 elif dateFormat == messages.DATE_FORMAT_FULL_YMD: 1582 indexdate = DATE_FORMAT_FULL_YMD 1583 elif dateFormat == messages.DATE_FORMAT_ABBREVIATED_DM: 1584 indexdate = DATE_FORMAT_ABBREVIATED_DM 1585 elif dateFormat == messages.DATE_FORMAT_ABBREVIATED_MD: 1586 indexdate = DATE_FORMAT_ABBREVIATED_MD 1587 elif dateFormat == messages.DATE_FORMAT_ABBREVIATED_DMY: 1588 indexdate = DATE_FORMAT_ABBREVIATED_DMY 1589 elif dateFormat == messages.DATE_FORMAT_ABBREVIATED_MDY: 1590 indexdate = DATE_FORMAT_ABBREVIATED_MDY 1591 elif dateFormat == messages.DATE_FORMAT_ABBREVIATED_YMD: 1592 indexdate = DATE_FORMAT_ABBREVIATED_YMD 1593 combobox2.set_active (indexdate) 1594 1595 combobox3 = self.get_widget("timeFormatCombo") 1596 self.populateComboBox(combobox3, 1597 [sdtime(messages.TIME_FORMAT_LOCALE, ltime()), 1598 sdtime(messages.TIME_FORMAT_12_HM, ltime()), 1599 sdtime(messages.TIME_FORMAT_12_HMS, ltime()), 1600 sdtime(messages.TIME_FORMAT_24_HMS, ltime()), 1601 sdtime(messages.TIME_FORMAT_24_HMS_WITH_WORDS, ltime()), 1602 sdtime(messages.TIME_FORMAT_24_HM, ltime()), 1603 sdtime(messages.TIME_FORMAT_24_HM_WITH_WORDS, ltime())]) 1604 indextime = TIME_FORMAT_LOCALE 1605 timeFormat = self.prefsDict["presentTimeFormat"] 1606 if timeFormat == messages.TIME_FORMAT_LOCALE: 1607 indextime = TIME_FORMAT_LOCALE 1608 elif timeFormat == messages.TIME_FORMAT_12_HM: 1609 indextime = TIME_FORMAT_12_HM 1610 elif timeFormat == messages.TIME_FORMAT_12_HMS: 1611 indextime = TIME_FORMAT_12_HMS 1612 elif timeFormat == messages.TIME_FORMAT_24_HMS: 1613 indextime = TIME_FORMAT_24_HMS 1614 elif timeFormat == messages.TIME_FORMAT_24_HMS_WITH_WORDS: 1615 indextime = TIME_FORMAT_24_HMS_WITH_WORDS 1616 elif timeFormat == messages.TIME_FORMAT_24_HM: 1617 indextime = TIME_FORMAT_24_HM 1618 elif timeFormat == messages.TIME_FORMAT_24_HM_WITH_WORDS: 1619 indextime = TIME_FORMAT_24_HM_WITH_WORDS 1620 combobox3.set_active (indextime) 1621 1622 self.get_widget("speakProgressBarUpdatesCheckButton").set_active( 1623 prefs.get("speakProgressBarUpdates", settings.speakProgressBarUpdates)) 1624 self.get_widget("brailleProgressBarUpdatesCheckButton").set_active( 1625 prefs.get("brailleProgressBarUpdates", settings.brailleProgressBarUpdates)) 1626 self.get_widget("beepProgressBarUpdatesCheckButton").set_active( 1627 prefs.get("beepProgressBarUpdates", settings.beepProgressBarUpdates)) 1628 1629 interval = prefs["progressBarUpdateInterval"] 1630 self.get_widget("progressBarUpdateIntervalSpinButton").set_value(interval) 1631 1632 comboBox = self.get_widget("progressBarVerbosity") 1633 levels = [guilabels.PROGRESS_BAR_ALL, 1634 guilabels.PROGRESS_BAR_APPLICATION, 1635 guilabels.PROGRESS_BAR_WINDOW] 1636 self.populateComboBox(comboBox, levels) 1637 comboBox.set_active(prefs["progressBarVerbosity"]) 1638 1639 enable = prefs["enableMouseReview"] 1640 self.get_widget("enableMouseReviewCheckButton").set_active(enable) 1641 1642 # Braille pane. 1643 # 1644 self.get_widget("enableBrailleCheckButton").set_active( \ 1645 prefs["enableBraille"]) 1646 state = prefs["brailleRolenameStyle"] == \ 1647 settings.BRAILLE_ROLENAME_STYLE_SHORT 1648 self.get_widget("abbrevRolenames").set_active(state) 1649 1650 self.get_widget("disableBrailleEOLCheckButton").set_active( 1651 prefs["disableBrailleEOL"]) 1652 1653 if louis is None: 1654 self.get_widget( \ 1655 "contractedBrailleCheckButton").set_sensitive(False) 1656 else: 1657 self.get_widget("contractedBrailleCheckButton").set_active( \ 1658 prefs["enableContractedBraille"]) 1659 # Set up contraction table combo box and set it to the 1660 # currently used one. 1661 # 1662 tablesCombo = self.get_widget("contractionTableCombo") 1663 tableDict = braille.listTables() 1664 selectedTableIter = None 1665 selectedTable = prefs["brailleContractionTable"] or \ 1666 braille.getDefaultTable() 1667 if tableDict: 1668 tablesModel = Gtk.ListStore(str, str) 1669 names = sorted(tableDict.keys()) 1670 for name in names: 1671 fname = tableDict[name] 1672 it = tablesModel.append([name, fname]) 1673 if os.path.join(braille.tablesdir, fname) == \ 1674 selectedTable: 1675 selectedTableIter = it 1676 cell = self.planeCellRendererText 1677 tablesCombo.clear() 1678 tablesCombo.pack_start(cell, True) 1679 tablesCombo.add_attribute(cell, 'text', 0) 1680 tablesCombo.set_model(tablesModel) 1681 if selectedTableIter: 1682 tablesCombo.set_active_iter(selectedTableIter) 1683 else: 1684 tablesCombo.set_active(0) 1685 else: 1686 tablesCombo.set_sensitive(False) 1687 if prefs["brailleVerbosityLevel"] == settings.VERBOSITY_LEVEL_BRIEF: 1688 self.get_widget("brailleBriefButton").set_active(True) 1689 else: 1690 self.get_widget("brailleVerboseButton").set_active(True) 1691 1692 self.get_widget("enableBrailleWordWrapCheckButton").set_active( 1693 prefs.get("enableBrailleWordWrap", settings.enableBrailleWordWrap)) 1694 1695 selectionIndicator = prefs["brailleSelectorIndicator"] 1696 if selectionIndicator == settings.BRAILLE_UNDERLINE_7: 1697 self.get_widget("brailleSelection7Button").set_active(True) 1698 elif selectionIndicator == settings.BRAILLE_UNDERLINE_8: 1699 self.get_widget("brailleSelection8Button").set_active(True) 1700 elif selectionIndicator == settings.BRAILLE_UNDERLINE_BOTH: 1701 self.get_widget("brailleSelectionBothButton").set_active(True) 1702 else: 1703 self.get_widget("brailleSelectionNoneButton").set_active(True) 1704 1705 linkIndicator = prefs["brailleLinkIndicator"] 1706 if linkIndicator == settings.BRAILLE_UNDERLINE_7: 1707 self.get_widget("brailleLink7Button").set_active(True) 1708 elif linkIndicator == settings.BRAILLE_UNDERLINE_8: 1709 self.get_widget("brailleLink8Button").set_active(True) 1710 elif linkIndicator == settings.BRAILLE_UNDERLINE_BOTH: 1711 self.get_widget("brailleLinkBothButton").set_active(True) 1712 else: 1713 self.get_widget("brailleLinkNoneButton").set_active(True) 1714 1715 enable = prefs.get("enableFlashMessages", settings.enableFlashMessages) 1716 self.get_widget("enableFlashMessagesCheckButton").set_active(enable) 1717 1718 enable = prefs.get("flashIsPersistent", settings.flashIsPersistent) 1719 self.get_widget("flashIsPersistentCheckButton").set_active(enable) 1720 1721 enable = prefs.get("flashIsDetailed", settings.flashIsDetailed) 1722 self.get_widget("flashIsDetailedCheckButton").set_active(enable) 1723 1724 duration = prefs["brailleFlashTime"] 1725 self.get_widget("brailleFlashTimeSpinButton").set_value(duration / 1000) 1726 1727 # Key Echo pane. 1728 # 1729 self.get_widget("keyEchoCheckButton").set_active( \ 1730 prefs["enableKeyEcho"]) 1731 self.get_widget("enableAlphabeticKeysCheckButton").set_active( 1732 prefs.get("enableAlphabeticKeys", settings.enableAlphabeticKeys)) 1733 self.get_widget("enableNumericKeysCheckButton").set_active( 1734 prefs.get("enableNumericKeys", settings.enableNumericKeys)) 1735 self.get_widget("enablePunctuationKeysCheckButton").set_active( 1736 prefs.get("enablePunctuationKeys", settings.enablePunctuationKeys)) 1737 self.get_widget("enableSpaceCheckButton").set_active( 1738 prefs.get("enableSpace", settings.enableSpace)) 1739 self.get_widget("enableModifierKeysCheckButton").set_active( \ 1740 prefs["enableModifierKeys"]) 1741 self.get_widget("enableFunctionKeysCheckButton").set_active( \ 1742 prefs["enableFunctionKeys"]) 1743 self.get_widget("enableActionKeysCheckButton").set_active( \ 1744 prefs["enableActionKeys"]) 1745 self.get_widget("enableNavigationKeysCheckButton").set_active( \ 1746 prefs["enableNavigationKeys"]) 1747 self.get_widget("enableDiacriticalKeysCheckButton").set_active( \ 1748 prefs["enableDiacriticalKeys"]) 1749 self.get_widget("enableEchoByCharacterCheckButton").set_active( \ 1750 prefs["enableEchoByCharacter"]) 1751 self.get_widget("enableEchoByWordCheckButton").set_active( \ 1752 prefs["enableEchoByWord"]) 1753 self.get_widget("enableEchoBySentenceCheckButton").set_active( \ 1754 prefs["enableEchoBySentence"]) 1755 1756 # Text attributes pane. 1757 # 1758 self._createTextAttributesTreeView() 1759 1760 brailleIndicator = prefs["textAttributesBrailleIndicator"] 1761 if brailleIndicator == settings.BRAILLE_UNDERLINE_7: 1762 self.get_widget("textBraille7Button").set_active(True) 1763 elif brailleIndicator == settings.BRAILLE_UNDERLINE_8: 1764 self.get_widget("textBraille8Button").set_active(True) 1765 elif brailleIndicator == settings.BRAILLE_UNDERLINE_BOTH: 1766 self.get_widget("textBrailleBothButton").set_active(True) 1767 else: 1768 self.get_widget("textBrailleNoneButton").set_active(True) 1769 1770 # Pronunciation dictionary pane. 1771 # 1772 self._createPronunciationTreeView() 1773 1774 # General pane. 1775 # 1776 self.get_widget("presentToolTipsCheckButton").set_active( 1777 prefs["presentToolTips"]) 1778 1779 if prefs["keyboardLayout"] == settings.GENERAL_KEYBOARD_LAYOUT_DESKTOP: 1780 self.get_widget("generalDesktopButton").set_active(True) 1781 else: 1782 self.get_widget("generalLaptopButton").set_active(True) 1783 1784 combobox = self.get_widget("sayAllStyle") 1785 self.populateComboBox(combobox, [guilabels.SAY_ALL_STYLE_LINE, 1786 guilabels.SAY_ALL_STYLE_SENTENCE]) 1787 combobox.set_active(prefs["sayAllStyle"]) 1788 self.get_widget("rewindAndFastForwardInSayAllCheckButton").set_active( 1789 prefs.get("rewindAndFastForwardInSayAll", settings.rewindAndFastForwardInSayAll)) 1790 self.get_widget("structNavInSayAllCheckButton").set_active( 1791 prefs.get("structNavInSayAll", settings.structNavInSayAll)) 1792 self.get_widget("sayAllContextBlockquoteCheckButton").set_active( 1793 prefs.get("sayAllContextBlockquote", settings.sayAllContextBlockquote)) 1794 self.get_widget("sayAllContextLandmarkCheckButton").set_active( 1795 prefs.get("sayAllContextLandmark", settings.sayAllContextLandmark)) 1796 self.get_widget("sayAllContextNonLandmarkFormCheckButton").set_active( 1797 prefs.get("sayAllContextNonLandmarkForm", settings.sayAllContextNonLandmarkForm)) 1798 self.get_widget("sayAllContextListCheckButton").set_active( 1799 prefs.get("sayAllContextList", settings.sayAllContextList)) 1800 self.get_widget("sayAllContextPanelCheckButton").set_active( 1801 prefs.get("sayAllContextPanel", settings.sayAllContextPanel)) 1802 self.get_widget("sayAllContextTableCheckButton").set_active( 1803 prefs.get("sayAllContextTable", settings.sayAllContextTable)) 1804 1805 # Orca User Profiles 1806 # 1807 self.profilesCombo = self.get_widget('availableProfilesComboBox1') 1808 self.startingProfileCombo = self.get_widget('availableProfilesComboBox2') 1809 self.profilesComboModel = self.get_widget('model9') 1810 self.__initProfileCombo() 1811 if self.script.app: 1812 self.get_widget('profilesFrame').set_sensitive(False) 1813 1814 def __initProfileCombo(self): 1815 """Adding available profiles and setting active as the active one""" 1816 1817 availableProfiles = self.__getAvailableProfiles() 1818 self.profilesComboModel.clear() 1819 1820 if not len(availableProfiles): 1821 self.profilesComboModel.append(self._defaultProfile) 1822 else: 1823 for profile in availableProfiles: 1824 self.profilesComboModel.append(profile) 1825 1826 activeProfile = self.prefsDict.get('activeProfile') or self._defaultProfile 1827 startingProfile = self.prefsDict.get('startingProfile') or self._defaultProfile 1828 1829 activeProfileIter = self.getComboBoxIndex(self.profilesCombo, 1830 activeProfile[0]) 1831 startingProfileIter = self.getComboBoxIndex(self.startingProfileCombo, 1832 startingProfile[0]) 1833 self.profilesCombo.set_active(activeProfileIter) 1834 self.startingProfileCombo.set_active(startingProfileIter) 1835 1836 def __getAvailableProfiles(self): 1837 """Get available user profiles.""" 1838 return _settingsManager.availableProfiles() 1839 1840 def _updateOrcaModifier(self): 1841 combobox = self.get_widget("orcaModifierComboBox") 1842 keystring = ", ".join(self.prefsDict["orcaModifierKeys"]) 1843 combobox.set_active(self.getComboBoxIndex(combobox, keystring)) 1844 1845 def populateComboBox(self, combobox, items): 1846 """Populates the combobox with the items provided. 1847 1848 Arguments: 1849 - combobox: the GtkComboBox to populate 1850 - items: the list of strings with which to populate it 1851 """ 1852 1853 model = Gtk.ListStore(str) 1854 for item in items: 1855 model.append([item]) 1856 combobox.set_model(model) 1857 1858 def getComboBoxIndex(self, combobox, searchStr, col=0): 1859 """ For each of the entries in the given combo box, look for searchStr. 1860 Return the index of the entry if searchStr is found. 1861 1862 Arguments: 1863 - combobox: the GtkComboBox to search. 1864 - searchStr: the string to search for. 1865 1866 Returns the index of the first entry in combobox with searchStr, or 1867 0 if not found. 1868 """ 1869 1870 model = combobox.get_model() 1871 myiter = model.get_iter_first() 1872 for i in range(0, len(model)): 1873 name = model.get_value(myiter, col) 1874 if name == searchStr: 1875 return i 1876 myiter = model.iter_next(myiter) 1877 1878 return 0 1879 1880 def getComboBoxList(self, combobox): 1881 """Get the list of values from the active combox 1882 """ 1883 active = combobox.get_active() 1884 model = combobox.get_model() 1885 activeIter = model.get_iter(active) 1886 activeLabel = model.get_value(activeIter, 0) 1887 activeName = model.get_value(activeIter, 1) 1888 return [activeLabel, activeName] 1889 1890 def getKeyBindingsModelDict(self, model, modifiedOnly=True): 1891 modelDict = {} 1892 node = model.get_iter_first() 1893 while node: 1894 child = model.iter_children(node) 1895 while child: 1896 key, modified = model.get(child, HANDLER, MODIF) 1897 if modified or not modifiedOnly: 1898 value = [] 1899 value.append(list(model.get( 1900 child, KEY1, MOD_MASK1, MOD_USED1, CLICK_COUNT1))) 1901 modelDict[key] = value 1902 child = model.iter_next(child) 1903 node = model.iter_next(node) 1904 1905 return modelDict 1906 1907 def getModelDict(self, model): 1908 """Get the list of values from a list[str,str] model 1909 """ 1910 pronunciation_dict.pronunciation_dict = {} 1911 currentIter = model.get_iter_first() 1912 while currentIter is not None: 1913 key, value = model.get(currentIter, ACTUAL, REPLACEMENT) 1914 if key and value: 1915 pronunciation_dict.setPronunciation(key, value) 1916 currentIter = model.iter_next(currentIter) 1917 modelDict = pronunciation_dict.pronunciation_dict 1918 return modelDict 1919 1920 def showGUI(self): 1921 """Show the Orca configuration GUI window. This assumes that 1922 the GUI has already been created. 1923 """ 1924 1925 orcaSetupWindow = self.get_widget("orcaSetupWindow") 1926 1927 accelGroup = Gtk.AccelGroup() 1928 orcaSetupWindow.add_accel_group(accelGroup) 1929 helpButton = self.get_widget("helpButton") 1930 (keyVal, modifierMask) = Gtk.accelerator_parse("F1") 1931 helpButton.add_accelerator("clicked", 1932 accelGroup, 1933 keyVal, 1934 modifierMask, 1935 0) 1936 1937 try: 1938 ts = orca_state.lastInputEvent.timestamp 1939 except: 1940 ts = 0 1941 if ts == 0: 1942 ts = Gtk.get_current_event_time() 1943 orcaSetupWindow.present_with_time(ts) 1944 1945 # We always want to re-order the text attributes page so that enabled 1946 # items are consistently at the top. 1947 # 1948 self._setSpokenTextAttributes( 1949 self.getTextAttributesView, 1950 _settingsManager.getSetting('enabledSpokenTextAttributes'), 1951 True, True) 1952 1953 if self.script.app: 1954 title = guilabels.PREFERENCES_APPLICATION_TITLE % self.script.app.name 1955 orcaSetupWindow.set_title(title) 1956 1957 orcaSetupWindow.show() 1958 1959 def _initComboBox(self, combobox): 1960 """Initialize the given combo box to take a list of int/str pairs. 1961 1962 Arguments: 1963 - combobox: the GtkComboBox to initialize. 1964 """ 1965 1966 cell = Gtk.CellRendererText() 1967 combobox.pack_start(cell, True) 1968 # We only want to display one column; not two. 1969 # 1970 try: 1971 columnToDisplay = combobox.get_cells()[0] 1972 combobox.add_attribute(columnToDisplay, 'text', 1) 1973 except: 1974 combobox.add_attribute(cell, 'text', 1) 1975 model = Gtk.ListStore(int, str) 1976 combobox.set_model(model) 1977 1978 # Force the display comboboxes to be left aligned. 1979 # 1980 if isinstance(combobox, Gtk.ComboBoxText): 1981 size = combobox.size_request() 1982 cell.set_fixed_size(size[0] - 29, -1) 1983 1984 return model 1985 1986 def _setKeyEchoItems(self): 1987 """[In]sensitize the checkboxes for the various types of key echo, 1988 depending upon whether the value of the key echo check button is set. 1989 """ 1990 1991 enable = self.get_widget("keyEchoCheckButton").get_active() 1992 self.get_widget("enableAlphabeticKeysCheckButton").set_sensitive(enable) 1993 self.get_widget("enableNumericKeysCheckButton").set_sensitive(enable) 1994 self.get_widget("enablePunctuationKeysCheckButton").set_sensitive(enable) 1995 self.get_widget("enableSpaceCheckButton").set_sensitive(enable) 1996 self.get_widget("enableModifierKeysCheckButton").set_sensitive(enable) 1997 self.get_widget("enableFunctionKeysCheckButton").set_sensitive(enable) 1998 self.get_widget("enableActionKeysCheckButton").set_sensitive(enable) 1999 self.get_widget("enableNavigationKeysCheckButton").set_sensitive(enable) 2000 self.get_widget("enableDiacriticalKeysCheckButton").set_sensitive( \ 2001 enable) 2002 2003 def _presentMessage(self, text, interrupt=False): 2004 """If the text field is not None, presents the given text, optionally 2005 interrupting anything currently being spoken. 2006 2007 Arguments: 2008 - text: the text to present 2009 - interrupt: if True, interrupt any speech currently being spoken 2010 """ 2011 2012 self.script.speakMessage(text, interrupt=interrupt) 2013 try: 2014 self.script.displayBrailleMessage(text, flashTime=-1) 2015 except: 2016 pass 2017 2018 def _createNode(self, appName): 2019 """Create a new root node in the TreeStore model with the name of the 2020 application. 2021 2022 Arguments: 2023 - appName: the name of the TreeStore Node (the same of the application) 2024 """ 2025 2026 model = self.keyBindingsModel 2027 2028 myiter = model.append(None) 2029 model.set_value(myiter, DESCRIP, appName) 2030 model.set_value(myiter, MODIF, False) 2031 2032 return myiter 2033 2034 def _getIterOf(self, appName): 2035 """Returns the Gtk.TreeIter of the TreeStore model 2036 that matches the application name passed as argument 2037 2038 Arguments: 2039 - appName: a string with the name of the application of the node wanted 2040 it's the same that the field DESCRIP of the model treeStore 2041 """ 2042 2043 model = self.keyBindingsModel 2044 2045 for row in model: 2046 if ((model.iter_depth(row.iter) == 0) \ 2047 and (row[DESCRIP] == appName)): 2048 return row.iter 2049 2050 return None 2051 2052 def _clickCountToString(self, clickCount): 2053 """Given a numeric clickCount, returns a string for inclusion 2054 in the list of keybindings. 2055 2056 Argument: 2057 - clickCount: the number of clicks associated with the keybinding. 2058 """ 2059 2060 clickCountString = "" 2061 if clickCount == 2: 2062 clickCountString = " (%s)" % guilabels.CLICK_COUNT_DOUBLE 2063 elif clickCount == 3: 2064 clickCountString = " (%s)" % guilabels.CLICK_COUNT_TRIPLE 2065 2066 return clickCountString 2067 2068 def _insertRow(self, handl, kb, parent=None, modif=False): 2069 """Appends a new row with the new keybinding data to the treeview 2070 2071 Arguments: 2072 - handl: the name of the handler associated to the keyBinding 2073 - kb: the new keybinding. 2074 - parent: the parent node of the treeview, where to append the kb 2075 - modif: whether to check the modified field or not. 2076 2077 Returns a Gtk.TreeIter pointing at the new row. 2078 """ 2079 2080 model = self.keyBindingsModel 2081 2082 if parent is None: 2083 parent = self._getIterOf(guilabels.KB_GROUP_DEFAULT) 2084 2085 if parent is not None: 2086 myiter = model.append(parent) 2087 if not kb.keysymstring: 2088 text = None 2089 else: 2090 clickCount = self._clickCountToString(kb.click_count) 2091 modifierNames = keybindings.getModifierNames(kb.modifiers) 2092 keysymstring = kb.keysymstring 2093 text = keybindings.getModifierNames(kb.modifiers) \ 2094 + keysymstring \ 2095 + clickCount 2096 2097 model.set_value(myiter, HANDLER, handl) 2098 model.set_value(myiter, DESCRIP, kb.handler.description) 2099 model.set_value(myiter, MOD_MASK1, str(kb.modifier_mask)) 2100 model.set_value(myiter, MOD_USED1, str(kb.modifiers)) 2101 model.set_value(myiter, KEY1, kb.keysymstring) 2102 model.set_value(myiter, CLICK_COUNT1, str(kb.click_count)) 2103 if text is not None: 2104 model.set_value(myiter, OLDTEXT1, text) 2105 model.set_value(myiter, TEXT1, text) 2106 model.set_value(myiter, MODIF, modif) 2107 model.set_value(myiter, EDITABLE, True) 2108 2109 return myiter 2110 else: 2111 return None 2112 2113 def _insertRowBraille(self, handl, com, inputEvHand, 2114 parent=None, modif=False): 2115 """Appends a new row with the new braille binding data to the treeview 2116 2117 Arguments: 2118 - handl: the name of the handler associated to the brailleBinding 2119 - com: the BrlTTY command 2120 - inputEvHand: the inputEventHandler with the new brailleBinding 2121 - parent: the parent node of the treeview, where to append the kb 2122 - modif: whether to check the modified field or not. 2123 2124 Returns a Gtk.TreeIter pointing at the new row. 2125 """ 2126 2127 model = self.keyBindingsModel 2128 2129 if parent is None: 2130 parent = self._getIterOf(guilabels.KB_GROUP_BRAILLE) 2131 2132 if parent is not None: 2133 myiter = model.append(parent) 2134 model.set_value(myiter, HANDLER, handl) 2135 model.set_value(myiter, DESCRIP, inputEvHand.description) 2136 model.set_value(myiter, KEY1, str(com)) 2137 model.set_value(myiter, TEXT1, braille.command_name[com]) 2138 model.set_value(myiter, MODIF, modif) 2139 model.set_value(myiter, EDITABLE, False) 2140 return myiter 2141 else: 2142 return None 2143 2144 def _markModified(self): 2145 """ Mark as modified the user custom key bindings: 2146 """ 2147 2148 try: 2149 self.script.setupInputEventHandlers() 2150 keyBinds = keybindings.KeyBindings() 2151 keyBinds = _settingsManager.overrideKeyBindings(self.script, keyBinds) 2152 keyBind = keybindings.KeyBinding(None, None, None, None) 2153 treeModel = self.keyBindingsModel 2154 2155 myiter = treeModel.get_iter_first() 2156 while myiter is not None: 2157 iterChild = treeModel.iter_children(myiter) 2158 while iterChild is not None: 2159 descrip = treeModel.get_value(iterChild, DESCRIP) 2160 keyBind.handler = \ 2161 input_event.InputEventHandler(None, descrip) 2162 if keyBinds.hasKeyBinding(keyBind, 2163 typeOfSearch="description"): 2164 treeModel.set_value(iterChild, MODIF, True) 2165 iterChild = treeModel.iter_next(iterChild) 2166 myiter = treeModel.iter_next(myiter) 2167 except: 2168 debug.printException(debug.LEVEL_SEVERE) 2169 2170 def _populateKeyBindings(self, clearModel=True): 2171 """Fills the TreeView with the list of Orca keybindings 2172 2173 Arguments: 2174 - clearModel: if True, initially clear out the key bindings model. 2175 """ 2176 2177 self.keyBindView.set_model(None) 2178 self.keyBindView.set_headers_visible(False) 2179 self.keyBindView.hide() 2180 if clearModel: 2181 self.keyBindingsModel.clear() 2182 self.kbindings = None 2183 2184 try: 2185 appName = self.script.app.name 2186 except: 2187 appName = "" 2188 2189 iterApp = self._createNode(appName) 2190 iterOrca = self._createNode(guilabels.KB_GROUP_DEFAULT) 2191 iterUnbound = self._createNode(guilabels.KB_GROUP_UNBOUND) 2192 2193 if not self.kbindings: 2194 self.kbindings = keybindings.KeyBindings() 2195 self.script.setupInputEventHandlers() 2196 allKeyBindings = self.script.getKeyBindings() 2197 defKeyBindings = self.script.getDefaultKeyBindings() 2198 for kb in allKeyBindings.keyBindings: 2199 if not self.kbindings.hasKeyBinding(kb, "strict"): 2200 handl = self.script.getInputEventHandlerKey(kb.handler) 2201 if not defKeyBindings.hasKeyBinding(kb, "description"): 2202 self._insertRow(handl, kb, iterApp) 2203 elif kb.keysymstring: 2204 self._insertRow(handl, kb, iterOrca) 2205 else: 2206 self._insertRow(handl, kb, iterUnbound) 2207 self.kbindings.add(kb) 2208 2209 if not self.keyBindingsModel.iter_has_child(iterApp): 2210 self.keyBindingsModel.remove(iterApp) 2211 2212 if not self.keyBindingsModel.iter_has_child(iterUnbound): 2213 self.keyBindingsModel.remove(iterUnbound) 2214 2215 self._updateOrcaModifier() 2216 self._markModified() 2217 iterBB = self._createNode(guilabels.KB_GROUP_BRAILLE) 2218 self.bbindings = self.script.getBrailleBindings() 2219 for com, inputEvHand in self.bbindings.items(): 2220 handl = self.script.getInputEventHandlerKey(inputEvHand) 2221 self._insertRowBraille(handl, com, inputEvHand, iterBB) 2222 2223 self.keyBindView.set_model(self.keyBindingsModel) 2224 self.keyBindView.set_headers_visible(True) 2225 self.keyBindView.expand_all() 2226 self.keyBindingsModel.set_sort_column_id(OLDTEXT1, Gtk.SortType.ASCENDING) 2227 self.keyBindView.show() 2228 2229 # Keep track of new/unbound keybindings that have yet to be applied. 2230 # 2231 self.pendingKeyBindings = {} 2232 2233 def _cleanupSpeechServers(self): 2234 """Remove unwanted factories and drivers for the current active 2235 factory, when the user dismisses the Orca Preferences dialog.""" 2236 2237 for workingFactory in self.workingFactories: 2238 if not (workingFactory == self.speechSystemsChoice): 2239 workingFactory.SpeechServer.shutdownActiveServers() 2240 else: 2241 servers = workingFactory.SpeechServer.getSpeechServers() 2242 for server in servers: 2243 if not (server == self.speechServersChoice): 2244 server.shutdown() 2245 2246 def speechSupportChecked(self, widget): 2247 """Signal handler for the "toggled" signal for the 2248 speechSupportCheckButton GtkCheckButton widget. The user has 2249 [un]checked the 'Enable Speech' checkbox. Set the 'enableSpeech' 2250 preference to the new value. Set the rest of the speech pane items 2251 [in]sensensitive depending upon whether this checkbox is checked. 2252 2253 Arguments: 2254 - widget: the component that generated the signal. 2255 """ 2256 2257 enable = widget.get_active() 2258 self.prefsDict["enableSpeech"] = enable 2259 self.get_widget("speechOptionsGrid").set_sensitive(enable) 2260 2261 def onlySpeakDisplayedTextToggled(self, widget): 2262 """Signal handler for the "toggled" signal for the GtkCheckButton 2263 onlySpeakDisplayedText. In addition to updating the preferences, 2264 set the sensitivity of the contextOptionsGrid. 2265 2266 Arguments: 2267 - widget: the component that generated the signal. 2268 """ 2269 2270 enable = widget.get_active() 2271 self.prefsDict["onlySpeakDisplayedText"] = enable 2272 self.get_widget("contextOptionsGrid").set_sensitive(not enable) 2273 2274 def speechSystemsChanged(self, widget): 2275 """Signal handler for the "changed" signal for the speechSystems 2276 GtkComboBox widget. The user has selected a different speech 2277 system. Clear the existing list of speech servers, and setup 2278 a new list of speech servers based on the new choice. Setup a 2279 new list of voices for the first speech server in the list. 2280 2281 Arguments: 2282 - widget: the component that generated the signal. 2283 """ 2284 2285 if self.initializingSpeech: 2286 return 2287 2288 selectedIndex = widget.get_active() 2289 self.speechSystemsChoice = self.speechSystemsChoices[selectedIndex] 2290 self._setupSpeechServers() 2291 2292 def speechServersChanged(self, widget): 2293 """Signal handler for the "changed" signal for the speechServers 2294 GtkComboBox widget. The user has selected a different speech 2295 server. Clear the existing list of voices, and setup a new 2296 list of voices based on the new choice. 2297 2298 Arguments: 2299 - widget: the component that generated the signal. 2300 """ 2301 2302 if self.initializingSpeech: 2303 return 2304 2305 selectedIndex = widget.get_active() 2306 self.speechServersChoice = self.speechServersChoices[selectedIndex] 2307 2308 # Whenever the speech servers change, we need to make sure we 2309 # clear whatever family was in use by the current voice types. 2310 # Otherwise, we can end up with family names from one server 2311 # bleeding over (e.g., "Paul" from Fonix ends up getting in 2312 # the "Default" voice type after we switch to eSpeak). 2313 # 2314 try: 2315 del self.defaultVoice[acss.ACSS.FAMILY] 2316 del self.uppercaseVoice[acss.ACSS.FAMILY] 2317 del self.hyperlinkVoice[acss.ACSS.FAMILY] 2318 del self.systemVoice[acss.ACSS.FAMILY] 2319 except: 2320 pass 2321 2322 self._setupVoices() 2323 2324 def speechLanguagesChanged(self, widget): 2325 """Signal handler for the "value_changed" signal for the languages 2326 GtkComboBox widget. The user has selected a different voice 2327 language. Save the new voice language name based on the new choice. 2328 2329 Arguments: 2330 - widget: the component that generated the signal. 2331 """ 2332 2333 if self.initializingSpeech: 2334 return 2335 2336 selectedIndex = widget.get_active() 2337 try: 2338 self.speechLanguagesChoice = self.speechLanguagesChoices[selectedIndex] 2339 if (self.speechServersChoice, self.speechLanguagesChoice) in \ 2340 self.selectedFamilyChoices: 2341 i = self.selectedFamilyChoices[self.speechServersChoice, \ 2342 self.speechLanguagesChoice] 2343 family = self.speechFamiliesChoices[i] 2344 name = family[speechserver.VoiceFamily.NAME] 2345 language = family[speechserver.VoiceFamily.LANG] 2346 dialect = family[speechserver.VoiceFamily.DIALECT] 2347 variant = family[speechserver.VoiceFamily.VARIANT] 2348 voiceType = self.get_widget("voiceTypesCombo").get_active() 2349 self._setFamilyNameForVoiceType(voiceType, name, language, dialect, variant) 2350 except: 2351 debug.printException(debug.LEVEL_SEVERE) 2352 2353 # Remember the last family manually selected by the user for the 2354 # current speech server. 2355 # 2356 if not selectedIndex == -1: 2357 self.selectedLanguageChoices[self.speechServersChoice] = selectedIndex 2358 2359 self._setupFamilies() 2360 2361 def speechFamiliesChanged(self, widget): 2362 """Signal handler for the "value_changed" signal for the families 2363 GtkComboBox widget. The user has selected a different voice 2364 family. Save the new voice family name based on the new choice. 2365 2366 Arguments: 2367 - widget: the component that generated the signal. 2368 """ 2369 2370 if self.initializingSpeech: 2371 return 2372 2373 selectedIndex = widget.get_active() 2374 try: 2375 family = self.speechFamiliesChoices[selectedIndex] 2376 name = family[speechserver.VoiceFamily.NAME] 2377 language = family[speechserver.VoiceFamily.LANG] 2378 dialect = family[speechserver.VoiceFamily.DIALECT] 2379 variant = family[speechserver.VoiceFamily.VARIANT] 2380 voiceType = self.get_widget("voiceTypesCombo").get_active() 2381 self._setFamilyNameForVoiceType(voiceType, name, language, dialect, variant) 2382 except: 2383 debug.printException(debug.LEVEL_SEVERE) 2384 2385 # Remember the last family manually selected by the user for the 2386 # current speech server. 2387 # 2388 if not selectedIndex == -1: 2389 self.selectedFamilyChoices[self.speechServersChoice, \ 2390 self.speechLanguagesChoice] = selectedIndex 2391 2392 def voiceTypesChanged(self, widget): 2393 """Signal handler for the "changed" signal for the voiceTypes 2394 GtkComboBox widget. The user has selected a different voice 2395 type. Setup the new family, rate, pitch and volume component 2396 values based on the new choice. 2397 2398 Arguments: 2399 - widget: the component that generated the signal. 2400 """ 2401 2402 if self.initializingSpeech: 2403 return 2404 2405 voiceType = widget.get_active() 2406 self._setVoiceSettingsForVoiceType(voiceType) 2407 2408 def rateValueChanged(self, widget): 2409 """Signal handler for the "value_changed" signal for the rateScale 2410 GtkScale widget. The user has changed the current rate value. 2411 Save the new rate value based on the currently selected voice 2412 type. 2413 2414 Arguments: 2415 - widget: the component that generated the signal. 2416 """ 2417 2418 rate = widget.get_value() 2419 voiceType = self.get_widget("voiceTypesCombo").get_active() 2420 self._setRateForVoiceType(voiceType, rate) 2421 voices = _settingsManager.getSetting('voices') 2422 voices[settings.DEFAULT_VOICE][acss.ACSS.RATE] = rate 2423 _settingsManager.setSetting('voices', voices) 2424 2425 def pitchValueChanged(self, widget): 2426 """Signal handler for the "value_changed" signal for the pitchScale 2427 GtkScale widget. The user has changed the current pitch value. 2428 Save the new pitch value based on the currently selected voice 2429 type. 2430 2431 Arguments: 2432 - widget: the component that generated the signal. 2433 """ 2434 2435 pitch = widget.get_value() 2436 voiceType = self.get_widget("voiceTypesCombo").get_active() 2437 self._setPitchForVoiceType(voiceType, pitch) 2438 voices = _settingsManager.getSetting('voices') 2439 voices[settings.DEFAULT_VOICE][acss.ACSS.AVERAGE_PITCH] = pitch 2440 _settingsManager.setSetting('voices', voices) 2441 2442 def volumeValueChanged(self, widget): 2443 """Signal handler for the "value_changed" signal for the voiceScale 2444 GtkScale widget. The user has changed the current volume value. 2445 Save the new volume value based on the currently selected voice 2446 type. 2447 2448 Arguments: 2449 - widget: the component that generated the signal. 2450 """ 2451 2452 volume = widget.get_value() 2453 voiceType = self.get_widget("voiceTypesCombo").get_active() 2454 self._setVolumeForVoiceType(voiceType, volume) 2455 voices = _settingsManager.getSetting('voices') 2456 voices[settings.DEFAULT_VOICE][acss.ACSS.GAIN] = volume 2457 _settingsManager.setSetting('voices', voices) 2458 2459 def checkButtonToggled(self, widget): 2460 """Signal handler for "toggled" signal for basic GtkCheckButton 2461 widgets. The user has altered the state of the checkbox. 2462 Set the preference to the new value. 2463 2464 Arguments: 2465 - widget: the component that generated the signal. 2466 """ 2467 2468 # To use this default handler please make sure: 2469 # The name of the setting that will be changed is: settingName 2470 # The id of the widget in the ui should be: settingNameCheckButton 2471 # 2472 settingName = Gtk.Buildable.get_name(widget) 2473 # strip "CheckButton" from the end. 2474 settingName = settingName[:-11] 2475 self.prefsDict[settingName] = widget.get_active() 2476 2477 def keyEchoChecked(self, widget): 2478 """Signal handler for the "toggled" signal for the 2479 keyEchoCheckbutton GtkCheckButton widget. The user has 2480 [un]checked the 'Enable Key Echo' checkbox. Set the 2481 'enableKeyEcho' preference to the new value. [In]sensitize 2482 the checkboxes for the various types of key echo, depending 2483 upon whether this value is checked or unchecked. 2484 2485 Arguments: 2486 - widget: the component that generated the signal. 2487 """ 2488 2489 self.prefsDict["enableKeyEcho"] = widget.get_active() 2490 self._setKeyEchoItems() 2491 2492 def brailleSelectionChanged(self, widget): 2493 """Signal handler for the "toggled" signal for the 2494 brailleSelectionNoneButton, brailleSelection7Button, 2495 brailleSelection8Button or brailleSelectionBothButton 2496 GtkRadioButton widgets. The user has toggled the braille 2497 selection indicator value. If this signal was generated 2498 as the result of a radio button getting selected (as 2499 opposed to a radio button losing the selection), set the 2500 'brailleSelectorIndicator' preference to the new value. 2501 2502 Arguments: 2503 - widget: the component that generated the signal. 2504 """ 2505 2506 if widget.get_active(): 2507 if widget.get_label() == guilabels.BRAILLE_DOT_7: 2508 self.prefsDict["brailleSelectorIndicator"] = \ 2509 settings.BRAILLE_UNDERLINE_7 2510 elif widget.get_label() == guilabels.BRAILLE_DOT_8: 2511 self.prefsDict["brailleSelectorIndicator"] = \ 2512 settings.BRAILLE_UNDERLINE_8 2513 elif widget.get_label() == guilabels.BRAILLE_DOT_7_8: 2514 self.prefsDict["brailleSelectorIndicator"] = \ 2515 settings.BRAILLE_UNDERLINE_BOTH 2516 else: 2517 self.prefsDict["brailleSelectorIndicator"] = \ 2518 settings.BRAILLE_UNDERLINE_NONE 2519 2520 def brailleLinkChanged(self, widget): 2521 """Signal handler for the "toggled" signal for the 2522 brailleLinkNoneButton, brailleLink7Button, 2523 brailleLink8Button or brailleLinkBothButton 2524 GtkRadioButton widgets. The user has toggled the braille 2525 link indicator value. If this signal was generated 2526 as the result of a radio button getting selected (as 2527 opposed to a radio button losing the selection), set the 2528 'brailleLinkIndicator' preference to the new value. 2529 2530 Arguments: 2531 - widget: the component that generated the signal. 2532 """ 2533 2534 if widget.get_active(): 2535 if widget.get_label() == guilabels.BRAILLE_DOT_7: 2536 self.prefsDict["brailleLinkIndicator"] = \ 2537 settings.BRAILLE_UNDERLINE_7 2538 elif widget.get_label() == guilabels.BRAILLE_DOT_8: 2539 self.prefsDict["brailleLinkIndicator"] = \ 2540 settings.BRAILLE_UNDERLINE_8 2541 elif widget.get_label() == guilabels.BRAILLE_DOT_7_8: 2542 self.prefsDict["brailleLinkIndicator"] = \ 2543 settings.BRAILLE_UNDERLINE_BOTH 2544 else: 2545 self.prefsDict["brailleLinkIndicator"] = \ 2546 settings.BRAILLE_UNDERLINE_NONE 2547 2548 def brailleIndicatorChanged(self, widget): 2549 """Signal handler for the "toggled" signal for the 2550 textBrailleNoneButton, textBraille7Button, textBraille8Button 2551 or textBrailleBothButton GtkRadioButton widgets. The user has 2552 toggled the text attributes braille indicator value. If this signal 2553 was generated as the result of a radio button getting selected 2554 (as opposed to a radio button losing the selection), set the 2555 'textAttributesBrailleIndicator' preference to the new value. 2556 2557 Arguments: 2558 - widget: the component that generated the signal. 2559 """ 2560 2561 if widget.get_active(): 2562 if widget.get_label() == guilabels.BRAILLE_DOT_7: 2563 self.prefsDict["textAttributesBrailleIndicator"] = \ 2564 settings.BRAILLE_UNDERLINE_7 2565 elif widget.get_label() == guilabels.BRAILLE_DOT_8: 2566 self.prefsDict["textAttributesBrailleIndicator"] = \ 2567 settings.BRAILLE_UNDERLINE_8 2568 elif widget.get_label() == guilabels.BRAILLE_DOT_7_8: 2569 self.prefsDict["textAttributesBrailleIndicator"] = \ 2570 settings.BRAILLE_UNDERLINE_BOTH 2571 else: 2572 self.prefsDict["textAttributesBrailleIndicator"] = \ 2573 settings.BRAILLE_UNDERLINE_NONE 2574 2575 def punctuationLevelChanged(self, widget): 2576 """Signal handler for the "toggled" signal for the noneButton, 2577 someButton or allButton GtkRadioButton widgets. The user has 2578 toggled the speech punctuation level value. If this signal 2579 was generated as the result of a radio button getting selected 2580 (as opposed to a radio button losing the selection), set the 2581 'verbalizePunctuationStyle' preference to the new value. 2582 2583 Arguments: 2584 - widget: the component that generated the signal. 2585 """ 2586 2587 if widget.get_active(): 2588 if widget.get_label() == guilabels.PUNCTUATION_STYLE_NONE: 2589 self.prefsDict["verbalizePunctuationStyle"] = \ 2590 settings.PUNCTUATION_STYLE_NONE 2591 elif widget.get_label() == guilabels.PUNCTUATION_STYLE_SOME: 2592 self.prefsDict["verbalizePunctuationStyle"] = \ 2593 settings.PUNCTUATION_STYLE_SOME 2594 elif widget.get_label() == guilabels.PUNCTUATION_STYLE_MOST: 2595 self.prefsDict["verbalizePunctuationStyle"] = \ 2596 settings.PUNCTUATION_STYLE_MOST 2597 else: 2598 self.prefsDict["verbalizePunctuationStyle"] = \ 2599 settings.PUNCTUATION_STYLE_ALL 2600 2601 def orcaModifierChanged(self, widget): 2602 """Signal handler for the changed signal for the orcaModifierComboBox 2603 Set the 'orcaModifierKeys' preference to the new value. 2604 2605 Arguments: 2606 - widget: the component that generated the signal. 2607 """ 2608 2609 model = widget.get_model() 2610 myIter = widget.get_active_iter() 2611 orcaModifier = model[myIter][0] 2612 self.prefsDict["orcaModifierKeys"] = orcaModifier.split(', ') 2613 2614 def progressBarVerbosityChanged(self, widget): 2615 """Signal handler for the changed signal for the progressBarVerbosity 2616 GtkComboBox widget. Set the 'progressBarVerbosity' preference to 2617 the new value. 2618 2619 Arguments: 2620 - widget: the component that generated the signal. 2621 """ 2622 2623 model = widget.get_model() 2624 myIter = widget.get_active_iter() 2625 progressBarVerbosity = model[myIter][0] 2626 if progressBarVerbosity == guilabels.PROGRESS_BAR_ALL: 2627 self.prefsDict["progressBarVerbosity"] = \ 2628 settings.PROGRESS_BAR_ALL 2629 elif progressBarVerbosity == guilabels.PROGRESS_BAR_WINDOW: 2630 self.prefsDict["progressBarVerbosity"] = \ 2631 settings.PROGRESS_BAR_WINDOW 2632 else: 2633 self.prefsDict["progressBarVerbosity"] = \ 2634 settings.PROGRESS_BAR_APPLICATION 2635 2636 def capitalizationStyleChanged(self, widget): 2637 model = widget.get_model() 2638 myIter = widget.get_active_iter() 2639 capitalizationStyle = model[myIter][0] 2640 if capitalizationStyle == guilabels.CAPITALIZATION_STYLE_ICON: 2641 self.prefsDict["capitalizationStyle"] = settings.CAPITALIZATION_STYLE_ICON 2642 elif capitalizationStyle == guilabels.CAPITALIZATION_STYLE_SPELL: 2643 self.prefsDict["capitalizationStyle"] = settings.CAPITALIZATION_STYLE_SPELL 2644 else: 2645 self.prefsDict["capitalizationStyle"] = settings.CAPITALIZATION_STYLE_NONE 2646 speech.updateCapitalizationStyle() 2647 2648 def sayAllStyleChanged(self, widget): 2649 """Signal handler for the "changed" signal for the sayAllStyle 2650 GtkComboBox widget. Set the 'sayAllStyle' preference to the 2651 new value. 2652 2653 Arguments: 2654 - widget: the component that generated the signal. 2655 """ 2656 2657 model = widget.get_model() 2658 myIter = widget.get_active_iter() 2659 sayAllStyle = model[myIter][0] 2660 if sayAllStyle == guilabels.SAY_ALL_STYLE_LINE: 2661 self.prefsDict["sayAllStyle"] = settings.SAYALL_STYLE_LINE 2662 elif sayAllStyle == guilabels.SAY_ALL_STYLE_SENTENCE: 2663 self.prefsDict["sayAllStyle"] = settings.SAYALL_STYLE_SENTENCE 2664 2665 def dateFormatChanged(self, widget): 2666 """Signal handler for the "changed" signal for the dateFormat 2667 GtkComboBox widget. Set the 'dateFormat' preference to the 2668 new value. 2669 2670 Arguments: 2671 - widget: the component that generated the signal. 2672 """ 2673 2674 dateFormatCombo = widget.get_active() 2675 if dateFormatCombo == DATE_FORMAT_LOCALE: 2676 newFormat = messages.DATE_FORMAT_LOCALE 2677 elif dateFormatCombo == DATE_FORMAT_NUMBERS_DM: 2678 newFormat = messages.DATE_FORMAT_NUMBERS_DM 2679 elif dateFormatCombo == DATE_FORMAT_NUMBERS_MD: 2680 newFormat = messages.DATE_FORMAT_NUMBERS_MD 2681 elif dateFormatCombo == DATE_FORMAT_NUMBERS_DMY: 2682 newFormat = messages.DATE_FORMAT_NUMBERS_DMY 2683 elif dateFormatCombo == DATE_FORMAT_NUMBERS_MDY: 2684 newFormat = messages.DATE_FORMAT_NUMBERS_MDY 2685 elif dateFormatCombo == DATE_FORMAT_NUMBERS_YMD: 2686 newFormat = messages.DATE_FORMAT_NUMBERS_YMD 2687 elif dateFormatCombo == DATE_FORMAT_FULL_DM: 2688 newFormat = messages.DATE_FORMAT_FULL_DM 2689 elif dateFormatCombo == DATE_FORMAT_FULL_MD: 2690 newFormat = messages.DATE_FORMAT_FULL_MD 2691 elif dateFormatCombo == DATE_FORMAT_FULL_DMY: 2692 newFormat = messages.DATE_FORMAT_FULL_DMY 2693 elif dateFormatCombo == DATE_FORMAT_FULL_MDY: 2694 newFormat = messages.DATE_FORMAT_FULL_MDY 2695 elif dateFormatCombo == DATE_FORMAT_FULL_YMD: 2696 newFormat = messages.DATE_FORMAT_FULL_YMD 2697 elif dateFormatCombo == DATE_FORMAT_ABBREVIATED_DM: 2698 newFormat = messages.DATE_FORMAT_ABBREVIATED_DM 2699 elif dateFormatCombo == DATE_FORMAT_ABBREVIATED_MD: 2700 newFormat = messages.DATE_FORMAT_ABBREVIATED_MD 2701 elif dateFormatCombo == DATE_FORMAT_ABBREVIATED_DMY: 2702 newFormat = messages.DATE_FORMAT_ABBREVIATED_DMY 2703 elif dateFormatCombo == DATE_FORMAT_ABBREVIATED_MDY: 2704 newFormat = messages.DATE_FORMAT_ABBREVIATED_MDY 2705 elif dateFormatCombo == DATE_FORMAT_ABBREVIATED_YMD: 2706 newFormat = messages.DATE_FORMAT_ABBREVIATED_YMD 2707 self.prefsDict["presentDateFormat"] = newFormat 2708 2709 def timeFormatChanged(self, widget): 2710 """Signal handler for the "changed" signal for the timeFormat 2711 GtkComboBox widget. Set the 'timeFormat' preference to the 2712 new value. 2713 2714 Arguments: 2715 - widget: the component that generated the signal. 2716 """ 2717 2718 timeFormatCombo = widget.get_active() 2719 if timeFormatCombo == TIME_FORMAT_LOCALE: 2720 newFormat = messages.TIME_FORMAT_LOCALE 2721 elif timeFormatCombo == TIME_FORMAT_12_HM: 2722 newFormat = messages.TIME_FORMAT_12_HM 2723 elif timeFormatCombo == TIME_FORMAT_12_HMS: 2724 newFormat = messages.TIME_FORMAT_12_HMS 2725 elif timeFormatCombo == TIME_FORMAT_24_HMS: 2726 newFormat = messages.TIME_FORMAT_24_HMS 2727 elif timeFormatCombo == TIME_FORMAT_24_HMS_WITH_WORDS: 2728 newFormat = messages.TIME_FORMAT_24_HMS_WITH_WORDS 2729 elif timeFormatCombo == TIME_FORMAT_24_HM: 2730 newFormat = messages.TIME_FORMAT_24_HM 2731 elif timeFormatCombo == TIME_FORMAT_24_HM_WITH_WORDS: 2732 newFormat = messages.TIME_FORMAT_24_HM_WITH_WORDS 2733 self.prefsDict["presentTimeFormat"] = newFormat 2734 2735 def speechVerbosityChanged(self, widget): 2736 """Signal handler for the "toggled" signal for the speechBriefButton, 2737 or speechVerboseButton GtkRadioButton widgets. The user has 2738 toggled the speech verbosity level value. If this signal was 2739 generated as the result of a radio button getting selected 2740 (as opposed to a radio button losing the selection), set the 2741 'speechVerbosityLevel' preference to the new value. 2742 2743 Arguments: 2744 - widget: the component that generated the signal. 2745 """ 2746 2747 if widget.get_active(): 2748 if widget.get_label() == guilabels.VERBOSITY_LEVEL_BRIEF: 2749 self.prefsDict["speechVerbosityLevel"] = \ 2750 settings.VERBOSITY_LEVEL_BRIEF 2751 else: 2752 self.prefsDict["speechVerbosityLevel"] = \ 2753 settings.VERBOSITY_LEVEL_VERBOSE 2754 2755 def progressBarUpdateIntervalValueChanged(self, widget): 2756 """Signal handler for the "value_changed" signal for the 2757 progressBarUpdateIntervalSpinButton GtkSpinButton widget. 2758 2759 Arguments: 2760 - widget: the component that generated the signal. 2761 """ 2762 2763 self.prefsDict["progressBarUpdateInterval"] = widget.get_value_as_int() 2764 2765 def brailleFlashTimeValueChanged(self, widget): 2766 self.prefsDict["brailleFlashTime"] = widget.get_value_as_int() * 1000 2767 2768 def abbrevRolenamesChecked(self, widget): 2769 """Signal handler for the "toggled" signal for the abbrevRolenames 2770 GtkCheckButton widget. The user has [un]checked the 'Abbreviated 2771 Rolenames' checkbox. Set the 'brailleRolenameStyle' preference 2772 to the new value. 2773 2774 Arguments: 2775 - widget: the component that generated the signal. 2776 """ 2777 2778 if widget.get_active(): 2779 self.prefsDict["brailleRolenameStyle"] = \ 2780 settings.BRAILLE_ROLENAME_STYLE_SHORT 2781 else: 2782 self.prefsDict["brailleRolenameStyle"] = \ 2783 settings.BRAILLE_ROLENAME_STYLE_LONG 2784 2785 def brailleVerbosityChanged(self, widget): 2786 """Signal handler for the "toggled" signal for the brailleBriefButton, 2787 or brailleVerboseButton GtkRadioButton widgets. The user has 2788 toggled the braille verbosity level value. If this signal was 2789 generated as the result of a radio button getting selected 2790 (as opposed to a radio button losing the selection), set the 2791 'brailleVerbosityLevel' preference to the new value. 2792 2793 Arguments: 2794 - widget: the component that generated the signal. 2795 """ 2796 2797 if widget.get_active(): 2798 if widget.get_label() == guilabels.VERBOSITY_LEVEL_BRIEF: 2799 self.prefsDict["brailleVerbosityLevel"] = \ 2800 settings.VERBOSITY_LEVEL_BRIEF 2801 else: 2802 self.prefsDict["brailleVerbosityLevel"] = \ 2803 settings.VERBOSITY_LEVEL_VERBOSE 2804 2805 def keyModifiedToggle(self, cell, path, model, col): 2806 """When the user changes a checkbox field (boolean field)""" 2807 2808 model[path][col] = not model[path][col] 2809 return 2810 2811 def editingKey(self, cell, editable, path, treeModel): 2812 """Starts user input of a Key for a selected key binding""" 2813 2814 self._presentMessage(messages.KB_ENTER_NEW_KEY) 2815 orca_state.capturingKeys = True 2816 editable.connect('key-press-event', self.kbKeyPressed) 2817 return 2818 2819 def editingCanceledKey(self, editable): 2820 """Stops user input of a Key for a selected key binding""" 2821 2822 orca_state.capturingKeys = False 2823 self._capturedKey = [] 2824 return 2825 2826 def _processKeyCaptured(self, keyPressedEvent): 2827 """Called when a new key event arrives and we are capturing keys. 2828 (used for key bindings redefinition) 2829 """ 2830 2831 # We want the keyname rather than the printable character. 2832 # If it's not on the keypad, get the name of the unshifted 2833 # character. (i.e. "1" instead of "!") 2834 # 2835 keycode = keyPressedEvent.hardware_keycode 2836 keymap = Gdk.Keymap.get_default() 2837 entries_for_keycode = keymap.get_entries_for_keycode(keycode) 2838 entries = entries_for_keycode[-1] 2839 eventString = Gdk.keyval_name(entries[0]) 2840 eventState = keyPressedEvent.state 2841 2842 orcaMods = settings.orcaModifierKeys 2843 if eventString in orcaMods: 2844 self._capturedKey = ['', keybindings.ORCA_MODIFIER_MASK, 0] 2845 return False 2846 2847 modifierKeys = ['Alt_L', 'Alt_R', 'Control_L', 'Control_R', 2848 'Shift_L', 'Shift_R', 'Meta_L', 'Meta_R', 2849 'Num_Lock', 'Caps_Lock', 'Shift_Lock'] 2850 if eventString in modifierKeys: 2851 return False 2852 2853 eventState = eventState & Gtk.accelerator_get_default_mod_mask() 2854 if not self._capturedKey \ 2855 or eventString in ['Return', 'Escape']: 2856 self._capturedKey = [eventString, eventState, 1] 2857 return True 2858 2859 string, modifiers, clickCount = self._capturedKey 2860 isOrcaModifier = modifiers & keybindings.ORCA_MODIFIER_MASK 2861 if isOrcaModifier: 2862 eventState |= keybindings.ORCA_MODIFIER_MASK 2863 self._capturedKey = [eventString, eventState, clickCount + 1] 2864 2865 return True 2866 2867 def kbKeyPressed(self, editable, event): 2868 """Special handler for the key_pressed events when editing the 2869 keybindings. This lets us control what gets inserted into the 2870 entry. 2871 """ 2872 2873 keyProcessed = self._processKeyCaptured(event) 2874 if not keyProcessed: 2875 return True 2876 2877 if not self._capturedKey: 2878 return False 2879 2880 keyName, modifiers, clickCount = self._capturedKey 2881 if not keyName or keyName in ["Return", "Escape"]: 2882 return False 2883 2884 isOrcaModifier = modifiers & keybindings.ORCA_MODIFIER_MASK 2885 if keyName in ["Delete", "BackSpace"] and not isOrcaModifier: 2886 editable.set_text("") 2887 self._presentMessage(messages.KB_DELETED) 2888 self._capturedKey = [] 2889 self.newBinding = None 2890 return True 2891 2892 self.newBinding = keybindings.KeyBinding(keyName, 2893 keybindings.defaultModifierMask, 2894 modifiers, 2895 None, 2896 clickCount) 2897 modifierNames = keybindings.getModifierNames(modifiers) 2898 clickCountString = self._clickCountToString(clickCount) 2899 newString = modifierNames + keyName + clickCountString 2900 description = self.pendingKeyBindings.get(newString) 2901 2902 if description is None: 2903 match = lambda x: x.keysymstring == keyName \ 2904 and x.modifiers == modifiers \ 2905 and x.click_count == clickCount \ 2906 and x.handler 2907 matches = list(filter(match, self.kbindings.keyBindings)) 2908 if matches: 2909 description = matches[0].handler.description 2910 2911 if description: 2912 msg = messages.KB_ALREADY_BOUND % description 2913 delay = int(1000 * settings.doubleClickTimeout) 2914 GLib.timeout_add(delay, self._presentMessage, msg) 2915 else: 2916 msg = messages.KB_CAPTURED % newString 2917 editable.set_text(newString) 2918 self._presentMessage(msg) 2919 2920 return True 2921 2922 def editedKey(self, cell, path, new_text, treeModel, 2923 modMask, modUsed, key, click_count, text): 2924 """The user changed the key for a Keybinding: update the model of 2925 the treeview. 2926 """ 2927 2928 orca_state.capturingKeys = False 2929 self._capturedKey = [] 2930 myiter = treeModel.get_iter_from_string(path) 2931 try: 2932 originalBinding = treeModel.get_value(myiter, text) 2933 except: 2934 originalBinding = '' 2935 modified = (originalBinding != new_text) 2936 2937 try: 2938 string = self.newBinding.keysymstring 2939 mods = self.newBinding.modifiers 2940 clickCount = self.newBinding.click_count 2941 except: 2942 string = '' 2943 mods = 0 2944 clickCount = 1 2945 2946 mods = mods & Gdk.ModifierType.MODIFIER_MASK 2947 if mods & (1 << pyatspi.MODIFIER_SHIFTLOCK) \ 2948 and mods & keybindings.ORCA_MODIFIER_MASK: 2949 mods ^= (1 << pyatspi.MODIFIER_SHIFTLOCK) 2950 2951 treeModel.set(myiter, 2952 modMask, str(keybindings.defaultModifierMask), 2953 modUsed, str(int(mods)), 2954 key, string, 2955 text, new_text, 2956 click_count, str(clickCount), 2957 MODIF, modified) 2958 speech.stop() 2959 if new_text: 2960 message = messages.KB_CAPTURED_CONFIRMATION % new_text 2961 description = treeModel.get_value(myiter, DESCRIP) 2962 self.pendingKeyBindings[new_text] = description 2963 else: 2964 message = messages.KB_DELETED_CONFIRMATION 2965 2966 if modified: 2967 self._presentMessage(message) 2968 self.pendingKeyBindings[originalBinding] = "" 2969 2970 return 2971 2972 def presentToolTipsChecked(self, widget): 2973 """Signal handler for the "toggled" signal for the 2974 presentToolTipsCheckButton GtkCheckButton widget. 2975 The user has [un]checked the 'Present ToolTips' 2976 checkbox. Set the 'presentToolTips' 2977 preference to the new value if the user can present tooltips. 2978 2979 Arguments: 2980 - widget: the component that generated the signal. 2981 """ 2982 2983 self.prefsDict["presentToolTips"] = widget.get_active() 2984 2985 def keyboardLayoutChanged(self, widget): 2986 """Signal handler for the "toggled" signal for the generalDesktopButton, 2987 or generalLaptopButton GtkRadioButton widgets. The user has 2988 toggled the keyboard layout value. If this signal was 2989 generated as the result of a radio button getting selected 2990 (as opposed to a radio button losing the selection), set the 2991 'keyboardLayout' preference to the new value. Also set the 2992 matching list of Orca modifier keys 2993 2994 Arguments: 2995 - widget: the component that generated the signal. 2996 """ 2997 2998 if widget.get_active(): 2999 if widget.get_label() == guilabels.KEYBOARD_LAYOUT_DESKTOP: 3000 self.prefsDict["keyboardLayout"] = \ 3001 settings.GENERAL_KEYBOARD_LAYOUT_DESKTOP 3002 self.prefsDict["orcaModifierKeys"] = \ 3003 settings.DESKTOP_MODIFIER_KEYS 3004 else: 3005 self.prefsDict["keyboardLayout"] = \ 3006 settings.GENERAL_KEYBOARD_LAYOUT_LAPTOP 3007 self.prefsDict["orcaModifierKeys"] = \ 3008 settings.LAPTOP_MODIFIER_KEYS 3009 3010 def pronunciationAddButtonClicked(self, widget): 3011 """Signal handler for the "clicked" signal for the 3012 pronunciationAddButton GtkButton widget. The user has clicked 3013 the Add button on the Pronunciation pane. A new row will be 3014 added to the end of the pronunciation dictionary list. Both the 3015 actual and replacement strings will initially be set to an empty 3016 string. Focus will be moved to that row. 3017 3018 Arguments: 3019 - widget: the component that generated the signal. 3020 """ 3021 3022 model = self.pronunciationView.get_model() 3023 thisIter = model.append() 3024 model.set(thisIter, ACTUAL, "", REPLACEMENT, "") 3025 path = model.get_path(thisIter) 3026 col = self.pronunciationView.get_column(0) 3027 self.pronunciationView.grab_focus() 3028 self.pronunciationView.set_cursor(path, col, True) 3029 3030 def pronunciationDeleteButtonClicked(self, widget): 3031 """Signal handler for the "clicked" signal for the 3032 pronunciationDeleteButton GtkButton widget. The user has clicked 3033 the Delete button on the Pronunciation pane. The row in the 3034 pronunciation dictionary list with focus will be deleted. 3035 3036 Arguments: 3037 - widget: the component that generated the signal. 3038 """ 3039 3040 model, oldIter = self.pronunciationView.get_selection().get_selected() 3041 model.remove(oldIter) 3042 3043 def textSelectAllButtonClicked(self, widget): 3044 """Signal handler for the "clicked" signal for the 3045 textSelectAllButton GtkButton widget. The user has clicked 3046 the Speak all button. Check all the text attributes and 3047 then update the "enabledSpokenTextAttributes" and 3048 "enabledBrailledTextAttributes" preference strings. 3049 3050 Arguments: 3051 - widget: the component that generated the signal. 3052 """ 3053 3054 attributes = _settingsManager.getSetting('allTextAttributes') 3055 self._setSpokenTextAttributes( 3056 self.getTextAttributesView, attributes, True) 3057 self._setBrailledTextAttributes( 3058 self.getTextAttributesView, attributes, True) 3059 self._updateTextDictEntry() 3060 3061 def textUnselectAllButtonClicked(self, widget): 3062 """Signal handler for the "clicked" signal for the 3063 textUnselectAllButton GtkButton widget. The user has clicked 3064 the Speak none button. Uncheck all the text attributes and 3065 then update the "enabledSpokenTextAttributes" and 3066 "enabledBrailledTextAttributes" preference strings. 3067 3068 Arguments: 3069 - widget: the component that generated the signal. 3070 """ 3071 3072 attributes = _settingsManager.getSetting('allTextAttributes') 3073 self._setSpokenTextAttributes( 3074 self.getTextAttributesView, attributes, False) 3075 self._setBrailledTextAttributes( 3076 self.getTextAttributesView, attributes, False) 3077 self._updateTextDictEntry() 3078 3079 def textResetButtonClicked(self, widget): 3080 """Signal handler for the "clicked" signal for the 3081 textResetButton GtkButton widget. The user has clicked 3082 the Reset button. Reset all the text attributes to their 3083 initial state and then update the "enabledSpokenTextAttributes" 3084 and "enabledBrailledTextAttributes" preference strings. 3085 3086 Arguments: 3087 - widget: the component that generated the signal. 3088 """ 3089 3090 attributes = _settingsManager.getSetting('allTextAttributes') 3091 self._setSpokenTextAttributes( 3092 self.getTextAttributesView, attributes, False) 3093 self._setBrailledTextAttributes( 3094 self.getTextAttributesView, attributes, False) 3095 3096 attributes = _settingsManager.getSetting('enabledSpokenTextAttributes') 3097 self._setSpokenTextAttributes( 3098 self.getTextAttributesView, attributes, True) 3099 3100 attributes = \ 3101 _settingsManager.getSetting('enabledBrailledTextAttributes') 3102 self._setBrailledTextAttributes( 3103 self.getTextAttributesView, attributes, True) 3104 3105 self._updateTextDictEntry() 3106 3107 def textMoveToTopButtonClicked(self, widget): 3108 """Signal handler for the "clicked" signal for the 3109 textMoveToTopButton GtkButton widget. The user has clicked 3110 the Move to top button. Move the selected rows in the text 3111 attribute view to the very top of the list and then update 3112 the "enabledSpokenTextAttributes" and "enabledBrailledTextAttributes" 3113 preference strings. 3114 3115 Arguments: 3116 - widget: the component that generated the signal. 3117 """ 3118 3119 textSelection = self.getTextAttributesView.get_selection() 3120 [model, paths] = textSelection.get_selected_rows() 3121 for path in paths: 3122 thisIter = model.get_iter(path) 3123 model.move_after(thisIter, None) 3124 self._updateTextDictEntry() 3125 3126 def textMoveUpOneButtonClicked(self, widget): 3127 """Signal handler for the "clicked" signal for the 3128 textMoveUpOneButton GtkButton widget. The user has clicked 3129 the Move up one button. Move the selected rows in the text 3130 attribute view up one row in the list and then update the 3131 "enabledSpokenTextAttributes" and "enabledBrailledTextAttributes" 3132 preference strings. 3133 3134 Arguments: 3135 - widget: the component that generated the signal. 3136 """ 3137 3138 textSelection = self.getTextAttributesView.get_selection() 3139 [model, paths] = textSelection.get_selected_rows() 3140 for path in paths: 3141 thisIter = model.get_iter(path) 3142 indices = path.get_indices() 3143 if indices[0]: 3144 otherIter = model.iter_nth_child(None, indices[0]-1) 3145 model.swap(thisIter, otherIter) 3146 self._updateTextDictEntry() 3147 3148 def textMoveDownOneButtonClicked(self, widget): 3149 """Signal handler for the "clicked" signal for the 3150 textMoveDownOneButton GtkButton widget. The user has clicked 3151 the Move down one button. Move the selected rows in the text 3152 attribute view down one row in the list and then update the 3153 "enabledSpokenTextAttributes" and "enabledBrailledTextAttributes" 3154 preference strings. 3155 3156 Arguments: 3157 - widget: the component that generated the signal. 3158 """ 3159 3160 textSelection = self.getTextAttributesView.get_selection() 3161 [model, paths] = textSelection.get_selected_rows() 3162 noRows = model.iter_n_children(None) 3163 for path in paths: 3164 thisIter = model.get_iter(path) 3165 indices = path.get_indices() 3166 if indices[0] < noRows-1: 3167 otherIter = model.iter_next(thisIter) 3168 model.swap(thisIter, otherIter) 3169 self._updateTextDictEntry() 3170 3171 def textMoveToBottomButtonClicked(self, widget): 3172 """Signal handler for the "clicked" signal for the 3173 textMoveToBottomButton GtkButton widget. The user has clicked 3174 the Move to bottom button. Move the selected rows in the text 3175 attribute view to the bottom of the list and then update the 3176 "enabledSpokenTextAttributes" and "enabledBrailledTextAttributes" 3177 preference strings. 3178 3179 Arguments: 3180 - widget: the component that generated the signal. 3181 """ 3182 3183 textSelection = self.getTextAttributesView.get_selection() 3184 [model, paths] = textSelection.get_selected_rows() 3185 for path in paths: 3186 thisIter = model.get_iter(path) 3187 model.move_before(thisIter, None) 3188 self._updateTextDictEntry() 3189 3190 def helpButtonClicked(self, widget): 3191 """Signal handler for the "clicked" signal for the helpButton 3192 GtkButton widget. The user has clicked the Help button. 3193 3194 Arguments: 3195 - widget: the component that generated the signal. 3196 """ 3197 3198 orca.helpForOrca(page="preferences") 3199 3200 def restoreSettings(self): 3201 """Restore the settings we saved away when opening the preferences 3202 dialog.""" 3203 # Restore the default rate/pitch/gain, 3204 # in case the user played with the sliders. 3205 # 3206 voices = _settingsManager.getSetting('voices') 3207 defaultVoice = voices[settings.DEFAULT_VOICE] 3208 defaultVoice[acss.ACSS.GAIN] = self.savedGain 3209 defaultVoice[acss.ACSS.AVERAGE_PITCH] = self.savedPitch 3210 defaultVoice[acss.ACSS.RATE] = self.savedRate 3211 3212 def saveBasicSettings(self): 3213 if not self._isInitialSetup: 3214 self.restoreSettings() 3215 3216 enable = self.get_widget("speechSupportCheckButton").get_active() 3217 self.prefsDict["enableSpeech"] = enable 3218 3219 if self.speechSystemsChoice: 3220 self.prefsDict["speechServerFactory"] = \ 3221 self.speechSystemsChoice.__name__ 3222 3223 if self.speechServersChoice: 3224 self.prefsDict["speechServerInfo"] = \ 3225 self.speechServersChoice.getInfo() 3226 3227 if self.defaultVoice is not None: 3228 self.prefsDict["voices"] = { 3229 settings.DEFAULT_VOICE: acss.ACSS(self.defaultVoice), 3230 settings.UPPERCASE_VOICE: acss.ACSS(self.uppercaseVoice), 3231 settings.HYPERLINK_VOICE: acss.ACSS(self.hyperlinkVoice), 3232 settings.SYSTEM_VOICE: acss.ACSS(self.systemVoice), 3233 } 3234 3235 def applyButtonClicked(self, widget): 3236 """Signal handler for the "clicked" signal for the applyButton 3237 GtkButton widget. The user has clicked the Apply button. 3238 Write out the users preferences. If GNOME accessibility hadn't 3239 previously been enabled, warn the user that they will need to 3240 log out. Shut down any active speech servers that were started. 3241 Reload the users preferences to get the new speech, braille and 3242 key echo value to take effect. Do not dismiss the configuration 3243 window. 3244 3245 Arguments: 3246 - widget: the component that generated the signal. 3247 """ 3248 self.saveBasicSettings() 3249 3250 activeProfile = self.getComboBoxList(self.profilesCombo) 3251 startingProfile = self.getComboBoxList(self.startingProfileCombo) 3252 3253 self.prefsDict['profile'] = activeProfile 3254 self.prefsDict['activeProfile'] = activeProfile 3255 self.prefsDict['startingProfile'] = startingProfile 3256 _settingsManager.setStartingProfile(startingProfile) 3257 3258 self.writeUserPreferences() 3259 3260 orca.loadUserSettings(self.script) 3261 3262 braille.checkBrailleSetting() 3263 3264 self._initSpeechState() 3265 3266 self._populateKeyBindings() 3267 3268 self.__initProfileCombo() 3269 3270 def cancelButtonClicked(self, widget): 3271 """Signal handler for the "clicked" signal for the cancelButton 3272 GtkButton widget. The user has clicked the Cancel button. 3273 Don't write out the preferences. Destroy the configuration window. 3274 3275 Arguments: 3276 - widget: the component that generated the signal. 3277 """ 3278 3279 self.windowClosed(widget) 3280 self.get_widget("orcaSetupWindow").destroy() 3281 3282 def okButtonClicked(self, widget=None): 3283 """Signal handler for the "clicked" signal for the okButton 3284 GtkButton widget. The user has clicked the OK button. 3285 Write out the users preferences. If GNOME accessibility hadn't 3286 previously been enabled, warn the user that they will need to 3287 log out. Shut down any active speech servers that were started. 3288 Reload the users preferences to get the new speech, braille and 3289 key echo value to take effect. Hide the configuration window. 3290 3291 Arguments: 3292 - widget: the component that generated the signal. 3293 """ 3294 3295 self.applyButtonClicked(widget) 3296 self._cleanupSpeechServers() 3297 self.get_widget("orcaSetupWindow").destroy() 3298 3299 def windowClosed(self, widget): 3300 """Signal handler for the "closed" signal for the orcaSetupWindow 3301 GtkWindow widget. This is effectively the same as pressing the 3302 cancel button, except the window is destroyed for us. 3303 3304 Arguments: 3305 - widget: the component that generated the signal. 3306 """ 3307 3308 factory = _settingsManager.getSetting('speechServerFactory') 3309 if factory: 3310 self._setSpeechSystemsChoice(factory) 3311 3312 server = _settingsManager.getSetting('speechServerInfo') 3313 if server: 3314 self._setSpeechServersChoice(server) 3315 3316 self._cleanupSpeechServers() 3317 self.restoreSettings() 3318 3319 def windowDestroyed(self, widget): 3320 """Signal handler for the "destroyed" signal for the orcaSetupWindow 3321 GtkWindow widget. Reset orca_state.orcaOS to None, so that the 3322 GUI can be rebuilt from the GtkBuilder file the next time the user 3323 wants to display the configuration GUI. 3324 3325 Arguments: 3326 - widget: the component that generated the signal. 3327 """ 3328 3329 self.keyBindView.set_model(None) 3330 self.getTextAttributesView.set_model(None) 3331 self.pronunciationView.set_model(None) 3332 self.keyBindView.set_headers_visible(False) 3333 self.getTextAttributesView.set_headers_visible(False) 3334 self.pronunciationView.set_headers_visible(False) 3335 self.keyBindView.hide() 3336 self.getTextAttributesView.hide() 3337 self.pronunciationView.hide() 3338 orca_state.orcaOS = None 3339 3340 def showProfileGUI(self, widget): 3341 """Show profile Dialog to add a new one""" 3342 3343 orca_gui_profile.showProfileUI(self) 3344 3345 def saveProfile(self, profileToSaveLabel): 3346 """Creates a new profile based on the name profileToSaveLabel and 3347 updates the Preferences dialog combo boxes accordingly.""" 3348 3349 if not profileToSaveLabel: 3350 return 3351 profileToSave = profileToSaveLabel.replace(' ', '_').lower() 3352 profile = [profileToSaveLabel, profileToSave] 3353 3354 def saveActiveProfile(newProfile = True): 3355 if newProfile: 3356 activeProfileIter = self.profilesComboModel.append(profile) 3357 self.profilesCombo.set_active_iter(activeProfileIter) 3358 3359 self.prefsDict['profile'] = profile 3360 self.prefsDict['activeProfile'] = profile 3361 self.saveBasicSettings() 3362 self.writeUserPreferences() 3363 3364 availableProfiles = [p[1] for p in self.__getAvailableProfiles()] 3365 if isinstance(profileToSave, str) \ 3366 and profileToSave != '' \ 3367 and not profileToSave in availableProfiles \ 3368 and profileToSave != self._defaultProfile[1]: 3369 saveActiveProfile() 3370 else: 3371 if profileToSave is not None: 3372 message = guilabels.PROFILE_CONFLICT_MESSAGE % \ 3373 ("<b>%s</b>" % GLib.markup_escape_text(profileToSaveLabel)) 3374 dialog = Gtk.MessageDialog(None, 3375 Gtk.DialogFlags.MODAL, 3376 type=Gtk.MessageType.INFO, 3377 buttons=Gtk.ButtonsType.YES_NO) 3378 dialog.set_markup("<b>%s</b>" % guilabels.PROFILE_CONFLICT_LABEL) 3379 dialog.format_secondary_markup(message) 3380 dialog.set_title(guilabels.PROFILE_CONFLICT_TITLE) 3381 response = dialog.run() 3382 if response == Gtk.ResponseType.YES: 3383 dialog.destroy() 3384 saveActiveProfile(False) 3385 else: 3386 dialog.destroy() 3387 3388 3389 def removeProfileButtonClicked(self, widget): 3390 """Remove profile button clicked handler 3391 3392 If we removed the last profile, a default one will automatically get 3393 added back by the settings manager. 3394 """ 3395 3396 oldProfile = self.getComboBoxList(self.profilesCombo) 3397 3398 message = guilabels.PROFILE_REMOVE_MESSAGE % \ 3399 ("<b>%s</b>" % GLib.markup_escape_text(oldProfile[0])) 3400 dialog = Gtk.MessageDialog(self.window, Gtk.DialogFlags.MODAL, 3401 type=Gtk.MessageType.INFO, 3402 buttons=Gtk.ButtonsType.YES_NO) 3403 dialog.set_markup("<b>%s</b>" % guilabels.PROFILE_REMOVE_LABEL) 3404 dialog.format_secondary_markup(message) 3405 if dialog.run() == Gtk.ResponseType.YES: 3406 # If we remove the currently used starting profile, fallback on 3407 # the first listed profile, or the default one if there's 3408 # nothing better 3409 newStartingProfile = self.prefsDict.get('startingProfile') 3410 if not newStartingProfile or newStartingProfile == oldProfile: 3411 newStartingProfile = self._defaultProfile 3412 for row in self.profilesComboModel: 3413 rowProfile = row[:] 3414 if rowProfile != oldProfile: 3415 newStartingProfile = rowProfile 3416 break 3417 # Update the current profile to the active profile unless we're 3418 # removing that one, in which case we use the new starting 3419 # profile 3420 newProfile = self.prefsDict.get('activeProfile') 3421 if not newProfile or newProfile == oldProfile: 3422 newProfile = newStartingProfile 3423 3424 _settingsManager.removeProfile(oldProfile[1]) 3425 self.loadProfile(newProfile) 3426 3427 # Make sure nothing is referencing the removed profile anymore 3428 startingProfile = self.prefsDict.get('startingProfile') 3429 if not startingProfile or startingProfile == oldProfile: 3430 self.prefsDict['startingProfile'] = newStartingProfile 3431 _settingsManager.setStartingProfile(newStartingProfile) 3432 self.writeUserPreferences() 3433 3434 dialog.destroy() 3435 3436 def loadProfileButtonClicked(self, widget): 3437 """Load profile button clicked handler""" 3438 3439 if self._isInitialSetup: 3440 return 3441 3442 dialog = Gtk.MessageDialog(None, 3443 Gtk.DialogFlags.MODAL, 3444 type=Gtk.MessageType.INFO, 3445 buttons=Gtk.ButtonsType.YES_NO) 3446 3447 dialog.set_markup("<b>%s</b>" % guilabels.PROFILE_LOAD_LABEL) 3448 dialog.format_secondary_markup(guilabels.PROFILE_LOAD_MESSAGE) 3449 response = dialog.run() 3450 if response == Gtk.ResponseType.YES: 3451 dialog.destroy() 3452 self.loadSelectedProfile() 3453 else: 3454 dialog.destroy() 3455 3456 def loadSelectedProfile(self): 3457 """Load selected profile""" 3458 3459 activeProfile = self.getComboBoxList(self.profilesCombo) 3460 self.loadProfile(activeProfile) 3461 3462 def loadProfile(self, profile): 3463 """Load profile""" 3464 3465 self.saveBasicSettings() 3466 3467 self.prefsDict['activeProfile'] = profile 3468 _settingsManager.setProfile(profile[1]) 3469 self.prefsDict = _settingsManager.getGeneralSettings(profile[1]) 3470 3471 orca.loadUserSettings(skipReloadMessage=True) 3472 3473 self._initGUIState() 3474 3475 braille.checkBrailleSetting() 3476 3477 self._initSpeechState() 3478 3479 self._populateKeyBindings() 3480 3481 self.__initProfileCombo() 3482 3483