orca r4013 - in trunk: . src/orca



Author: richb
Date: Tue Jul  1 14:38:15 2008
New Revision: 4013
URL: http://svn.gnome.org/viewvc/orca?rev=4013&view=rev

Log:
        * src/orca/settings.py:
          src/orca/orca-setup.glade:
          src/orca/default.py:
          src/orca/orca_gui_prefs.py:
          Fix for bug #520596 - Orca should implement echo by sentence.


Modified:
   trunk/ChangeLog
   trunk/src/orca/default.py
   trunk/src/orca/orca-setup.glade
   trunk/src/orca/orca_gui_prefs.py
   trunk/src/orca/settings.py

Modified: trunk/src/orca/default.py
==============================================================================
--- trunk/src/orca/default.py	(original)
+++ trunk/src/orca/default.py	Tue Jul  1 14:38:15 2008
@@ -2214,6 +2214,83 @@
         if len(utterance):
             speech.speak(utterance)
 
+    def echoPreviousSentence(self, obj):
+        """Speaks the sentence prior to the caret, as long as there is
+        a sentence prior to the caret and there is no intervening sentence
+        delimiter between the caret and the end of the sentence.
+ 
+        The entry condition for this method is that the character
+        prior to the current caret position is a sentence delimiter,
+        and it's what caused this method to be called in the first
+        place.
+ 
+        Arguments:
+        - obj: an Accessible object that implements the AccessibleText
+        interface.
+        """
+ 
+        try:
+            text = obj.queryText()
+        except NotImplementedError:
+            return
+ 
+        offset = text.caretOffset - 1
+        previousOffset = text.caretOffset - 2
+        if (offset < 0 or previousOffset < 0):
+            return
+ 
+        [currentChar, startOffset, endOffset] = \
+            text.getTextAtOffset(offset, pyatspi.TEXT_BOUNDARY_CHAR)
+        [previousChar, startOffset, endOffset] = \
+            text.getTextAtOffset(previousOffset, pyatspi.TEXT_BOUNDARY_CHAR)
+        if not self.isSentenceDelimiter(currentChar, previousChar):
+            return
+ 
+        # OK - we seem to be cool so far.  So...starting with what
+        # should be the last character in the sentence (caretOffset - 2),
+        # work our way to the beginning of the sentence, stopping when
+        # we hit another sentence delimiter.
+        #
+        sentenceEndOffset = text.caretOffset - 2
+        sentenceStartOffset = sentenceEndOffset
+ 
+        while sentenceStartOffset >= 0:
+            [currentChar, startOffset, endOffset] = \
+                text.getTextAtOffset(sentenceStartOffset,
+                                     pyatspi.TEXT_BOUNDARY_CHAR)
+            [previousChar, startOffset, endOffset] = \
+                text.getTextAtOffset(sentenceStartOffset-1,
+                                     pyatspi.TEXT_BOUNDARY_CHAR)
+            if self.isSentenceDelimiter(currentChar, previousChar):
+                break
+            else:
+                sentenceStartOffset -= 1
+ 
+        # If we came across a sentence delimiter before hitting any
+        # text, we really don't have a previous sentence.
+        #
+        # Otherwise, get the sentence.  Remember we stopped when we
+        # hit a sentence delimiter, so the sentence really starts at
+        # sentenceStartOffset + 1.  getText also does not include
+        # the character at sentenceEndOffset, so we need to adjust
+        # for that, too.
+        #
+        if sentenceStartOffset == sentenceEndOffset:
+            return
+        else:
+            sentence = self.getText(obj, sentenceStartOffset + 1,
+                                         sentenceEndOffset + 1)
+ 
+        if self.getLinkIndex(obj, sentenceStartOffset + 1) >= 0:
+            voice = self.voices[settings.HYPERLINK_VOICE]
+        elif sentence.isupper():
+            voice = self.voices[settings.UPPERCASE_VOICE]
+        else:
+            voice = self.voices[settings.DEFAULT_VOICE]
+ 
+        sentence = self.adjustForRepeats(sentence)
+        speech.speak(sentence, voice)
+ 
     def echoPreviousWord(self, obj, offset=None):
         """Speaks the word prior to the caret, as long as there is
         a word prior to the caret and there is no intervening word
@@ -3588,8 +3665,26 @@
             else:
                 speech.speak(text)
 
-        if settings.enableEchoByWord \
-           and self.isWordDelimiter(text.decode("UTF-8")[-1:]):
+        try:
+            text = event.source.queryText()
+        except NotImplementedError:
+            return
+
+        offset = text.caretOffset - 1
+        previousOffset = text.caretOffset - 2
+        if (offset < 0 or previousOffset < 0):
+            return
+
+        [currentChar, startOffset, endOffset] = \
+            text.getTextAtOffset(offset, pyatspi.TEXT_BOUNDARY_CHAR)
+        [previousChar, startOffset, endOffset] = \
+            text.getTextAtOffset(previousOffset, pyatspi.TEXT_BOUNDARY_CHAR)
+
+        if settings.enableEchoBySentence and \
+           self.isSentenceDelimiter(currentChar, previousChar):
+            self.echoPreviousSentence(event.source)
+
+        elif settings.enableEchoByWord and self.isWordDelimiter(currentChar):
             self.echoPreviousWord(event.source)
 
     def onActiveDescendantChanged(self, event):
@@ -6179,6 +6274,30 @@
         """
         return obj.getIndexInParent()
 
