Make KeySequence.matchs() work correctly

This commit is contained in:
Florian Bruhin 2018-03-04 17:46:26 +01:00
parent 866c758660
commit 8da878c77c
2 changed files with 58 additions and 7 deletions

View File

@ -361,15 +361,38 @@ class KeySequence:
raise KeyParseError(keystr, "Got unknown key!") raise KeyParseError(keystr, "Got unknown key!")
def matches(self, other): def matches(self, other):
"""Check whether the given KeySequence matches with this one.""" """Check whether the given KeySequence matches with this one.
We store multiple QKeySequences with <= 4 keys each, so we need to match
those pair-wise, and account for an unequal amount of sequences as well.
"""
# pylint: disable=protected-access # pylint: disable=protected-access
assert self._sequences
assert other._sequences if len(self._sequences) > len(other._sequences):
for seq1, seq2 in zip(self._sequences, other._sequences): # If we entered more sequences than there are in the config, there's
match = seq1.matches(seq2) # no way there can be a match.
return QKeySequence.NoMatch
for entered, configured in zip(self._sequences, other._sequences):
# If we get NoMatch/PartialMatch in a sequence, we can abort there.
match = entered.matches(configured)
if match != QKeySequence.ExactMatch: if match != QKeySequence.ExactMatch:
return match return match
# We checked all common sequences and they had an ExactMatch.
#
# If there's still more sequences configured than entered, that's a
# PartialMatch, as more keypresses can still follow and new sequences
# will appear which we didn't check above.
#
# If there's the same amount of sequences configured and entered, that's
# an EqualMatch.
if len(self._sequences) == len(other._sequences):
return QKeySequence.ExactMatch return QKeySequence.ExactMatch
elif len(self._sequences) < len(other._sequences):
return QKeySequence.PartialMatch
else:
assert False, (self, other)
def append_event(self, ev): def append_event(self, ev):
"""Create a new KeySequence object with the given QKeyEvent added. """Create a new KeySequence object with the given QKeyEvent added.

View File

@ -21,7 +21,7 @@ import operator
import pytest import pytest
from PyQt5.QtCore import Qt, QEvent, pyqtSignal from PyQt5.QtCore import Qt, QEvent, pyqtSignal
from PyQt5.QtGui import QKeyEvent from PyQt5.QtGui import QKeyEvent, QKeySequence
from PyQt5.QtWidgets import QWidget from PyQt5.QtWidgets import QWidget
from tests.unit.keyinput import key_data from tests.unit.keyinput import key_data
@ -291,6 +291,34 @@ class TestKeySequence:
assert s1[3:5] == s2 assert s1[3:5] == s2
assert seq[3:5] == expected assert seq[3:5] == expected
@pytest.mark.parametrize('entered, configured, expected', [
# config: abcd
('abc', 'abcd', QKeySequence.PartialMatch),
('abcd', 'abcd', QKeySequence.ExactMatch),
('ax', 'abcd', QKeySequence.NoMatch),
('abcdef', 'abcd', QKeySequence.NoMatch),
# config: abcd ef
('abc', 'abcdef', QKeySequence.PartialMatch),
('abcde', 'abcdef', QKeySequence.PartialMatch),
('abcd', 'abcdef', QKeySequence.PartialMatch),
('abcdx', 'abcdef', QKeySequence.NoMatch),
('ax', 'abcdef', QKeySequence.NoMatch),
('abcdefg', 'abcdef', QKeySequence.NoMatch),
('abcdef', 'abcdef', QKeySequence.ExactMatch),
# other examples
('ab', 'a', QKeySequence.NoMatch),
# empty strings
('', '', QKeySequence.ExactMatch),
('', 'a', QKeySequence.PartialMatch),
('a', '', QKeySequence.NoMatch),
])
def test_matches(self, entered, configured, expected):
entered = keyutils.KeySequence.parse(entered)
configured = keyutils.KeySequence.parse(configured)
assert entered.matches(configured) == expected
@pytest.mark.parametrize('keystr, expected', [ @pytest.mark.parametrize('keystr, expected', [
('<Control-x>', keyutils.KeySequence(Qt.ControlModifier | Qt.Key_X)), ('<Control-x>', keyutils.KeySequence(Qt.ControlModifier | Qt.Key_X)),