GNOME Bugzilla – Bug 465087
Orca speaks "Available fields panel" too many times with OOo sbase Tables wizard.
Last modified: 2007-09-26 18:02:53 UTC
Tested with OOo-dev 2.3.0 (build #223) Linux RPM's on Ubuntu Gutsy (with all the latest updates and latest Orca from SVN HEAD). Steps to reproduce: 1/ Start Orca 2/ Start /opt/ooo-dev2.3/program/sbase 3/ Work through the startup wizard. Choose to create a new database. Click Next. 4/ Say "Yes, please register database for me" and "Open for editing AND Create tables". Click Finish. 5/ When the "Save as" dialog appears, select a name and press Save. 6/ When the Table Wizard appears, you will hear a description of it. Most of it is just fine. Unfortunately it speaks "Available fields panel" numerous times. I'll attach a debug.out of this next.
Created attachment 93376 [details] Orca debug.out generated whilst testing this problem.
Just spent some time on this. We are getting numerous "object:state-changed:focused" events when we Tab into the "Available fields" list on the sbase table wizard. We are getting them for three components in the following component hierarchy: panel <-- type 1. scroll pane <-- type 2. panel <-- type 3 option pane dialog application I started to add some code to the onStateChanged() method in StarOffice.py, to try to see how many of each type we are getting: Index: src/orca/scripts/StarOffice.py =================================================================== --- src/orca/scripts/StarOffice.py (revision 2637) +++ src/orca/scripts/StarOffice.py (working copy) @@ -2059,6 +2062,34 @@ orca.setLocusOfFocus(event, event.source, False) return + # If we are in the sbase Table Wizard, try to prevent numerous + # utterances of "Available fields panel". See bug #465087 for + # more details. + if event.type == "object:state-changed:focused": + rolesList = [rolenames.ROLE_PANEL, \ + rolenames.ROLE_SCROLL_PANE, \ + rolenames.ROLE_PANEL, \ + rolenames.ROLE_OPTION_PANE, \ + rolenames.ROLE_DIALOG, \ + rolenames.ROLE_APPLICATION] + if self.isDesiredFocusedItem(event.source, rolesList): + print "GOT TYPE 1." + + rolesList = [rolenames.ROLE_SCROLL_PANE, \ + rolenames.ROLE_PANEL, \ + rolenames.ROLE_OPTION_PANE, \ + rolenames.ROLE_DIALOG, \ + rolenames.ROLE_APPLICATION] + if self.isDesiredFocusedItem(event.source, rolesList): + print "GOT TYPE 2." + + rolesList = [rolenames.ROLE_PANEL, \ + rolenames.ROLE_OPTION_PANE, \ + rolenames.ROLE_DIALOG, \ + rolenames.ROLE_APPLICATION] + if self.isDesiredFocusedItem(event.source, rolesList): + print "GOT TYPE 3." + # If we get "object:state-changed:focused" events for children of # a combo-box, just set the focus to the combo box. This is needed # to help reduce the verbosity of focusing on the Calc Name combo and now, when I run sbase and Orca together, sbase keeps going into Error Recovery mode. Why it thinks I'd want swriter to be started if I decide I don't want to recover the sbase file at this time is anyones guess. But I digress. I've also noticed that we are getting the following traceback when the sbase table wizard appears: Traceback (most recent call last):
+ Trace 155203
s.processObjectEvent(event)
self.listeners[key](event)
frame = self.getFrame(event.source)
+ obj.accessibleNameToString())
Looks like we are going to need some more bullet proofing around that code.
The Attribute error is caused by the following code in the onStateChanged() routine in StarOffice.py: # [[[TODO: JD - HACK because we won't get events from toggle # buttons on the Formatting toolbar until we "tickle/poke" # the hierarchy. But we only want to do it once. # See bug #363830 and OOo issue #70872.]]] # if not self.tickled: frame = self.getFrame(event.source) <=== problem code if frame: self.getObjects(frame) self.tickled = True This in turn calls getFrame() in default.py: def getFrame(self, obj): """Returns the frame containing this object, or None if this object is not inside a frame. Arguments: - obj: the Accessible object """ debug.println(debug.LEVEL_FINEST, "Finding frame for source.name=" + obj.accessibleNameToString()) while obj \ and (obj != obj.parent) \ and (obj.role != rolenames.ROLE_FRAME): obj = obj.parent debug.println(debug.LEVEL_FINEST, "--> obj.name=" + obj.accessibleNameToString()) if obj and (obj.role == rolenames.ROLE_FRAME): pass else: obj = None return obj Problem here is this is a dialog not a frame, so the while checks don't catch that, and we go shooting out the top of the accessible component hierarchy. Joanie, Will, what do you think is the best approach to tightening the code and fixing the problem?
The traceback can be eliminated by checking that we have an obj before calling accessibleNameToString(). Perhaps in StarOffice.py we should call getTopLevel() instead of getFrame() and tickle only if the returned object has rolename of ROLE_FRAME?
> while obj \ > and (obj != obj.parent) \ > and (obj.role != rolenames.ROLE_FRAME): > obj = obj.parent > debug.println(debug.LEVEL_FINEST, "--> obj.name=" > + obj.accessibleNameToString()) Good sleuthing. So the problem is the debug.println above -- obj could be None. I guess adding an "if obj:" to conditionally do the debug would be a decent (and needed) fix. With this, the return value should remain None and the StarOffice.py code should continue to work. What do you think?
> What do you think? It's certainly the easiest fix (workaround). I just wondered if there was some better way of handling this. Unless I hear otherwise in the next 15 minutes, I'll check it a fix to add that line (for both the gnome-2-20 branch and SVN HEAD). Thanks.
Created attachment 93677 [details] [review] Patch to prevent the traceback. Not committed yet. Just here for your viewing pleasure. Will be committed to gnome-2-20 branch and SVN HEAD shortly.
Patch committed to gnome-2-20 branch and SVN HEAD. Thanks.
Created attachment 93866 [details] [review] Patch to reduce the number of times that "Available field panel" is uttered. Patch to SVN HEAD. Not committed yet. This reduces the number of times this is spoken done to two.
Created attachment 93990 [details] [review] Second revision Unfortunately the last patch was too generic. This one makes sure we are focused on the "Available fields" item.
(In reply to comment #2) > Just spent some time on this. We are getting numerous > "object:state-changed:focused" events when we Tab into > the "Available fields" list on the sbase table wizard. > We are getting them for three components in the following > component hierarchy: > > panel <-- type 1. > scroll pane <-- type 2. > panel <-- type 3 Just to make sure I understand what's going on with the patch, is the proposal to ignore some object:state-changed:focused events because the the focus: on the related objects is going to end up being somewhat transient?
Right. The patch reduces the number significantly. It's not down to one though, but it's a vast improvement.
(In reply to comment #12) > Right. The patch reduces the number significantly. It's not down > to one though, but it's a vast improvement. Can more filtering be done? For example, are we guaranteed to get focus on the one thing that we really really care about? If so, can we filter out the rest of the events and restrict our calls to orca.setLocusOfFocus to be for the object we care about?
> Can more filtering be done? Probably. It's just a case of how many chunks of code that look very similar to: + # If we are in the sbase Table Wizard, try to reduce the numerous + # utterances of "Available fields panel". See bug #465087 for + # more details. + if event.type == "object:state-changed:focused": + rolesList = [rolenames.ROLE_PANEL, \ + rolenames.ROLE_OPTION_PANE, \ + rolenames.ROLE_DIALOG, \ + rolenames.ROLE_APPLICATION] + if self.isDesiredFocusedItem(event.source, rolesList): + # The above accessible role hierarchy is common. We need to + # determine we have the one we are interested in. + # + # Translators: this represents a match with the name of the + # "Available fields" list in the Tables wizard dialog in the + # the OOo oobase database application. We're looking for the + # accessible object name starting with "Available fields". + # We really try to avoid doing this kind of thing, but + # sometimes it is necessary and we apologize. + # + if event.source.name.startswith(_("Available fields")): + return + do we want? The second and third chunks will be remarkably similar (just one or two more items in the rolesList. If you are okay with that, then I can modify accordingly. I was trying to strike a balance between the amount of code and how many times it speaks the "Available fields panel".
> Probably. It's just a case of how many chunks of code that > look very similar to: I see. Yech. Would these chunks be something that could be collapsed into a method that can be called from the various spots? For example, something like an "__isAvailableFieldsPanel" method that returns True/False?
Created attachment 95014 [details] [review] Third revision. Patch to SVN trunk. Not committed yet. This seems to nicely tidy up the utterances of "Available fields panel". Mike, when you test this please let me know if there are any other changes you'd like made. Thanks.
I tested this one a while ago and forgot to comment. Sorry about that. This does seem to nicely improve the extra chatter.
Patch committed to trunk. Moving bug state to "[pending].
This one looks good.
Thanks Mike. Closing as FIXED.