Always report object states in same order, regardless whether positive or negative#7279
Conversation
…ame order, regardless whether they are positive or negative. Fixes #7076
dkager
left a comment
There was a problem hiding this comment.
Looks good to me. Quite a bit of code duplicaion, but I guess the states for braille and speech are not guaranteed to be identical?
| elif state in negativeStates: | ||
| # Translators: Indicates that a particular state on an object is negated. | ||
| # Separate braille abbreviations have now been defined for commonly negated states (e.g. ( ) for not checked), | ||
| # and, if no braille abbreviations are provided, we fall back to the defined state labels in ControlTypes, |
There was a problem hiding this comment.
Slightly more spaces than necessary. :)
…hat in the speech and braille modules
| negativeStates=propertyValues['negativeStates'] | ||
| else: | ||
| negativeStates=None | ||
| if negativeStates is not None or (reason != controlTypes.REASON_CHANGE and states is not None): |
There was a problem hiding this comment.
@jcsteh: Could you clarify this line? Was there a particular reason why if negativeStates is not None wasn't enough?
There was a problem hiding this comment.
Could you clarify this line? Was there a particular reason why if negativeStates is not None wasn't enough?
The negativeStates argument is only provided for REASON_CHANGE. It specifies states that have just changed from positive to negative. However, for other reasons (e.g. REASON_FOCUS), we still want to report certain states if they aren't present; e.g. "not checked".
There was a problem hiding this comment.
Thanks. In the new code, it seems this check is no longer necessary as I provide empty sets as default
| # Return all negative states which should be spoken, excluding the positive states. | ||
| return speakNegatives - states | ||
|
|
||
| def processAndLabelStates(role, states, reason, positiveStates, negativeStates, positiveStateLabelDict={}, negativeStateLabelDict={}): |
There was a problem hiding this comment.
I'm happy to provide a Doc-string for this, but processPositiveStates and processNegativeStates don't have a doc string yet. May be the initial author of these functions can provide some explanation (e.g. about why we both have states and positiveStates parameters for processPositiveStates)? We can add doc strings for these in this pr as well.
There was a problem hiding this comment.
why we both have states and positiveStates parameters for processPositiveStates
states contains the current states for the object. For REASON_CHANGE, positiveStates contains only those states that just got added. In other words, positiveStates contains only the states we want to possibly be reported at this time, but we might need the "unfiltered" states for the object, so we provide states as well.
|
@jcsteh: Apart from doc strings, I think this is ready for review. |
|
This now contains doc strings as well. @dkager: Would you like to review them? Your grammar is better than mine. :) |
| textList.extend(positiveStateLabels.get(state, controlTypes.stateLabels[state]) for state in positiveStates) | ||
| negativeStates = controlTypes.processNegativeStates(role, states, controlTypes.REASON_FOCUS, None) | ||
| textList.extend(negativeStateLabels.get(state, controlTypes.negativeStateLabels.get(state, _("not %s") % controlTypes.stateLabels[state])) for state in negativeStates) | ||
| textList.extend(controlTypes.processAndLabelStates(role, states, controlTypes.REASON_FOCUS, states,None,positiveStateLabels,negativeStateLabels)) |
There was a problem hiding this comment.
Inconsistent use of space after comma. Maybe pull this function out into two lines to improve readability?
| # Translators: This is presented when a checkbox is not checked. | ||
| STATE_CHECKED:_("not checked"), | ||
| # Translators: This is presented when drag and drop is finished. | ||
| # This is only reported for objects which support accessible drag and drop. |
There was a problem hiding this comment.
I think "that support" is the correct form here.
|
|
||
| def processPositiveStates(role, states, reason, positiveStates): | ||
| """Processes the states for an object and returns the positive states to output for a specified reason. | ||
| For example, if C{STATE_CHECKED} is among the returned states, it means that the processed object is checked. |
There was a problem hiding this comment.
Trivial I guess, but "in the returned states" is a bit closer to what you'd actually write in a program to check this.
| For example, if C{STATE_CHECKED} is among the returned states, it means that the processed object is checked. | ||
| @param role: The role of the object to process states for (e.g. C{ROLE_CHECKBOX}. | ||
| @type role: int | ||
| @param states: Usually the raw states for an object to process. |
There was a problem hiding this comment.
This implies there are exceptions. What are they?
| @type role: int | ||
| @param states: Usually the raw states for an object to process. | ||
| @type states: set | ||
| @param reason: The reason to process the states for (e.g. C{REASON_FOCUS}. |
There was a problem hiding this comment.
I think "for" should be removed.
|
|
||
| def processNegativeStates(role, states, reason, negativeStates): | ||
| """Processes the states for an object and returns the negative states to output for a specified reason. | ||
| For example, if C{STATE_CHECKED} is among the returned states, it means that the processed object is not checked. |
| # Return all negative states which should be spoken, excluding the positive states. | ||
| return speakNegatives - states | ||
|
|
||
| def processAndLabelStates(role, states, reason, positiveStates, negativeStates, positiveStateLabelDict={}, negativeStateLabelDict={}): |
There was a problem hiding this comment.
In another PR @jcsteh cautioned against using empty dicts as default function parameters. I wonder if that applies here.
| """Processes the states for an object and returns the appropriate state labels for both positive and negative states. | ||
| @param role: The role of the object to process states for (e.g. C{ROLE_CHECKBOX}. | ||
| @type role: int | ||
| @param states: Usually the raw states for an object to process. |
| if state in positiveStates: | ||
| mergedStateLabels.append(positiveStateLabelDict.get(state, stateLabels[state])) | ||
| elif state in negativeStates: | ||
| # Translators: Indicates that a particular state on an object is negated. |
|
@dkager: Could you review my most recent commits? |
|
As far as small changes bringing big joy go, this is still one of my favorites. |
Link to issue number:
fixes #7076
Summary of the issue:
When reporting object states to the user in speech or braille, the positive object states are processed before the negative states. This creates the following problem as reported by @dkager:
Description of how this pull request fixes the issue:
Testing performed:
In disk clean up, the selected state is now always spoken before the checked state, regardless whether positive or negative
Known issues with pull request: