commit/columnsReview: ABuffEr: NEW: list headers manager (experimental). Minor changes in code and comments.

  • From: commits-noreply@xxxxxxxxxxxxx
  • To: nvda-addons-commits@xxxxxxxxxxxxx
  • Date: Thu, 24 Nov 2016 15:07:53 -0000

1 new commit in columnsReview:

https://bitbucket.org/nvdaaddonteam/columnsreview/commits/41f429179cf1/
Changeset:   41f429179cf1
Branch:      master
User:        ABuffEr
Date:        2016-11-24 15:07:55+00:00
Summary:     NEW: list headers manager (experimental). Minor changes in code 
and comments.

Affected #:  1 file

diff --git a/addon/globalPlugins/columnsReview/__init__.py 
b/addon/globalPlugins/columnsReview/__init__.py
index f447185..769ce8a 100644
--- a/addon/globalPlugins/columnsReview/__init__.py
+++ b/addon/globalPlugins/columnsReview/__init__.py
@@ -7,19 +7,22 @@ by Peter Vagner and contributors
 """
 import addonHandler
 import globalPluginHandler
-import controlTypes
+import controlTypes as ct
 import api
 import ui
 from NVDAObjects.behaviors import RowWithFakeNavigation
 from NVDAObjects.UIA import UIA # For UIA implementations only, chiefly 64-bit.
 from appModules.explorer import GridTileElement, GridListTileElement # 
Specific for Start Screen tiles.
-import scriptHandler
+from scriptHandler import isScriptWaiting, getLastScriptRepeatCount
 import gui
 import os
 from configobj import *
 import globalVars
 import wx
 from msg import message as msg
+import winUser
+#from logHandler import log
+from gui.guiHelper import *
 
 addonHandler.initTranslation()
 
@@ -45,7 +48,8 @@ baseKeys = getBaseKeys()
 
 class ColumnsReview(RowWithFakeNavigation):
        """The main abstract class that generates gestures and calculate index;
-       classes that define new list types must override it"""
+       classes that define new list types must override it,
+       defining (or eventually re-defining) methods of this class."""
 
        # the variable representing tens
        # of current interval (except the last column,
@@ -64,16 +68,19 @@ class ColumnsReview(RowWithFakeNavigation):
                nk = "numpad" if useNumpadKeys else ""
                # bind gestures from 1 to 9
                for n in xrange(1,10):
-                       self.bindGesture("kb:%s+%s%d" %(baseKeys, nk, n), 
"readColumn")
+                       self.bindGesture("kb:%s+%s%d"%(baseKeys, nk, n), 
"readColumn")
                if useNumpadKeys:
                        # map numpadMinus for 10th column
-                       self.bindGesture("kb:%s+numpadMinus" %baseKeys, 
"readColumn")
-                       # map numpadPlus to change interval
-                       self.bindGesture("kb:%s+numpadPlus" %baseKeys, 
"changeInterval")
+                       self.bindGesture("kb:%s+numpadMinus"%baseKeys, 
"readColumn")
+                       # ...numpadPlus to change interval
+                       self.bindGesture("kb:%s+numpadPlus"%baseKeys, 
"changeInterval")
+                       # ...and enter to headers manager
+                       self.bindGesture("kb:%s+numpadEnter"%baseKeys, 
"manageHeaders")
                else:
                        # do same things for no numpad case
-                       self.bindGesture("kb:%s+0" %baseKeys, "readColumn")
-                       self.bindGesture("kb:%s+%s" %(baseKeys, switchChar), 
"changeInterval")
+                       self.bindGesture("kb:%s+0"%baseKeys, "readColumn")
+                       self.bindGesture("kb:%s+%s"%(baseKeys, switchChar), 
"changeInterval")
+                       self.bindGesture("kb:%s+enter"%baseKeys, 
"manageHeaders")
 
        def script_readColumn(self,gesture):
                raise NotImplementedError
@@ -83,20 +90,18 @@ class ColumnsReview(RowWithFakeNavigation):
 
        def getIndex(self, key):
                """get index from key pressed"""
