pywinauto/Branches/OriginalPydlgChecks/tests/repeatedhotkey.py

173 lines
4.5 KiB
Python
Raw Normal View History

2006-01-04 20:40:23 +01:00
"tests a set of controls for repeated hotkey errors"
__revision__ = "0.0.1"
from win32defines import SS_NOPREFIX
#-----------------------------------------------------------------------------
def RepeatedHotkeyTest(windows):
"Return the repeated hotkey errors"
hotkeyControls, allChars, hotkeys = CollectDialogInfo(windows)
#if windows[0].Class == "MenuItem":
# print "=-" * 20
# import pprint
# pprint.pprint (windows)
# get the available characters in the dialog
dlgAvailable = allChars.difference(hotkeys)
# remove some characters that aren't good choices for hotkeys
dlgAvailable.difference_update(set("-& _"))
bugs = []
# for each hotkey
for char, controls in hotkeyControls.items():
# if there is more than one control associated then it is a bug
if len(controls) > 1:
ctrlsAvailableChars = ""
# build up the available characters for each control
for c in controls:
controlChars = ""
controlChars = set(c.Text.lower())
controlAvailableChars = controlChars.intersection(dlgAvailable)
controlAvailableChars = "<%s>" % SetAsString(controlAvailableChars)
ctrlsAvailableChars += controlAvailableChars
refCtrls = [ctrl.ref for ctrl in controls if ctrl.ref]
refHotkeyControls, refAllChars, refHotkeys = CollectDialogInfo(refCtrls)
isInRef = -1
if len(refHotkeys) > 1:
isInRef = 1
else:
isInRef = 0
bugs.append((
controls,
{
"RepeatedHotkey" : char,
"CharsUsedInDialog" : SetAsString(hotkeys),
"AllCharsInDialog" : SetAsString(allChars),
"AvailableInControls" : ctrlsAvailableChars,
},
"RepeatedHotkey",
isInRef)
)
# # What is the algorithm to try and do all that is necessary to find
# # if it is possible to get a fix character if none of the current
# # characters are free
# for bug in bugs:
# for c, chars in bug.bugData:
# # control has no possibilities
# if not chars:
# # check if there are any other hotkey controls
# # in the dialog that could be used
# others = set(c.Title.lower()).intersection(unUsedChars)
return bugs
#-----------------------------------------------------------------------------
def CollectDialogInfo(windows):
hotkeyControls = {}
allChars = ''
for win in windows:
# skip it if it doesn't implement hotkey functionality
if not ImplementsHotkey(win):
continue
# get the hotkey
pos, char = GetHotkey(win.Text)
# if no hotkey for this control
# then continue
if not char:
continue
# store hotkey with list of used hotkeys
# map this hotkey to the list of controls that have it
hotkeyControls.setdefault(char.lower(), []).append(win)
# Add the title of this control to the list of available
# characters for the dialog
allChars += win.Text.lower()
allChars = set(allChars)
hotkeys = set(hotkeyControls.keys())
return hotkeyControls, allChars, hotkeys
#-----------------------------------------------------------------------------
# get hokey position
def GetHotkey(text):
"Return the position and character of the hotkey"
# find the last & character that is not followed
# by & or by the end of the string
curEnd = len(text) + 1
text = text.replace("&&", "__")
while True:
pos = text.rfind("&", 0, curEnd)
# One found was at the end of the text or
# no (more) & were found
# so return the None value
if pos == -1 or pos == len(text):
return (-1, '')
# One found but was prededed by non valid hotkey character
# so continue, as that can't be a shortcut
if text[pos - 1] == '&':
curEnd = pos - 2
continue
# 2 ampersands in a row - so skip
# the 1st one and continue
return (pos, text[pos+1])
#-----------------------------------------------------------------------------
def SetAsString(s):
return "".join(sorted(s))
#=============================================================================
def ImplementsHotkey(win):
"checks whether a control interprets & character to be a hotkey"
# buttons always implement hotkey
if win.Class == "Button":
return True
# Statics do if they don't have SS_NOPREFIX style
elif win.Class == "Static" and not win.HasStyle(SS_NOPREFIX):
return True
if win.Class == "MenuItem" and win.State != "2048":
return True
# Most controls don't - so just return false if
# neither of the above condition hold
return False
RepeatedHotkeyTest.TestsMenus = True