+    def isSentenceDelimiter(self, currentChar, previousChar):
+        """Returns True if we are positioned at the end of a sentence.
+        This is determined by checking if the current character is a 
+        white space character and the previous character is one of the 
+        normal end-of-sentence punctuation characters.
+
+        Arguments:
+        - currentChar:  the current character
+        - previousChar: the previous character
+
+        Returns True if the given character is a sentence delimiter.
+        """
+
+        if not isinstance(currentChar, unicode):
+            currentChar = currentChar.decode("UTF-8")
+
+        if not isinstance(previousChar, unicode):
+            previousChar = previousChar.decode("UTF-8")
+
+        if currentChar == '\r' or currentChar == '\n':
+            return True
+
+        return (currentChar in self.whitespace and previousChar in '!.?:;')
+
     def isWordDelimiter(self, character):
         """Returns True if the given character is a word delimiter.
 

Modified: trunk/src/orca/orca-setup.glade
==============================================================================
--- trunk/src/orca/orca-setup.glade	(original)
+++ trunk/src/orca/orca-setup.glade	Tue Jul  1 14:38:15 2008
@@ -1292,8 +1292,8 @@
 				  <property name="wrap">False</property>
 				  <property name="adjustment">10 1 9999 1 10 10</property>
 				  <accessibility>
-				    <atkrelation target="speakProgressBarLabel" type="labelled-by"/>
 				    <atkrelation target="speakProgressBarUnitsLabel" type="labelled-by"/>
+				    <atkrelation target="speakProgressBarLabel" type="labelled-by"/>
 				  </accessibility>
 				  <signal name="value_changed" handler="speakProgressBarValueChanged" last_modification_time="Thu, 14 Jun 2007 15:09:00 GMT"/>
 				</widget>
@@ -2395,6 +2395,26 @@
 		      <property name="fill">False</property>
 		    </packing>
 		  </child>
+
+		  <child>
+		    <widget class="GtkCheckButton" id="echoBySentenceCheckbutton">
+		      <property name="visible">True</property>
+		      <property name="can_focus">True</property>
+		      <property name="label" translatable="yes">Enable echo by _sentence</property>
+		      <property name="use_underline">True</property>
+		      <property name="relief">GTK_RELIEF_NORMAL</property>
+		      <property name="focus_on_click">True</property>
+		      <property name="active">False</property>
+		      <property name="inconsistent">False</property>
+		      <property name="draw_indicator">True</property>
+		      <signal name="toggled" handler="echoBySentenceChecked" last_modification_time="Thu, 12 Jun 2008 15:31:32 GMT"/>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">False</property>
+		      <property name="fill">False</property>
+		    </packing>
+		  </child>
 		</widget>
 		<packing>
 		  <property name="tab_expand">False</property>
@@ -3701,8 +3721,8 @@
 							  <property name="wrap">False</property>
 							  <property name="adjustment">1 24 256 1 10 10</property>
 							  <accessibility>
-							    <atkrelation target="magCursorSizeUnitsLabel" type="labelled-by"/>
 							    <atkrelation target="magCursorSizeLabel" type="labelled-by"/>
+							    <atkrelation target="magCursorSizeUnitsLabel" type="labelled-by"/>
 							  </accessibility>
 							  <signal name="value_changed" handler="magCursorSizeValueChanged" last_modification_time="Wed, 03 May 2006 15:31:48 GMT"/>
 							</widget>
@@ -4054,8 +4074,8 @@
 							  <property name="wrap">False</property>
 							  <property name="adjustment">1 1 256 1 10 10</property>
 							  <accessibility>
-							    <atkrelation target="magCrossHairSizeUnitsLabel" type="labelled-by"/>
 							    <atkrelation target="magCrossHairSizeLabel" type="labelled-by"/>
+							    <atkrelation target="magCrossHairSizeUnitsLabel" type="labelled-by"/>
 							  </accessibility>
 							  <signal name="value_changed" handler="magCrossHairSizeValueChanged" last_modification_time="Wed, 03 May 2006 15:39:23 GMT"/>
 							</widget>
@@ -4492,8 +4512,8 @@
 						  <property name="wrap">False</property>
 						  <property name="adjustment">0 0 100 1 10 10</property>
 						  <accessibility>
-						    <atkrelation target="magEdgeMarginLabel" type="labelled-by"/>
 						    <atkrelation target="magEdgeMarginUnitsLabel" type="labelled-by"/>
+						    <atkrelation target="magEdgeMarginLabel" type="labelled-by"/>
 						  </accessibility>
 						  <signal name="value_changed" handler="magEdgeMarginValueChanged" last_modification_time="Thu, 06 Dec 2007 22:57:50 GMT"/>
 						</widget>

Modified: trunk/src/orca/orca_gui_prefs.py
==============================================================================
--- trunk/src/orca/orca_gui_prefs.py	(original)
+++ trunk/src/orca/orca_gui_prefs.py	Tue Jul  1 14:38:15 2008
@@ -1560,6 +1560,8 @@
                         prefs["enableNavigationKeys"])
         self.get_widget("echoByWordCheckbutton").set_active( \
                         prefs["enableEchoByWord"])
+        self.get_widget("echoBySentenceCheckbutton").set_active( \
+                        prefs["enableEchoBySentence"])
 
         # Magnifier pane.
         #
@@ -2539,6 +2541,18 @@
 
         self.prefsDict["enableEchoByWord"] = widget.get_active()
 
+    def echoBySentenceChecked(self, widget):
+        """Signal handler for the "toggled" signal for the
+           echoBySentenceCheckbutton GtkCheckButton widget. The user has
+           [un]checked the 'Enable Echo by Sentence' checkbox. Set the
+           'enableEchoBySentence' preference to the new value.
+
+        Arguments:
+        - widget: the component that generated the signal.
+        """
+
+        self.prefsDict["enableEchoBySentence"] = widget.get_active()
+
     def brailleSelectionChanged(self, widget):
         """Signal handler for the "toggled" signal for the
            brailleSelectionNoneButton, brailleSelection7Button,

Modified: trunk/src/orca/settings.py
==============================================================================
--- trunk/src/orca/settings.py	(original)
+++ trunk/src/orca/settings.py	Tue Jul  1 14:38:15 2008
@@ -98,6 +98,7 @@
     "readTableCellRow",
     "enableSpeechIndentation",
     "enableEchoByWord",
+    "enableEchoBySentence",
     "enableKeyEcho",
     "enablePrintableKeys",
     "enableModifierKeys",
@@ -508,6 +509,12 @@
 #
 enableEchoByWord        = False
 
+# if True, enable word echo.
+# Note that it is allowable for both enableEchoByWord and enableEchoBySentence
+# to be True.
+#
+enableEchoBySentence    = False
+
 # If True, enable key echo.
 # Note that it is allowable for both enableEchoByWord and enableKeyEcho
 # to be True



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]