-               # if key is not a digit
-               # that is, "s" from numpadMinus
-               if not key.isdigit():
-                       num = 0
-               else:
-                       # get the digit pressed as index
-                       num = int(key)
+               if key == "numpadMinus":
+                       # we assume minus as 0 for a comfortable use
+                       key = "0"
+               # get the digit pressed as index
+               num = int(key[-1])
                # if num == 0, from numpad or keyboard
-               if num == 0:
+               if not num:
                        # set it to 10, 20, etc
                        num = int(str(self.tens+1)+"0")
                else:
                        # set it to 9, 13, 22, etc
-                       num = int(str(self.tens if self.tens != 0 else 
"")+str(num))
+                       num = int(str(self.tens if self.tens else "")+str(num))
                return num
 
        def script_changeInterval(self, gesture):
@@ -108,14 +113,14 @@ class ColumnsReview(RowWithFakeNavigation):
                        ui.message(_("No more columns available"))
                        return
                # below operations are complicated to explain, so, for example:
-               # in a list with 13 columns (childCount = 13),
-               # we are sure that 13/10+1 return digits except last, that is,
+               # in a list with 13 columns (childCount == 13),
+               # we are sure that 13/10+1 (integer operation) let us to 
control the growth of 
                # the tens (or hundred and tens, etc) in max interval available
                # not considering the last column
                mod = self.childCount/10+1
                # now, we can scroll ten by ten among intervals, using modulus
                self.tens = (self.tens+1)%mod
-               start = str(self.tens if self.tens != 0 else "")+"1"
+               start = str(self.tens if self.tens else "")+"1"
                # nice: announce what is the absolutely last column available
                if self.tens == mod-1:
                        end = str(self.childCount)
