[orca] More work on flat review: Improve efficiency getting showing table cells
- From: Joanmarie Diggs <joanied src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [orca] More work on flat review: Improve efficiency getting showing table cells
- Date: Wed, 31 Aug 2016 20:13:08 +0000 (UTC)
commit d67067f89cc0f03136c10199cb885a00212ff140
Author: Joanmarie Diggs <jdiggs igalia com>
Date: Wed Aug 31 16:11:23 2016 -0400
More work on flat review: Improve efficiency getting showing table cells
Should solve the problem of non-responsiveness when invoking flat review
in ginormous tables (e.g. Thunderbird folder with 40,000 messages).
src/orca/flat_review.py | 11 +-
src/orca/script_utilities.py | 172 +++++++++-----------
.../scripts/toolkits/Gecko/script_utilities.py | 101 ------------
3 files changed, 83 insertions(+), 201 deletions(-)
---
diff --git a/src/orca/flat_review.py b/src/orca/flat_review.py
index d141e41..6a57745 100644
--- a/src/orca/flat_review.py
+++ b/src/orca/flat_review.py
@@ -991,11 +991,12 @@ class Context:
except NotImplementedError:
pass
- showingDescendants = \
- self.script.utilities.showingDescendants(root)
- if len(showingDescendants):
- for child in showingDescendants:
- zones.extend(self.getShowingZones(child))
+ cells = None
+ if "Table" in pyatspi.listInterfaces(root):
+ cells = self.script.utilities.getVisibleTableCells(root, rootexts)
+ if cells:
+ for cell in cells:
+ zones.extend(self.getShowingZones(cell))
else:
for i in range(0, root.childCount):
child = root.getChildAtIndex(i)
diff --git a/src/orca/script_utilities.py b/src/orca/script_utilities.py
index 076ffd2..15c0fe6 100644
--- a/src/orca/script_utilities.py
+++ b/src/orca/script_utilities.py
@@ -1653,101 +1653,6 @@ class Utilities:
activeDescendant or obj
return self._script.generatorCache[self.REAL_ACTIVE_DESCENDANT][obj]
- def showingDescendants(self, parent):
- """Given a parent that manages its descendants, return a list of
- Accessible children that are actually showing. This algorithm
- was inspired a little by the srw_elements_from_accessible logic
- in Gnopernicus, and makes the assumption that the children of
- an object that manages its descendants are arranged in a row
- and column format.
-
- Arguments:
- - parent: The accessible which manages its descendants
-
- Returns a list of Accessible descendants which are showing.
- """
-
- import sys
-
- if not parent:
- return []
-
- if not parent.getState().contains(pyatspi.STATE_MANAGES_DESCENDANTS) \
- or parent.childCount <= 50:
- return []
-
- try:
- icomponent = parent.queryComponent()
- except NotImplementedError:
- return []
-
- descendants = []
-
- parentExtents = icomponent.getExtents(0)
-
- # [[[TODO: WDW - HACK related to GAIL bug where table column
- # headers seem to be ignored:
- # http://bugzilla.gnome.org/show_bug.cgi?id=325809. The
- # problem is that this causes getAccessibleAtPoint to return
- # the cell effectively below the real cell at a given point,
- # making a mess of everything. So...we just manually add in
- # showing headers for now. The remainder of the logic below
- # accidentally accounts for this offset, yet it should also
- # work when bug 325809 is fixed.]]]
- #
- try:
- table = parent.queryTable()
- except NotImplementedError:
- table = None
-
- if table:
- for i in range(0, table.nColumns):
- header = table.getColumnHeader(i)
- if header:
- extents = header.queryComponent().getExtents(0)
- stateset = header.getState()
- if stateset.contains(pyatspi.STATE_SHOWING) \
- and (extents.x >= 0) and (extents.y >= 0) \
- and (extents.width > 0) and (extents.height > 0) \
- and self.containsRegion(extents, parentExtents):
- descendants.append(header)
-
- # This algorithm goes left to right, top to bottom while attempting
- # to do *some* optimization over queries. It could definitely be
- # improved. The gridSize is a minimal chunk to jump around in the
- # table.
- #
- gridSize = 7
- currentY = parentExtents.y
- while currentY < (parentExtents.y + parentExtents.height):
- currentX = parentExtents.x
- minHeight = sys.maxsize
- index = -1
- while currentX < (parentExtents.x + parentExtents.width):
- child = \
- icomponent.getAccessibleAtPoint(currentX, currentY + 1, 0)
- if child:
- index = child.getIndexInParent()
- extents = child.queryComponent().getExtents(0)
- if extents.x >= 0 and extents.y >= 0:
- newX = extents.x + extents.width
- minHeight = min(minHeight, extents.height)
- if not descendants.count(child):
- descendants.append(child)
- else:
- newX = currentX + gridSize
- else:
- break
- if newX <= currentX:
- currentX += gridSize
- else:
- currentX = newX
- if minHeight == sys.maxsize:
- minHeight = gridSize
- currentY += minHeight
-
- return descendants
-
def statusBar(self, obj):
"""Returns the status bar in the window which contains obj.
@@ -3464,6 +3369,9 @@ class Utilities:
return obj.getRole() in roles
def descendantAtPoint(self, root, x, y, coordType=None):
+ if not root:
+ return None
+
if coordType is None:
coordType = pyatspi.DESKTOP_COORDS
@@ -3473,6 +3381,17 @@ class Utilities:
elif self._treatAsLeafNode(root) or self._boundsIncludeChildren(root):
return None
+ if "Table" in pyatspi.listInterfaces(root):
+ try:
+ component = root.queryComponent()
+ except:
+ child = None
+ else:
+ child = component.getAccessibleAtPoint(x, y, coordType)
+ if child and child != root:
+ return self.descendantAtPoint(child, x, y, coordType)
+ return None
+
for child in root:
obj = self.descendantAtPoint(child, x, y, coordType)
if obj:
@@ -3512,6 +3431,69 @@ class Utilities:
return string, start, end
+ def visibleRows(self, obj, boundingbox):
+ try:
+ table = obj.queryTable()
+ nRows = table.nRows
+ except:
+ return []
+
+ x, y, width, height = boundingbox
+ cell = self.descendantAtPoint(obj, x, y + 1)
+ row, col = self.coordinatesForCell(cell)
+ startIndex = max(0, row)
+
+ # Just in case the row above is a static header row in a scrollable table.
+ try:
+ extents = cell.queryComponent().getExtents(pyatspi.DESKTOP_COORDS)
+ except:
+ nextIndex = startIndex
+ else:
+ cell = self.descendantAtPoint(obj, x, y + extents.height + 1)
+ row, col = self.coordinatesForCell(cell)
+ nextIndex = max(startIndex, row)
+
+ cell = self.descendantAtPoint(obj, x, y + height - 1)
+ row, col = self.coordinatesForCell(cell)
+ if row == -1:
+ row = nRows
+ endIndex = row
+
+ rows = list(range(nextIndex, endIndex))
+ if startIndex not in rows:
+ rows.insert(0, startIndex)
+
+ return rows
+
+ def getVisibleTableCells(self, obj, extents):
+ try:
+ table = obj.queryTable()
+ except:
+ return []
+
+ rows = self.visibleRows(obj, extents)
+ if not rows:
+ return []
+
+ colStartIndex, colEndIndex = self._getTableRowRange(obj)
+ if colStartIndex == colEndIndex:
+ return []
+
+ cells = []
+ for col in range(colStartIndex, colEndIndex):
+ colHeader = table.getColumnHeader(col)
+ if colHeader:
+ cells.append(colHeader)
+ for row in rows:
+ try:
+ cell = table.getAccessibleAt(row, col)
+ except:
+ continue
+ if cell:
+ cells.append(cell)
+
+ return cells
+
def _getTableRowRange(self, obj):
rowCount, columnCount = self.rowAndColumnCount(obj)
startIndex, endIndex = 0, columnCount
diff --git a/src/orca/scripts/toolkits/Gecko/script_utilities.py
b/src/orca/scripts/toolkits/Gecko/script_utilities.py
index 11f1db8..ac80920 100644
--- a/src/orca/scripts/toolkits/Gecko/script_utilities.py
+++ b/src/orca/scripts/toolkits/Gecko/script_utilities.py
@@ -103,104 +103,3 @@ class Utilities(web.Utilities):
msg = "GECKO: Treating %s and %s as same object: %s" % (obj1, obj2, rv)
debug.println(debug.LEVEL_INFO, msg, True)
return rv
-
- def showingDescendants(self, parent):
- """Given an accessible object, returns a list of accessible children
- that are actually showing/visible/pursable for flat review. We're
- overriding the default method here primarily to handle enormous
- tree tables (such as the Thunderbird message list) which do not
- manage their descendants.
-
- Arguments:
- - parent: The accessible which manages its descendants
-
- Returns a list of Accessible descendants which are showing.
- """
-
- if not parent:
- return []
-
- # If this object is not a tree table, if it manages its descendants,
- # or if it doesn't have very many children, let the default script
- # handle it.
- #
- if parent.getRole() != pyatspi.ROLE_TREE_TABLE \
- or parent.getState().contains(pyatspi.STATE_MANAGES_DESCENDANTS) \
- or parent.childCount <= 50:
- return super().showingDescendants(parent)
-
- try:
- table = parent.queryTable()
- except NotImplementedError:
- return []
-
- descendants = []
-
- # First figure out what columns are visible as there's no point
- # in examining cells which we know won't be visible.
- #
- visibleColumns = []
- for i in range(table.nColumns):
- header = table.getColumnHeader(i)
- if self.pursueForFlatReview(header):
- visibleColumns.append(i)
- descendants.append(header)
-
- if not len(visibleColumns):
- return []
-
- # Now that we know in which columns we can expect to find visible
- # cells, try to quickly locate a visible row.
- #
- startingRow = 0
-
- # If we have one or more selected items, odds are fairly good
- # (although not guaranteed) that one of those items happens to
- # be showing. Failing that, calculate how many rows can fit in
- # the exposed portion of the tree table and scroll down.
- #
- selectedRows = table.getSelectedRows()
- for row in selectedRows:
- acc = table.getAccessibleAt(row, visibleColumns[0])
- if self.pursueForFlatReview(acc):
- startingRow = row
- break
- else:
- try:
- tableExtents = parent.queryComponent().getExtents(0)
- acc = table.getAccessibleAt(0, visibleColumns[0])
- cellExtents = acc.queryComponent().getExtents(0)
- except:
- pass
- else:
- rowIncrement = max(1, tableExtents.height / cellExtents.height)
- for row in range(0, table.nRows, rowIncrement):
- acc = table.getAccessibleAt(row, visibleColumns[0])
- if acc and self.pursueForFlatReview(acc):
- startingRow = row
- break
-
- # Get everything after this point which is visible.
- #
- for row in range(startingRow, table.nRows):
- acc = table.getAccessibleAt(row, visibleColumns[0])
- if self.pursueForFlatReview(acc):
- descendants.append(acc)
- for col in visibleColumns[1:len(visibleColumns)]:
- descendants.append(table.getAccessibleAt(row, col))
- else:
- break
-
- # Get everything before this point which is visible.
- #
- for row in range(startingRow - 1, -1, -1):
- acc = table.getAccessibleAt(row, visibleColumns[0])
- if self.pursueForFlatReview(acc):
- thisRow = [acc]
- for col in visibleColumns[1:len(visibleColumns)]:
- thisRow.append(table.getAccessibleAt(row, col))
- descendants[0:0] = thisRow
- else:
- break
-
- return descendants
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]