Hi, I think you've used an older version of the app module. I've attached the current app module code just in case you wish to base your patch with it. Cheers, Joseph -----Original Message----- From: nvda-addons-bounce@xxxxxxxxxxxxx [mailto:nvda-addons-bounce@xxxxxxxxxxxxx] On Behalf Of Dylan Neale Sent: Monday, June 16, 2014 5:44 PM To: nvda-addons@xxxxxxxxxxxxx Subject: [nvda-addons] Re: Addon for MS access code review Hi I've attached the file, since I don't have a bitbucket or github account yet. On Tue, Jun 17, 2014 at 12:28 PM, Joseph Lee <joseph.lee22590@xxxxxxxxx> wrote: > > Hello, > > Please send the code (the py file) as an attachment to this list, or if you have Github or Bitbucket, please tell us where to get your code so we can fork it and give you code review.C > > Cheers, > > Joseph > > > > From: nvda-addons-bounce@xxxxxxxxxxxxx [mailto:nvda-addons-bounce@xxxxxxxxxxxxx] On Behalf Of Dylan Neale > Sent: Monday, June 16, 2014 4:52 PM > To: nvda-addons@xxxxxxxxxxxxx > Subject: [nvda-addons] Addon for MS access code review > > > > Hi > > This is my first attempt at improving an addon for NVDA, and most of the code was already written. I have made some changes, and would like to get these reviewed before submitting them to the repo. > > What I've done so far is quite hacky, mainly because I'm not aware of all the NVDA functions yet. It works with access 2013, but not sure about others. > > Do I email the code to this list for review/comments or submit it somewhere else? > > Thanks.
# App module for Microsoft Access # An add-on for NVDA # Copyright 2013 Joseph Lee and NVDA contributors, released under GPL (see copying.txt for more information). # Tested with Access 2010/2013; minimum compatible version should be Access 2007. # JL: Most of the code is not mine - I just pitched the ideas. Thank you Access users and developers for encouragement and contributions. import addonHandler import appModuleHandler from NVDAObjects.IAccessible import IAccessible # Not ready for translations; please remove this flag right before public beta 1 release. import eventHandler import api import ui from controlTypes import STATE_SELECTED class AppModule(appModuleHandler.AppModule): # The app module class for Microsoft Access. def getColumnHeader(self): # Locate the parent of this row, go through column headers and see if one of the columns matches the focus.name. # Does not work properly yet - tied to extra events being fired. col = api.getFocusObject() colHeader = col.parent.parent.firstChild colHeaderText = "" for colCompare in colHeader.children: if colCompare.name in col.name: colHeaderText = colCompare.value break return colHeaderText class AccessTableGrid(IAccessible): # The class for table grid. So far, handle row selection announcement. # If column header announcement works, announce this alongside cell coordinates. def event_focusEntered(self): # Ignore row selection messages. obj = api.getFocusObject() return class AccessCellEditableText(IAccessible): # The class for the cell edit field. Since one cannot infer text itself, try using display model and some tricks. pass def chooseNVDAObjectOverlayClasses(self, obj, clsList): if obj.windowClassName == "OGrid": clsList.insert(0, self.AccessTableGrid) elif obj.windowClassName == "OKttbx": clsList.insert(0, self.AccessCellEditableText) # A number of utility functions to work with column selection. def isEdgeColumn(self, obj): # See if we're at the edge column (left-most or right-most). return obj.next == None or obj.previous.previous == None def getFirstSelectedCell(self): # Use linear forward search to find the first selected cell. finder = api.getNavigatorObject().firstChild.children[1] while finder != None: if STATE_SELECTED in finder.states: break else: finder = finder.next selectedCell = finder.firstChild.next while selectedCell != None: if STATE_SELECTED in selectedCell.states: break else: selectedCell = selectedCell.next return selectedCell def getLastSelectedCell(self): # Use reverse linear search (from last to first row) to find the last selected cell. finder = api.getNavigatorObject().firstChild.lastChild while finder != None: if STATE_SELECTED in finder.states: break else: finder = finder.previous selectedCell = finder.lastChild while selectedCell != None: if STATE_SELECTED in selectedCell.states: break else: selectedCell = selectedCell.previous return selectedCell # Column selection commands. def announceSelectedCells(self, first, last): selectedCell = "" if first == last: selectedCell = "Edge of Table: {edgeCell} {edgeCellContent selected".format(edgeCell = first.name, edgeCellContent = first.value) else: selectedCell = "{firstAddress} {firstContent} through {lastAddress} {lastContent} selected".format(firstAddress = first.name, firstContent = first.value, lastAddress = last.name, lastContent = last.value) ui.message(selectedCell) def script_selectRightColumn(self, gesture): gesture.send() obj = api.getNavigatorObject() if obj.name != "Grid": self.announceSelectedCells(obj, obj) if obj.next == None else self.announceSelectedCells(obj, obj.next) else: self.announceSelectedCells(self.getFirstSelectedCell(), self.getLastSelectedCell()) def script_selectLeftColumn(self, gesture): gesture.send() obj = api.getNavigatorObject() if obj.name != "Grid": self.announceSelectedCells(obj, obj) if obj.previous.previous == None else self.announceSelectedCells(obj.previous, obj) else: self.announceSelectedCells(self.getFirstSelectedCell(), self.getLastSelectedCell()) def findSuccessor(self, obj, nextCousin): # Next cousin tells whether we want the next row (true) or previous row (false). successor, row = obj, obj.parent.next if nextCousin else obj.parent.previous if row == None: return None # Retrieve the index. index = 0 for i in obj.parent.children: if i.name == obj.name: index = obj.parent.children.index(i) successor = row.children[index] return successor def script_selectColumnBelow(self, gesture): gesture.send() obj = api.getNavigatorObject() if obj.name != "Grid": successor = self.findSuccessor(obj, True) if obj.parent.next == None: self.announceSelectedCells(obj, obj) if successor != None: self.announceSelectedCells(obj, successor) else: self.announceSelectedCells(self.getFirstSelectedCell(), self.getLastSelectedCell()) def script_selectColumnAbove(self, gesture): gesture.send() obj = api.getNavigatorObject() if obj.name != "Grid": successor = self.findSuccessor(obj, False) if obj.parent.previous.previous == None: self.announceSelectedCells(obj, obj) if successor != None: self.announceSelectedCells(successor, obj) else: self.announceSelectedCells(self.getFirstSelectedCell(), self.getLastSelectedCell()) def script_selectColumns(self, gesture): gesture.send() ui.message("All columns selected") __gestures={ "kb:shift+leftArrow":"selectLeftColumn", "kb:shift+rightArrow":"selectRightColumn", "kb:shift+upArrow":"selectColumnAbove", "kb:shift+downArrow":"selectColumnBelow", "kb:control+space":"selectColumns" }