@@ -130,12 +135,28 @@ class ColumnsReview(RowWithFakeNavigation):
        # Translators: documentation for script to change interval
        script_changeInterval.__doc__ = _("Cycles between a variable number of 
intervals of ten columns")
 
+       def script_manageHeaders(self, gesture):
+               def run():
+                       gui.mainFrame.prePopup()
+                       d = HeadersDialog(None, self.appModule.appName, 
self.getHeadersParent().children)
+                       if d is not None:
+                               d.Show()
+                       gui.mainFrame.postPopup()
+               wx.CallAfter(run)
+
+       # Translators: documentation for script to manage headers
+       script_manageHeaders.__doc__ = _("Provides a dialog for interactions 
with list column headers")
+
+       def getHeadersParent(self):
+               """return the navigator object with header objects as 
children."""
+               raise NotImplementedError
+
 class ColumnsReview32(ColumnsReview):
 # for SysListView32 or WindowsForms10.SysListView32.app.0.*
 
        def script_readColumn(self, gesture):
                # ask for index
-               num = self.getIndex(gesture.mainKeyName[-1])
+               num = self.getIndex(gesture.mainKeyName.rsplit('+', 1)[-1])
                if num > self.childCount:
                        # Translators: message when digit pressed exceed the 
columns number
                        ui.message(_("No more columns available"))
@@ -143,14 +164,14 @@ class ColumnsReview32(ColumnsReview):
                obj = self.getChild(num-1)
                # generally, an empty name is a None object,
                # in Mozilla, instead, it's a unicode object with length 0
-               if obj is not None and obj.name is not None and len(obj.name) 
!= 0:
+               if obj is not None and obj.name is not None and len(obj.name):
                        # obj.name is the column content
                        content = unicode(obj.name+";")
                else:
                        # Translators: message when cell in specified column is 
empty
                        content = _("Not available;")
                global readHeader, copyHeader
-               if scriptHandler.getLastScriptRepeatCount() != 0 and 
self.lastColumn == num:
+               if getLastScriptRepeatCount() and self.lastColumn == num:
                        header = (unicode(self._getColumnHeader(num)+": ") if 
copyHeader else "")
                        if api.copyToClip(header+content):
                                # Translators: message announcing what was 
copied
@@ -163,15 +184,26 @@ class ColumnsReview32(ColumnsReview):
        # Translators: documentation of script to read columns
        script_readColumn.__doc__ = _("Returns the header and the content of 
the list column at the index corresponding to the number pressed")
 
+       def getHeadersParent(self):
+               return self.parent.children[-1]
+
 class MozillaTable(ColumnsReview32):
-       """Class to manage columns headers in Mozilla list"""
+       """Class to manage column headers in Mozilla list"""
 
        def _getColumnHeader(self, index):
                """Returns the column header in Mozilla applications"""
-               # get the list with headers, excluding last
-               # that is not a header, but for settings only
-               if self.role != controlTypes.ROLE_TREEVIEWITEM:
-                       headers = self.parent.firstChild.children[:-1]
+               # get the list with headers, excluding these
+               # which are not header (i.e. for settings, in Thunderbird)
+               headers = filter(lambda i: i.role == ct.ROLE_TABLECOLUMNHEADER, 
self.getHeadersParent().children)
+               # now, headers are not ordered as on screen,
+               # but we deduce the order thanks to top location of each header
+               headers.sort(key=lambda i: i.location)
+               return headers[index-1].name
+
+       def getHeadersParent(self):
+               # when thread view is disabled
+               if self.role != ct.ROLE_TREEVIEWITEM:
+                       return self.parent.firstChild
                # else, we manage the thread grouping case
                else:
                        # tree-level of current obj
@@ -180,27 +212,14 @@ class MozillaTable(ColumnsReview32):
                        parent = self
                        for n in range(0,int(level)):
                                parent = parent.simpleParent
-                       headers = parent.firstChild.children[:-1]
-               # now, headers are not ordered as on screen,
-               # but we deduce the order thanks to top location of each header
-               # so, first useful list
-               origLocs = [x.location[0] for x in headers]
-               # list with top locations ordered
-               ordLocs = [x for x in origLocs]
-               ordLocs.sort()
-               # list with indexes of headers in real order
-               ordIndexes = []
-               for item in ordLocs:
-                       ordIndexes.append(origLocs.index(item))
-               # finally, return the header
-               return headers[ordIndexes[index-1]].name
+                       return parent.firstChild
 
 class ColumnsReview64(ColumnsReview):
        """for 64-bit systems (DirectUIHWND window class)
        see ColumnsReview32 class for more comments"""
 
        def script_readColumn(self,gesture):
-               num = self.getIndex(gesture.mainKeyName[-1])
+               num = self.getIndex(gesture.mainKeyName.rsplit('+', 1)[-1])
                # num is passed as is, excluding the first position (0) of the 
children list
                # containing an icon, so this check in this way
                if num > self.childCount-1:
@@ -217,7 +236,7 @@ class ColumnsReview64(ColumnsReview):
                        # Translators: message when cell in specified column is 
empty
                        content = _("Not available;")
                global readHeader, copyHeader
-               if scriptHandler.getLastScriptRepeatCount() != 0 and 
self.lastColumn == num:
+               if getLastScriptRepeatCount() and self.lastColumn == num:
                        # obj.name is the column header
                        header = (unicode(self.getChild(num).name+": ") if 
copyHeader else "")
                        if api.copyToClip(header+content):
@@ -231,6 +250,9 @@ class ColumnsReview64(ColumnsReview):
        # Translators: documentation of script to read columns
        script_readColumn.__doc__ = _("Returns the header and the content of 
the list column at the index corresponding to the number pressed")
 
+       def getHeadersParent(self):
+               return filter(lambda i: i.role == ct.ROLE_HEADER, 
self.parent.children)[0]
+
 class ColumnsReviewSettingsDialog(gui.SettingsDialog):
        """Class to define settings dialog."""
 
@@ -302,6 +324,52 @@ class ColumnsReviewSettingsDialog(gui.SettingsDialog):
                        self.settingsSizer.Show(self._switchChar)
                self.Fit()
 
+class HeadersDialog(wx.Dialog):
+       """define dialog for column headers management."""
+
+       def __init__(self, parent, appName, headersList):
+               title = ' - '.join([_("Headers manager"), appName])
+               super(HeadersDialog, self).__init__(parent, title=title)
+               helperSizer = BoxSizerHelper(self, wx.HORIZONTAL)
+               choices = [x.name if x.name else _("Unnamed header") for x in 
headersList]
+               self.list = helperSizer.addLabeledControl(_("Headers:"), 
wx.ListBox, choices=choices)
+               self.list.SetSelection(0)
+               self.headersList = headersList
+               actions = ButtonHelper(wx.VERTICAL)
+               leftClickAction = actions.addButton(self, label=_("Left click"))
+               leftClickAction.Bind(wx.EVT_BUTTON, self.onLeftClick)
+               rightClickAction = actions.addButton(self, label=_("Right 
click"))
+               rightClickAction.Bind(wx.EVT_BUTTON, self.onRightClick)
+               helperSizer.addItem(actions)
+               mainSizer = wx.BoxSizer(wx.VERTICAL)
+               mainSizer.Add(helperSizer.sizer, border=10, flag=wx.ALL)
+               mainSizer.Fit(self)
+               self.SetSizer(mainSizer)
+               for item in [self.list, leftClickAction, rightClickAction]:
+                       item.Bind(wx.EVT_KEY_UP, self.onEscape)
+
+       def onLeftClick(self, event):
+               index = self.list.GetSelection()
+               headerObj = self.headersList[index]
+               api.moveMouseToNVDAObject(headerObj)
+               winUser.mouse_event(winUser.MOUSEEVENTF_LEFTDOWN,0,0,None,None)
+               winUser.mouse_event(winUser.MOUSEEVENTF_LEFTUP,0,0,None,None)
+               ui.message(_("%s header clicked")%headerObj.name)
+               self.Destroy()
+
+       def onRightClick(self, event):
+               index = self.list.GetSelection()
+               headerObj = self.headersList[index]
+               api.moveMouseToNVDAObject(headerObj)
+               winUser.mouse_event(winUser.MOUSEEVENTF_RIGHTDOWN,0,0,None,None)
+               winUser.mouse_event(winUser.MOUSEEVENTF_RIGHTUP,0,0,None,None)
+               ui.message(_("%s header clicked")%headerObj.name)
+               self.Destroy()
+
+       def onEscape(self, event):
+               if event.GetKeyCode() == wx.WXK_ESCAPE:
+                       self.Destroy()
+
 class GlobalPlugin(globalPluginHandler.GlobalPlugin):
 
        def __init__(self, *args, **kwargs):
@@ -323,14 +391,14 @@ class GlobalPlugin(globalPluginHandler.GlobalPlugin):
                        pass
 
        def chooseNVDAObjectOverlayClasses(self, obj, clsList):
-               if obj.windowClassName == u'MozillaWindowClass' and obj.role in 
[controlTypes.ROLE_TABLEROW, controlTypes.ROLE_TREEVIEWITEM]:
+               if obj.windowClassName == u'MozillaWindowClass' and obj.role in 
[ct.ROLE_TABLEROW, ct.ROLE_TREEVIEWITEM]:
                        clsList.insert(0, MozillaTable)
-               elif obj.role == controlTypes.ROLE_LISTITEM:
+               elif obj.role == ct.ROLE_LISTITEM:
                        if obj.windowClassName == "SysListView32" or 
u'WindowsForms10.SysListView32.app.0' in obj.windowClassName:
                                clsList.insert(0, ColumnsReview32)
                        elif obj.windowClassName == "DirectUIHWND" and 
isinstance(obj, UIA):
                                # Windows 8/8.1/10 Start Screen tiles should 
not expose column info.
                                if not obj.UIAElement.cachedClassName in 
("GridTileElement", "GridListTileElement"):
                                        clsList.insert(0, ColumnsReview64)
-               else:
-                       return
+#              elif obj.role == ct.ROLE_CHECKBOX and obj.windowClassName in 
[u'WuDuiListView', u'SysListView32']:
+#                      clsList.insert(0, CheckboxList)

Repository URL: https://bitbucket.org/nvdaaddonteam/columnsreview/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.

Other related posts:

  • » commit/columnsReview: ABuffEr: NEW: list headers manager (experimental). Minor changes in code and comments. - commits-noreply