New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve working with message lists and calendars in Outlook #7949
Improve working with message lists and calendars in Outlook #7949
Conversation
Blocked by #7953 |
…ssage's UIAGridRow object
Implementation had to be changed completely.
I had to change this into a completely different implementation due to #7953. @michaelDCurran. It would be great if you could review this as soon as possible to fix #7953. |
source/appModules/outlook.py
Outdated
# The first valuePart is the type of the selection, e.g. Message, Contact. | ||
# The last valuePart indicates whether the message is read or unread. | ||
if len(valueParts)>=3: | ||
textList.extend(valueParts[1:-1]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we be sure that the first part (message, contact etc) is never more than one word in all languages?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question, which also applies to read/unread I belief.
Though JAWS uses these translated strings, I"m pretty sure they do some string matching on it, as the read state is ignored when Both Outlook and JAWS are set to Dutch, but the state is preserved when Outlook is Dutch and JAWS is English. So that's definitely not a clean solution.
I belief both Message and Unread are part of the NVDA translation, so it should be doable to check whether these words contain spaces in other languages without intervention of every single translator.
@michaelDCurran: I made the scope of this pr somewhat broader and also addressed some other concerns there were with the current way of dealing with Outlook. The initial message of the pr covers all relevant information. |
source/appModules/outlook.py
Outdated
} | ||
#: When in a list view, the message classes which should not be announced for an item. | ||
#: For these, it should be safe to assume that their names consist of only one word. | ||
silentMessageClasses = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So there is no such class for a message/email?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's the note one. I added a comment that clarifies this.
source/appModules/outlook.py
Outdated
CalendarView._lastStartDate=startDate | ||
if endDate!=startDate: | ||
if (endDate - startDate).total_seconds()==SECONDS_PER_DAY: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also catches events that start at noon on one day and end at noon on the next. Do we want to call these all day events or should we check for the start and end times being midnight as well?
source/appModules/outlook.py
Outdated
CalendarView._lastStartDate=startDate | ||
if endDate!=startDate: | ||
if (endDate - startDate).total_seconds()==SECONDS_PER_DAY: | ||
# Translators: a message reporting the date of a whole day Outlook calendar entry |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Outlook calls them "All day event", not "whole day".
source/appModules/outlook.py
Outdated
if endDate!=startDate: | ||
if (endDate - startDate).total_seconds()==SECONDS_PER_DAY: | ||
# Translators: a message reporting the date of a whole day Outlook calendar entry | ||
return _("{date} (entire day)").format(date=startDateText) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, "all day" may be better here.
source/appModules/outlook.py
Outdated
# Do not expose the read state | ||
lastPart = valueCount if unread else valueCount-1 | ||
# The first valuePart is the type of the selection, e.g. Message, Contact, meeting request. | ||
# We can safely assume that the message class of a regular message or appointment is one word. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yet the example you give above is "Meeting request". Is this not regular? If so, 2 words should be filtered out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to improve the clarity of the comments. Meeting request is regular, but it isn't part of silentMessageClasses and therefore always announced.
source/appModules/outlook.py
Outdated
# Thus we filter it out. | ||
if self.appModule.outlookVersion>=16 and e.cachedClassName=="DraftFlagField": | ||
continue | ||
isFlag = e.cachedClassName=="FlagField" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this handle the "DraftFlagField" case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I forgot to mention this in the initial pr description, I surely should have done that. It is still open to discussion.
MS no longer exposes "no associated draft" as a text node by default. Instead, the text node is empty. Furthermore, the "no associated draft" patch meant that it would be never announced when a message has an associated draft. Therefore, I propose people who have the "no associated draft" issue updating their outlook to fix this, rather than keeping the old patch. CC @bramd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I concur.
what about saying "all day" instead of "entire day" |
@derekriemer commented on 5 mrt. 2018 15:53 CET:
It is now saying "all day" as per the last commits from today morning. |
@michaelDCurran, this pr has been overhauled and is ready for another review I think. I'm afraid there's no way to work around relying on the localized contents of the UIA value. |
…ey ought to be silent.
@josephsl commented on 15 mrt. 2018 06:18 CET:
Looks like it is. It turns out it wasn't a good idea to remove the tree filter from the cache request that forced the fetched children to be text controls. I now added a new tree filter that requires the children to be content children. After that, I couldn't reproduce the issue any more. I also noticed another bug in the code that tried to access the object model for flag information when there was no selection. That bug was actually obfuscated by the treeFilter one. We are now ignoring flags when there is no object model access, just as we did before this pr. |
Currently blocked by #8129. When getting the name for message list items, a NULL COM pointer access error is raised because the custom UIA query fails. This is a bit strange, since until now, it fails only on two systems. @bramd has a system where it fails and another system where it works correctly, same windows and office builds. Note that such an error has been reported by @josephsl in #7949 (comment), the fix for that has yet not been committed to Next. However, testing by @bramd tells that the fix for #7949 (comment) does not aplly to this particular case of the null com pointer access error. I guess we can do an if check on cachedChildren, but I'd like to no why getting cached children would reveal a null com pointer in the first place. @michaelDCurran: Have you seen these cases earlier? |
ac0c603
to
be37594
Compare
I think I have seen a NULL COM pointer for cached children before. But I
can't remember exactly where.
We could argue it is a Microsoft bug, but in the end, we will still have
to handle it if it is happening in the wild.
|
…e the ContentViewCondition as tree filter instead of creating a property condition for content elements.
37b866c
to
8e06454
Compare
I reverted the announcement of importance, attachments and flags based on UIA children, as it is unreliable in conversation view. The announcement of these fields was based on the assumption that the UIA implementation treats relevant fields as content (i.e. with the IsContentElement property) whereas irrelevant fields (no attachment, no reminder) are non content. However, when conversation view is enabled, none of the relevant children have the IsContentElement property set. |
… mixed with tree view items (e.g. in conversation view)
@michaelDCurran: Could you please review the last few commits? |
Link to issue number:
Fixes #6911
Fixes #8028
Reverts #6219
Summary of the issue:
Description of how this pull request fixes the issue:
This pr gets the announcement of replied/forwarded state from the UIA value of rows in the Outlook messages list. NVDA will now also announce meeting requests based on this information, as well as appointment cancellations.
The initial implementation of this pr relied on the Outlook object model. However, this caused security warnings on some systems with a tight security policy.
When an appointment or time slot is now exactly one day (86400 seconds), and starts at 00.00, the time slot is announced as
26 february 2018 (entire day)
instead of26 februari 2018 00.00 to 27 februari 2018 00.00
. While looking at this code, I noticed that Microsoft strongly discourages the use of kernel32 GetTimeFormat and GetDateFormat functions, so I changed this implementation to use the *Ex alternatives for these functions.The associated draft column in Outlook 2016 is no longer silenced. After implementing Outlook 2016: NVDA reads "Associated draft, no associated drafts" for every message #6219, it seems Microsoft decided to present an empty text node when there is no associated draft, rather than spamming everyone with the "no associated draft" message. Therefore when this particular pr is merged, everyone who gets "no associated draft" for almost every message is advised to update Outlook 2016 to the most recent build.
Testing performed:
Known issues with pull request:
The replied or forwarded state is localized by Outlook itself, not by NVDA. This shouldn't be a problem though, as the headers are also localized by Outlook itself.
In theory, Outlook could expose every piece of relevant or irrelevant information using the UIA value. I've only seen the following strings until now:
I'm quite sure JAWS also relies on the value here, as replied/forwarded state is localized using Outlook, not using JAWS. The wild should make clear whether parsing the value this way is too non-restrictive.
The replied to all state is not reported as it is not exposed using the object's value.
When the root of a conversation in conversation view has focus, NVDA reads the headers of every single message in the conversation. There is currently no suitable workaround for this. Note that this was already the case before this pr. This issue is caused by a bug in UIA, where the tree scope is ignored when providing a custom tree filter for a cache request.
Change log entry:
New features
Changes