[orca] Fix for bgo#615489 - Migrate Pidgin script to new chat.py
- From: Joanmarie Diggs <joanied src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [orca] Fix for bgo#615489 - Migrate Pidgin script to new chat.py
- Date: Tue, 15 Jun 2010 10:18:07 +0000 (UTC)
commit 7d767c9e6f27c2b76fd99d75c33c3fb9c668104a
Author: Joanmarie Diggs <joanmarie diggs gmail com>
Date: Sun Jun 13 10:14:46 2010 -0400
Fix for bgo#615489 - Migrate Pidgin script to new chat.py
src/orca/chat.py | 2 +-
src/orca/scripts/apps/pidgin/Makefile.am | 2 +-
src/orca/scripts/apps/pidgin/__init__.py | 1 -
src/orca/scripts/apps/pidgin/chat.py | 64 ++
src/orca/scripts/apps/pidgin/script.py | 754 ++--------------------
src/orca/scripts/apps/pidgin/script_settings.py | 47 --
src/orca/scripts/apps/pidgin/script_utilities.py | 4 +-
src/orca/scripts/apps/pidgin/speech_generator.py | 4 +-
8 files changed, 132 insertions(+), 746 deletions(-)
---
diff --git a/src/orca/chat.py b/src/orca/chat.py
index 2749545..1dad68f 100644
--- a/src/orca/chat.py
+++ b/src/orca/chat.py
@@ -704,7 +704,7 @@ class Chat:
#
return True
- elif self.isTypingStatusChangedEvent(event.source):
+ elif self.isTypingStatusChangedEvent(event):
self.presentTypingStatusChange(event, event.any_data)
return True
diff --git a/src/orca/scripts/apps/pidgin/Makefile.am b/src/orca/scripts/apps/pidgin/Makefile.am
index 10ea6d4..9df9c24 100644
--- a/src/orca/scripts/apps/pidgin/Makefile.am
+++ b/src/orca/scripts/apps/pidgin/Makefile.am
@@ -2,8 +2,8 @@ orca_pathdir=$(pyexecdir)
orca_python_PYTHON = \
__init__.py \
+ chat.py \
script.py \
- script_settings.py \
script_utilities.py \
speech_generator.py
diff --git a/src/orca/scripts/apps/pidgin/__init__.py b/src/orca/scripts/apps/pidgin/__init__.py
index 6f2d03c..1eb5b8d 100644
--- a/src/orca/scripts/apps/pidgin/__init__.py
+++ b/src/orca/scripts/apps/pidgin/__init__.py
@@ -18,4 +18,3 @@
# Boston MA 02110-1301 USA.
from script import Script
-import script_settings
diff --git a/src/orca/scripts/apps/pidgin/chat.py b/src/orca/scripts/apps/pidgin/chat.py
new file mode 100644
index 0000000..7e344cf
--- /dev/null
+++ b/src/orca/scripts/apps/pidgin/chat.py
@@ -0,0 +1,64 @@
+# Orca
+#
+# Copyright 2010 Joanmarie Diggs.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
+# Boston MA 02110-1301 USA.
+
+"""Custom chat module for Pidgin."""
+
+__id__ = "$Id$"
+__version__ = "$Revision$"
+__date__ = "$Date$"
+__copyright__ = "Copyright (c) 2010 Joanmarie Diggs."
+__license__ = "LGPL"
+
+import orca.chat as chat
+
+########################################################################
+# #
+# The Pidgin chat class. #
+# #
+########################################################################
+
+class Chat(chat.Chat):
+
+ def __init__(self, script, buddyListAncestries):
+
+ chat.Chat.__init__(self, script, buddyListAncestries)
+
+ def isTypingStatusChangedEvent(self, event):
+ """Returns True if event is associated with a change in typing status.
+
+ Arguments:
+ - event: the accessible event being examined
+ """
+
+ if not event.type.startswith("object:text-changed:insert"):
+ return False
+
+ # Bit of a hack. Pidgin inserts text into the chat history when the
+ # user is typing. We seem able to (more or less) reliably distinguish
+ # this text via its attributes because these attributes are absent
+ # from user inserted text -- no matter how that text is formatted.
+ #
+ attr, start, end = \
+ self._script.utilities.textAttributes(event.source, event.detail1)
+
+ if float(attr.get('scale', '1')) < 1 \
+ or int(attr.get('weight', '400')) < 400:
+ return True
+
+ return False
diff --git a/src/orca/scripts/apps/pidgin/script.py b/src/orca/scripts/apps/pidgin/script.py
index ce2a675..5d5c7db 100644
--- a/src/orca/scripts/apps/pidgin/script.py
+++ b/src/orca/scripts/apps/pidgin/script.py
@@ -1,6 +1,7 @@
# Orca
#
# Copyright 2004-2008 Sun Microsystems Inc.
+# Copyright 2010 Joanmarie Diggs
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
@@ -17,92 +18,33 @@
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
# Boston MA 02110-1301 USA.
-"""Custom script for pidgin. This provides the ability for Orca to
-monitor both the IM input and IM output text areas at the same time.
-
-The following script specific key sequences are supported:
-
- Insert-h - Toggle whether we prefix chat room messages with
- the name of the chat room.
- Insert-[1-9] - Speak and braille a previous chat room message.
-"""
+"""Custom script for pidgin."""
__id__ = "$Id$"
__version__ = "$Revision$"
__date__ = "$Date$"
-__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
+__copyright__ = "Copyright (c) 2010 Joanmarie Diggs."
__license__ = "LGPL"
-import gtk
import pyatspi
-import orca.debug as debug
import orca.default as default
-import orca.input_event as input_event
-import orca.keybindings as keybindings
-import orca.orca_state as orca_state
-import orca.settings as settings
import orca.speech as speech
from orca.orca_i18n import _
+from chat import Chat
from script_utilities import Utilities
from speech_generator import SpeechGenerator
-import script_settings
########################################################################
# #
-# Ring List. A fixed size circular list by Flavio Catalani #
-# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/435902 #
-# #
-########################################################################
-
-class RingList:
- def __init__(self, length):
- self.__data__ = []
- self.__full__ = 0
- self.__max__ = length
- self.__cur__ = 0
-
- def append(self, x):
- if self.__full__ == 1:
- for i in range (0, self.__cur__ - 1):
- self.__data__[i] = self.__data__[i + 1]
- self.__data__[self.__cur__ - 1] = x
- else:
- self.__data__.append(x)
- self.__cur__ += 1
- if self.__cur__ == self.__max__:
- self.__full__ = 1
-
- def get(self):
- return self.__data__
-
- def remove(self):
- if (self.__cur__ > 0):
- del self.__data__[self.__cur__ - 1]
- self.__cur__ -= 1
-
- def size(self):
- return self.__cur__
-
- def maxsize(self):
- return self.__max__
-
- def __str__(self):
- return ''.join(self.__data__)
-
-
-########################################################################
-# #
-# The Gaim script class. #
+# The Pidgin script class. #
# #
########################################################################
class Script(default.Script):
- MESSAGE_LIST_LENGTH = 9
-
def __init__(self, app):
"""Creates a new script for the given application.
@@ -110,474 +52,75 @@ class Script(default.Script):
- app: the application to create a script for.
"""
- # Set the debug level for all the methods in this script.
+ # So we can take an educated guess at identifying the buddy list.
#
- self.debugLevel = debug.LEVEL_FINEST
+ self._buddyListAncestries = [[pyatspi.ROLE_TREE_TABLE,
+ pyatspi.ROLE_SCROLL_PANE,
+ pyatspi.ROLE_FILLER,
+ pyatspi.ROLE_PAGE_TAB,
+ pyatspi.ROLE_PAGE_TAB_LIST,
+ pyatspi.ROLE_FILLER,
+ pyatspi.ROLE_FRAME]]
- # Create two cyclic lists; one that will contain the previous
- # chat room messages and the other that will contain the names
- # of the associated chat rooms.
- #
- self.allPreviousMessages = RingList(Script.MESSAGE_LIST_LENGTH)
- self.previousChatRoomNames = RingList(Script.MESSAGE_LIST_LENGTH)
-
- # Create a dictionary that will be used to contain chat room
- # specific message histories. The key will be the chat room
- # name and the value will be a cyclic list of previous messages
- # for that chat room.
- #
- self.chatRoomMessages = {}
-
- # Initially populate the cyclic lists with empty strings.
- #
- i = 0
- while i < self.allPreviousMessages.maxsize():
- self.allPreviousMessages.append("")
- i += 1
-
- i = 0
- while i < self.previousChatRoomNames.maxsize():
- self.previousChatRoomNames.append("")
- i += 1
-
- # Keep track of the various text areas for chatting.
- # The key is the tab and the value is the text area where
- # the chat occurs.
- #
- self.chatAreas = {}
-
- # Button to handle preferences setting saying whether we want to
- # prefix the chat room name for our messages.
- #
- self.speakNameCheckButton = None
+ default.Script.__init__(self, app)
- # Keep track of the last status message to see if it's changed.
- #
- self.lastStatus = None
+ def getChat(self):
+ """Returns the 'chat' class for this script."""
- # To make pylint happy.
- #
- self.focusedChannelRadioButton = None
- self.allChannelsRadioButton = None
- self.allMessagesRadioButton = None
- self.buddyTypingCheckButton = None
- self.chatRoomHistoriesCheckButton = None
+ return Chat(self, self._buddyListAncestries)
- default.Script.__init__(self, app)
+ def getSpeechGenerator(self):
+ """Returns the speech generator for this script. """
- def getListeners(self):
- """Add in an AT-SPI event listener "object:children-changed:"
- events, for this script.
- """
+ return SpeechGenerator(self)
- listeners = default.Script.getListeners(self)
- listeners["object:children-changed:"] = self.onChildrenChanged
+ def getUtilities(self):
+ """Returns the utilites for this script."""
- return listeners
+ return Utilities(self)
def setupInputEventHandlers(self):
"""Defines InputEventHandler fields for this script that can be
- called by the key and braille bindings. In this particular case,
- we just want to be able to add a handler to toggle whether we
- prefix chat room messages with the name of the chat room.
+ called by the key and braille bindings. Here we need to add the
+ handlers for chat functionality.
"""
- debug.println(self.debugLevel, "pidgin.setupInputEventHandlers.")
-
default.Script.setupInputEventHandlers(self)
- self.inputEventHandlers["togglePrefixHandler"] = \
- input_event.InputEventHandler(
- Script.togglePrefix,
- _("Toggle whether we prefix chat room messages with " \
- "the name of the chat room."))
-
- self.inputEventHandlers["toggleBuddyTypingHandler"] = \
- input_event.InputEventHandler(
- Script.toggleBuddyTyping,
- _("Toggle whether we announce when our buddies are typing."))
-
- self.inputEventHandlers["toggleMessageHistoriesHandler"] = \
- input_event.InputEventHandler(
- Script.toggleMessageHistories,
- _("Toggle whether we provide chat room specific message " \
- "histories."))
-
- # Add the chat room message history event handler.
- #
- self.inputEventHandlers["reviewMessage"] = \
- input_event.InputEventHandler(
- Script.readPreviousMessage,
- _("Speak and braille a previous chat room message."))
+ self.inputEventHandlers.update(self.chat.inputEventHandlers)
def getKeyBindings(self):
- """Defines the key bindings for this script. Setup the default
- key bindings, then add one in for toggling whether we prefix
- chat room messages with the name of the chat room.
+ """Defines the key bindings for this script. Here we need to add
+ the keybindings associated with chat functionality.
Returns an instance of keybindings.KeyBindings.
"""
- debug.println(self.debugLevel, "pidgin.getKeyBindings.")
-
keyBindings = default.Script.getKeyBindings(self)
- keyBindings.add(
- keybindings.KeyBinding(
- "h",
- settings.defaultModifierMask,
- settings.ORCA_MODIFIER_MASK,
- self.inputEventHandlers["togglePrefixHandler"]))
-
- keyBindings.add(
- keybindings.KeyBinding(
- "",
- settings.defaultModifierMask,
- settings.NO_MODIFIER_MASK,
- self.inputEventHandlers["toggleBuddyTypingHandler"]))
-
- keyBindings.add(
- keybindings.KeyBinding(
- "",
- settings.defaultModifierMask,
- settings.NO_MODIFIER_MASK,
- self.inputEventHandlers["toggleMessageHistoriesHandler"]))
-
- # keybindings to provide chat room message history.
- #
- messageKeys = [ "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9" ]
- for messageKey in messageKeys:
- keyBindings.add(
- keybindings.KeyBinding(
- messageKey,
- settings.defaultModifierMask,
- settings.ORCA_MODIFIER_MASK,
- self.inputEventHandlers["reviewMessage"]))
- return keyBindings
+ bindings = self.chat.keyBindings
+ for keyBinding in bindings.keyBindings:
+ keyBindings.add(keyBinding)
- def getSpeechGenerator(self):
- """Returns the speech generator for this script.
- """
-
- return SpeechGenerator(self)
-
- def getUtilities(self):
- """Returns the utilites for this script."""
-
- return Utilities(self)
+ return keyBindings
def getAppPreferencesGUI(self):
"""Return a GtkVBox contain the application unique configuration
- GUI items for the current application.
+ GUI items for the current application. The chat-related options
+ get created by the chat module.
"""
- vbox = gtk.VBox(False, 0)
- vbox.set_border_width(12)
- gtk.Widget.show(vbox)
-
- # Translators: If this checkbox is checked, then Orca will speak
- # the name of the chat room.
- #
- label = _("_Speak Chat Room name")
- self.speakNameCheckButton = gtk.CheckButton(label)
- gtk.Widget.show(self.speakNameCheckButton)
- gtk.Box.pack_start(vbox, self.speakNameCheckButton, False, False, 0)
- gtk.ToggleButton.set_active(self.speakNameCheckButton,
- script_settings.prefixChatMessage)
-
- # Translators: If this checkbox is checked, then Orca will tell
- # you when one of your buddies is typing a message.
- #
- label = _("Announce when your _buddies are typing")
- self.buddyTypingCheckButton = gtk.CheckButton(label)
- gtk.Widget.show(self.buddyTypingCheckButton)
- gtk.Box.pack_start(vbox, self.buddyTypingCheckButton, False, False, 0)
- gtk.ToggleButton.set_active(self.buddyTypingCheckButton,
- script_settings.announceBuddyTyping)
-
- # Translators: If this checkbox is checked, then Orca will provide
- # the user with chat room specific message histories rather than just
- # a single history which contains the latest messages from all the
- # chat rooms that they are currently in.
- #
- label = _("Provide chat room specific _message histories")
- self.chatRoomHistoriesCheckButton = gtk.CheckButton(label)
- gtk.Widget.show(self.chatRoomHistoriesCheckButton)
- gtk.Box.pack_start(vbox, self.chatRoomHistoriesCheckButton,
- False, False, 0)
- gtk.ToggleButton.set_active(self.chatRoomHistoriesCheckButton,
- script_settings.chatRoomHistories)
-
- # "Speak Messages" frame.
- #
- messagesFrame = gtk.Frame()
- gtk.Widget.show(messagesFrame)
- gtk.Box.pack_start(vbox, messagesFrame, False, False, 5)
-
- messagesAlignment = gtk.Alignment(0.5, 0.5, 1, 1)
- gtk.Widget.show(messagesAlignment)
- gtk.Container.add(messagesFrame, messagesAlignment)
- gtk.Alignment.set_padding(messagesAlignment, 0, 0, 12, 0)
-
- messagesVBox = gtk.VBox(False, 0)
- gtk.Widget.show(messagesVBox)
- gtk.Container.add(messagesAlignment, messagesVBox)
-
- # Translators: Orca will speak all new chat messages as they appear
- # irrespective of whether the pidgin application currently has focus.
- # This is the default behaviour.
- #
- self.allMessagesRadioButton = gtk.RadioButton(None, _("All cha_nnels"))
- gtk.Widget.show(self.allMessagesRadioButton)
- gtk.Box.pack_start(messagesVBox, self.allMessagesRadioButton,
- False, False, 0)
- gtk.ToggleButton.set_active(self.allMessagesRadioButton,
- (script_settings.speakMessages == \
- script_settings.SPEAK_ALL_MESSAGES))
-
-
- # Translators: Orca will speak only new chat messages for the channel
- # that currently has focus, irrespective of whether the pidgin
- # application has focus.
- #
- self.focusedChannelRadioButton = gtk.RadioButton( \
- self.allMessagesRadioButton, \
- _("A channel only if its _window is active"))
- gtk.Widget.show(self.focusedChannelRadioButton)
- gtk.Box.pack_start(messagesVBox, self.focusedChannelRadioButton,
- False, False, 0)
- gtk.ToggleButton.set_active(self.focusedChannelRadioButton,
- (script_settings.speakMessages == \
- script_settings.SPEAK_CHANNEL_WITH_FOCUS))
-
- # Translators: Orca will speak new chat messages for all channels
- # only when the pidgin application has focus.
- #
- self.allChannelsRadioButton = gtk.RadioButton( \
- self.allMessagesRadioButton,
- _("All channels when an_y Pidgin window is active"))
- gtk.Widget.show(self.allChannelsRadioButton)
- gtk.Box.pack_start(messagesVBox, self.allChannelsRadioButton,
- False, False, 0)
- gtk.ToggleButton.set_active(self.allChannelsRadioButton,
- (script_settings.speakMessages == \
- script_settings.SPEAK_ALL_CHANNELS_WHEN_FOCUSED))
-
- # Translators: this is the title of a panel holding options for
- # how messages in the pidgin chat rooms should be spoken.
- #
- messagesLabel = gtk.Label("<b>%s</b>" % _("Speak messages from"))
- gtk.Widget.show(messagesLabel)
- gtk.Frame.set_label_widget(messagesFrame, messagesLabel)
- messagesFrame.set_shadow_type(gtk.SHADOW_NONE)
- gtk.Label.set_use_markup(messagesLabel, True)
-
- return vbox
+ return self.chat.getAppPreferencesGUI()
def setAppPreferences(self, prefs):
"""Write out the application specific preferences lines and set the
- new values.
+ new values. The chat-related options get written out by the chat
+ module.
Arguments:
- prefs: file handle for application preferences.
"""
- prefix = "orca.scripts.apps.pidgin.script_settings"
- script_settings.prefixChatMessage = \
- self.speakNameCheckButton.get_active()
- prefs.writelines("\n")
- prefs.writelines("%s.prefixChatMessage = %s\n" % \
- (prefix, script_settings.prefixChatMessage))
-
- script_settings.announceBuddyTyping = \
- self.buddyTypingCheckButton.get_active()
- prefs.writelines("%s.announceBuddyTyping = %s\n" % \
- (prefix, script_settings.announceBuddyTyping))
-
- script_settings.chatRoomHistories = \
- self.chatRoomHistoriesCheckButton.get_active()
- prefs.writelines("%s.chatRoomHistories = %s\n" % \
- (prefix, script_settings.chatRoomHistories))
-
- if self.allMessagesRadioButton.get_active():
- script_settings.speakMessages = \
- script_settings.SPEAK_ALL_MESSAGES
- option = ("%s.SPEAK_ALL_MESSAGES" % prefix)
- elif self.focusedChannelRadioButton.get_active():
- script_settings.speakMessages = \
- script_settings.SPEAK_CHANNEL_WITH_FOCUS
- option = ("%s.SPEAK_CHANNEL_WITH_FOCUS" % prefix)
- elif self.allChannelsRadioButton.get_active():
- script_settings.speakMessages = \
- script_settings.SPEAK_ALL_CHANNELS_WHEN_FOCUSED
- option = ("%s.SPEAK_ALL_CHANNELS_WHEN_FOCUSED" % prefix)
- prefs.writelines("\n")
- prefs.writelines("%s.speakMessages = %s\n" % (prefix, option))
-
- def getAppState(self):
- """Returns an object that can be passed to setAppState. This
- object will be use by setAppState to restore any state information
- that was being maintained by the script."""
- return [default.Script.getAppState(self),
- self.allPreviousMessages,
- self.previousChatRoomNames,
- self.chatRoomMessages,
- self.chatAreas]
-
- def setAppState(self, appState):
- """Sets the application state using the given appState object.
-
- Arguments:
- - appState: an object obtained from getAppState
- """
- try:
- [defaultAppState,
- self.allPreviousMessages,
- self.previousChatRoomNames,
- self.chatRoomMessages,
- self.chatAreas] = appState
- default.Script.setAppState(self, defaultAppState)
- except:
- debug.printException(debug.LEVEL_WARNING)
-
- def togglePrefix(self, inputEvent):
- """ Toggle whether we prefix chat room messages with the name of
- the chat room.
-
- Arguments:
- - inputEvent: if not None, the input event that caused this action.
- """
-
- debug.println(self.debugLevel, "pidgin.togglePrefix.")
-
- line = _("speak chat room name.")
- script_settings.prefixChatMessage = \
- not script_settings.prefixChatMessage
- if not script_settings.prefixChatMessage:
- line = _("Do not speak chat room name.")
-
- self.presentMessage(line)
-
- return True
-
- def toggleBuddyTyping(self, inputEvent):
- """ Toggle whether we announce when our buddies are typing a message.
-
- Arguments:
- - inputEvent: if not None, the input event that caused this action.
- """
-
- debug.println(self.debugLevel, "pidgin.toggleBuddyTyping.")
-
- line = _("announce when your buddies are typing.")
- script_settings.announceBuddyTyping = \
- not script_settings.announceBuddyTyping
- if not script_settings.announceBuddyTyping:
- line = _("Do not announce when your buddies are typing.")
-
- self.presentMessage(line)
-
- return True
-
- def toggleMessageHistories(self, inputEvent):
- """ Toggle whether we provide chat room specific message histories.
-
- Arguments:
- - inputEvent: if not None, the input event that caused this action.
- """
-
- debug.println(self.debugLevel, "pidgin.toggleMessageHistories.")
-
- line = _("Provide chat room specific message histories.")
- script_settings.chatRoomHistories = \
- not script_settings.chatRoomHistories
- if not script_settings.chatRoomHistories:
- line = _("Do not provide chat room specific message histories.")
-
- self.presentMessage(line)
-
- return True
-
- def utterMessage(self, chatRoomName, message, hasFocus=True):
- """ Speak/braille a chat room message.
-
- Arguments:
- - chatRoomName: name of the chat room this message came from.
- - message: the chat room message.
- """
-
- # Only speak/braille the new message if it matches how the user
- # wants chat messages spoken.
- #
- if script_settings.speakMessages == \
- script_settings.SPEAK_ALL_CHANNELS_WHEN_FOCUSED \
- and orca_state.activeScript != self:
- return
- elif script_settings.speakMessages == \
- script_settings.SPEAK_CHANNEL_WITH_FOCUS \
- and not hasFocus:
- return
-
- text = ""
- if script_settings.prefixChatMessage:
- if chatRoomName and chatRoomName != "":
- text += _("Message from chat room %s") % chatRoomName + " "
- if message and message != "":
- text += message
-
- if len(text.strip()):
- speech.speak(text)
- self.displayBrailleMessage(text)
-
- def readPreviousMessage(self, inputEvent):
- """ Speak/braille a previous chat room message. Up to nine
- previous messages are kept.
-
- Arguments:
- - inputEvent: if not None, the input event that caused this action.
- """
-
- debug.println(self.debugLevel, "pidgin.readPreviousMessage.")
-
- i = int(inputEvent.event_string[1:])
- messageNo = Script.MESSAGE_LIST_LENGTH - i
-
- if script_settings.chatRoomHistories:
- chatRoomTab = self.getChatRoomTab(orca_state.locusOfFocus)
- chatRoomName = self.utilities.displayedText(chatRoomTab)
- if not chatRoomName in self.chatRoomMessages:
- return
- messages = self.chatRoomMessages[chatRoomName].get()
- else:
- chatRoomNames = self.previousChatRoomNames.get()
- chatRoomName = chatRoomNames[messageNo]
- messages = self.allPreviousMessages.get()
-
- message = messages[messageNo]
- self.utterMessage(chatRoomName, message)
-
- def getChatRoomTab(self, obj):
- """Walk up the hierarchy until we've found the page tab for this
- chat room, and return that object.
-
- Arguments:
- - obj: the accessible component to start from.
-
- Returns the page tab component for the chat room.
- """
-
- if obj:
- while True:
- if obj:
- if obj.getRole() == pyatspi.ROLE_APPLICATION:
- break
- elif obj.getRole() == pyatspi.ROLE_PAGE_TAB:
- return obj
- else:
- obj = obj.parent
- else:
- break
-
- return None
+ self.chat.setAppPreferences(prefs)
def onChildrenChanged(self, event):
"""Called whenever a child object changes in some way.
@@ -590,8 +133,8 @@ class Script(default.Script):
# has, then announce its name. See bug #469098 for more details.
#
if event.type.startswith("object:children-changed:add"):
- rolesList = [pyatspi.ROLE_PAGE_TAB_LIST, \
- pyatspi.ROLE_FILLER, \
+ rolesList = [pyatspi.ROLE_PAGE_TAB_LIST,
+ pyatspi.ROLE_FILLER,
pyatspi.ROLE_FRAME]
if self.utilities.hasMatchingHierarchy(event.source, rolesList):
# As it's possible to get this component hierarchy in other
@@ -612,28 +155,17 @@ class Script(default.Script):
line = _("New chat tab %s") % child.name
speech.speak(line)
- def isBuddyListEvent(self, event):
- """If pidgin gets a status changed message for one of the users
- buddies then just ignore it. See bug #525644 for more details.
+ def onNameChanged(self, event):
+ """Called whenever a property on an object changes.
Arguments:
- event: the Event
-
- Return an indication of whether this is a buddy list event.
"""
- isBuddyListEvent = False
- rolesList = [pyatspi.ROLE_TABLE_CELL, \
- pyatspi.ROLE_TABLE_CELL, \
- pyatspi.ROLE_TREE_TABLE, \
- pyatspi.ROLE_SCROLL_PANE, \
- pyatspi.ROLE_FILLER, \
- pyatspi.ROLE_PAGE_TAB, \
- pyatspi.ROLE_PAGE_TAB_LIST]
- if self.utilities.hasMatchingHierarchy(event.source, rolesList):
- isBuddyListEvent = True
-
- return isBuddyListEvent
+ if self.chat.isInBuddyList(event.source):
+ return
+ else:
+ default.Script.onNameChanged(self, event)
def onTextDeleted(self, event):
"""Called whenever text is deleted from an object.
@@ -642,22 +174,18 @@ class Script(default.Script):
- event: the Event
"""
- if self.isBuddyListEvent(event):
+ if self.chat.isInBuddyList(event.source):
return
else:
default.Script.onTextDeleted(self, event)
- def onNameChanged(self, event):
- """Called whenever a property on an object changes.
-
- Arguments:
- - event: the Event
- """
+ def onTextInserted(self, event):
+ """Called whenever text is added to an object."""
- if self.isBuddyListEvent(event):
+ if self.chat.presentInsertedText(event):
return
- else:
- default.Script.onNameChanged(self, event)
+
+ default.Script.onTextInserted(self, event)
def onValueChanged(self, event):
"""Called whenever an object's value changes. Currently, the
@@ -667,181 +195,23 @@ class Script(default.Script):
- event: the Event
"""
- if self.isBuddyListEvent(event):
+ if self.chat.isInBuddyList(event.source):
return
else:
default.Script.onValueChanged(self, event)
- def onTextInserted(self, event):
- """Called whenever text is inserted into one of Gaim's text
- objects. If the object is an instant message or chat, speak
- the text. If we're not watching anything, do the default
- behavior.
-
- Arguments:
- - event: the text inserted Event
- """
-
- if self.isBuddyListEvent(event):
- return
-
- # Handle non-chat text areas (e.g., adding a new account)
- # the default way.
- #
- state = event.source.getState()
- if state.contains(pyatspi.STATE_EDITABLE) \
- and state.contains(pyatspi.STATE_SINGLE_LINE):
- default.Script.onTextInserted(self, event)
- return
-
- chatRoomTab = self.getChatRoomTab(event.source)
- if not chatRoomTab:
- default.Script.onTextInserted(self, event)
- return
-
- # [[[TODO: HACK - it looks as though the GAIM chat area may
- # not start emitting text inserted events until we tickle it
- # by looking at it in the hierarchy. The simple workaround of
- # entering flat review and exiting does this. So, we tickle
- # the hierarchy here. We probably should be trying somewhere
- # else since we may miss the first message in a chat area. In
- # addition, this is a source of a very small memory leak since
- # we do not free up the entries when the tab goes away. One
- # would have to engage in hundreds of chats with hundreds of
- # different people from the same instance of pidgin for that
- # memory leak to have an issue here. One thing we could do if
- # that is deemed a severe enough problem is to check for
- # children-changed events and clean up in that.]]]
- #
- chatArea = None
- if not chatRoomTab in self.chatAreas:
- # Different message types (AIM, IRC ...) have a different
- # component hierarchy for their chat rooms. By testing
- # with AIM and IRC, we've found that the messages area for
- # those two type of chats has an index that is the penultimate
- # text field. Hopefully this is true for other types of chat
- # as well, but is currently untested.
- #
- allTextFields = self.utilities.descendantsWithRole(
- chatRoomTab, pyatspi.ROLE_TEXT, False)
-
- # Pidgin 2.7 includes a Find text object, hidden by default.
- # We can identify (and eliminate) it by STATE_SINGLE_LINE.
- #
- allTextFields = \
- filter(lambda o:
- not o.getState().contains(pyatspi.STATE_SINGLE_LINE),
- allTextFields)
-
- index = len(allTextFields) - 2
- if index >= 0:
- self.chatAreas[chatRoomTab] = allTextFields[index]
- chatArea = self.chatAreas[chatRoomTab]
- else:
- chatArea = self.chatAreas[chatRoomTab]
+ def onWindowActivated(self, event):
+ """Called whenever a toplevel window is activated."""
- # Create a new cyclic message list for this chat room name
- # (if one doesn't already exist) and populate it with empty
- # strings.
+ # Hack to "tickle" the accessible hierarchy. Otherwise, the
+ # events we need to present text added to the chatroom are
+ # missing.
#
- chatRoomName = self.utilities.displayedText(chatRoomTab)
- if not chatRoomName in self.chatRoomMessages:
- self.chatRoomMessages[chatRoomName] = \
- RingList(Script.MESSAGE_LIST_LENGTH)
- i = 0
- while i < self.chatRoomMessages[chatRoomName].maxsize():
- self.chatRoomMessages[chatRoomName].append("")
- i += 1
-
- lastKey, mods = self.utilities.lastKeyAndModifiers()
- if event.source and (event.source == chatArea):
- # We always automatically go back to focus tracking mode when
- # someone sends us a message.
- #
- if self.flatReviewContext:
- self.toggleFlatReviewMode()
-
- message = self.utilities.substring(event.source,
- event.detail1,
- event.detail1 + event.detail2)
- if message and message[0] == "\n":
- message = message[1:]
-
- chatRoomName = self.utilities.displayedText(chatRoomTab)
-
- # If the user doesn't want announcements for when their buddies
- # are typing (or have stopped typing), and this is such a message,
- # then just return. The only reliable way to identify such text
- # is by the scale. This attribute seems to have been removed by
- # pidgin, so we'll also check the weight. We also want to store
- # the last message because msn seems to be sending a constant
- # stream of "is typing" updates.
- #
- attr, start, end = \
- self.utilities.textAttributes(event.source, event.detail1)
- if float(attr.get('scale', '1')) < 1 \
- or int(attr.get('weight', '400')) < 400:
- if not script_settings.announceBuddyTyping or \
- self.lastStatus == message:
- return
- self.lastStatus = message
- else:
- self.lastStatus = None
-
- # If the new message came from the room with focus, we don't
- # want to speak its name even if script_settings.prefixChatMessage
- # is enabled.
- #
- state = event.source.getState()
- hasFocus = state.contains(pyatspi.STATE_SHOWING)
- if hasFocus:
- chatRoomName = ""
- self.utterMessage(chatRoomName, message, hasFocus)
-
- # Add the latest message to the list of saved ones. For each
- # one added, the oldest one automatically gets dropped off.
- # We don't want to do this for the status messages however.
- #
- if not self.lastStatus:
- chatRoomName = self.utilities.displayedText(chatRoomTab)
-
- self.allPreviousMessages.append(message)
- self.previousChatRoomNames.append(chatRoomName)
-
- self.chatRoomMessages[chatRoomName].append(message)
-
- elif lastKey == "Tab" and event.any_data and event.any_data != "\t":
- # This is autocompleted text (the name of a user in an IRC
- # chatroom). The default script isn't announcing it because
- # it's not selected.
- #
- text = event.any_data
- if text.decode("UTF-8").isupper():
- speech.speak(text, self.voices[settings.UPPERCASE_VOICE])
- else:
- speech.speak(text)
-
- else:
- # Pass the event onto the parent class to be handled in the
- # default way.
- #
- default.Script.onTextInserted(self, event)
-
- def isInBuddyList(self, obj):
- """Determines whether or not this object is in the buddy list.
-
- Arguments:
- -obj: the Accessible object
- """
+ allPageTabs = self.utilities.descendantsWithRole(
+ event.source, pyatspi.ROLE_PAGE_TAB)
- rolesList = [pyatspi.ROLE_TABLE_CELL,
- pyatspi.ROLE_TREE_TABLE,
- pyatspi.ROLE_SCROLL_PANE,
- pyatspi.ROLE_FILLER,
- pyatspi.ROLE_PAGE_TAB]
+ default.Script.onWindowActivated(self, event)
- return self.utilities.hasMatchingHierarchy(obj, rolesList)
-
def visualAppearanceChanged(self, event, obj):
"""Called when the visual appearance of an object changes.
Overridden here because we get object:state-changed:expanded
@@ -852,7 +222,7 @@ class Script(default.Script):
- obj: the Accessible whose visual appearance changed.
"""
- if self.isInBuddyList(obj) \
+ if self.chat.isInBuddyList(obj) \
and event.type.startswith("object:state-changed:expanded"):
# The event is associated with the invisible cell. Set it
diff --git a/src/orca/scripts/apps/pidgin/script_utilities.py b/src/orca/scripts/apps/pidgin/script_utilities.py
index 044d094..7383662 100644
--- a/src/orca/scripts/apps/pidgin/script_utilities.py
+++ b/src/orca/scripts/apps/pidgin/script_utilities.py
@@ -68,7 +68,7 @@ class Utilities(script_utilities.Utilities):
Returns: a list of all the child nodes
"""
- if not self._script.isInBuddyList(obj):
+ if not self._script.chat.isInBuddyList(obj):
return script_utilities.Utilities.childNodes(self, obj)
try:
@@ -124,7 +124,7 @@ class Utilities(script_utilities.Utilities):
if not obj:
return -1
- if not self._script.isInBuddyList(obj):
+ if not self._script.chat.isInBuddyList(obj):
return script_utilities.Utilities.nodeLevel(self, obj)
try:
diff --git a/src/orca/scripts/apps/pidgin/speech_generator.py b/src/orca/scripts/apps/pidgin/speech_generator.py
index 6d526dc..2e88848 100644
--- a/src/orca/scripts/apps/pidgin/speech_generator.py
+++ b/src/orca/scripts/apps/pidgin/speech_generator.py
@@ -43,7 +43,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
def _generateExpandableState(self, obj, **args):
result = []
- if self._script.isInBuddyList(obj):
+ if self._script.chat.isInBuddyList(obj):
# The Pidgin buddy list consists of two columns. The
# column which is set as the expander column and which
# also contains the node relationship is hidden. Hidden
@@ -68,7 +68,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
def _generateNumberOfChildren(self, obj, **args):
result = []
- if self._script.isInBuddyList(obj):
+ if self._script.chat.isInBuddyList(obj):
# The Pidgin buddy list consists of two columns. The
# column which is set as the expander column and which
# also contains the node relationship is hidden. Hidden
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]