poedit.py 4.65 KB
#appModules/poedit.py
#A part of NonVisual Desktop Access (NVDA)
#Copyright (C) 2012-2013 Mesar Hameed, NV Access Limited
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

"""App module for Poedit.
"""

import api
import appModuleHandler
import controlTypes
import displayModel
import textInfos
import tones
import ui
from NVDAObjects.IAccessible import sysListView32
import windowUtils
import NVDAObjects.IAccessible
import winUser


def getPath(obj, ancestor):
	"""Gets the path of the object with respect to its ancestor.
	the ancestor is typically the forground object.

	@returns: A list of coordinates relative to the ansestor.
	@rtype: L{list}
	"""
	path = []
	cancel = 0
	if obj == stopObj: return []
	p = obj
	while p != stopObj:
		counter = 0
		while p.previous:
			p = p.previous
			counter += 1
			cancel += 1
			# Looks like we have an infinite ancestry, so get out
			if cancel == 50: return [-1]
		path.append(counter)
		p = p.parent
	path.reverse()
	return path

def fetchObject(obj, path):
	"""Fetch the child object  described by path.
	@returns: requested object if found, or None
	@rtype: L{NVDAObjects.NVDAObject}
	"""
	path.reverse()
	p = obj
	while len(path) and p.firstChild:
		p = p.firstChild
		steps = path.pop()
		i=0
		while i<steps and p.next: 
			p = p.next
			i += 1
		# the path requests us to look for further siblings, but none found.
		if i<steps: return None
	# the path requests us to look for further children, but none found.
	if len(path): return None
	return p


class AppModule(appModuleHandler.AppModule):

	def script_reportAutoCommentsWindow(self,gesture):
		obj = fetchObject(api.getForegroundObject(), [2, 0, 1, 0, 1, 0, 1])
		if obj and obj.windowControlID != 101:
			try:
				obj = obj.next.firstChild
			except AttributeError:
				obj = None
		elif obj:
			obj = obj.firstChild
		if obj:
			try:
				ui.message(obj.name + " " + obj.value)
			except:
				# Translators: this message is reported when there are no 
				# notes for translators to be presented to the user in Poedit.
				ui.message(_("No notes for translators."))
		else:
			# Translators: this message is reported when NVDA is unable to find 
			# the 'Notes for translators' window in poedit.
			ui.message(_("Could not find Notes for translators window."))
	# Translators: The description of an NVDA command for Poedit.
	script_reportAutoCommentsWindow.__doc__ = _("Reports any notes for translators")

	def script_reportCommentsWindow(self,gesture):
		try:
			obj = NVDAObjects.IAccessible.getNVDAObjectFromEvent(
				windowUtils.findDescendantWindow(api.getForegroundObject().windowHandle, visible=True, controlID=104),
				winUser.OBJID_CLIENT, 0)
		except LookupError:
			# Translators: this message is reported when NVDA is unable to find
			# the 'comments' window in poedit.
			ui.message(_("Could not find comment window."))
			return None
		try:
			ui.message(obj.name + " " + obj.value)
		except:
			# Translators: this message is reported when there are no
			# comments to be presented to the user in the translator
			# comments window in poedit.
			ui.message(_("No comment."))
	# Translators: The description of an NVDA command for Poedit.
	script_reportCommentsWindow.__doc__ = _("Reports any comments in the comments window")

	__gestures = {
		"kb:control+shift+c": "reportCommentsWindow",
		"kb:control+shift+a": "reportAutoCommentsWindow",
	}

	def chooseNVDAObjectOverlayClasses(self, obj, clsList):
		if "SysListView32" in obj.windowClassName and obj.role==controlTypes.ROLE_LISTITEM:
			clsList.insert(0,PoeditListItem)

	def event_NVDAObject_init(self, obj):
		if obj.role == controlTypes.ROLE_EDITABLETEXT and controlTypes.STATE_MULTILINE in obj.states and obj.isInForeground:
			# Oleacc often gets the name wrong.
			# The label object is positioned just above the field on the screen.
			l, t, w, h = obj.location
			try:
				obj.name = NVDAObjects.NVDAObject.objectFromPoint(l + 10, t - 10).name
			except AttributeError:
				pass
			return

class PoeditListItem(sysListView32.ListItem):

	def _get_isBold(self):
		info=displayModel.DisplayModelTextInfo(self,position=textInfos.POSITION_FIRST)
		info.expand(textInfos.UNIT_CHARACTER)
		fields=info.getTextWithFields()
		try:
			return fields[0].field['bold']
		except:
			return False

	def _get_name(self):
		# If this item is untranslated or fuzzy, then it will be bold.
		# Other info on the web says that the background color of 
		# the item changes, but this doesn't seem to be true while testing.
		name = super(PoeditListItem,self).name
		return "* " + name if self.isBold else name

	def event_gainFocus(self):
		super(sysListView32.ListItem, self).event_gainFocus()
		if self.isBold:
			tones.beep(550, 50)