PDA

View Full Version : Puzzling QAction::hover() behavior



d_stranz
4th April 2016, 18:26
I have a QMainWindow with both a menubar and a set of toolbars. I create QAction instances and connect slots to their triggered() and hovered() events. All of the action instances get put into QMenu instances owned by the menubar, and many of them also get added to one or more toolbars.

The enabled state for most of the QAction instances is set to false when the app first starts. As the user performs certain operations, the data needed by the actions becomes available, so the action should be enabled. I do this in the hovered() events - I check to see if the required data is available, and enable the QAction if it is.

The weird behaviour I am seeing is that since Qt 5.5 (I think), hovering over a disabled menu item will not cause the hovered() signal to fire (or at least my slot doesn't get called). If I hover over the same item on a toolbar, the hovered() signal is emitted whether the action is enabled or not.

If the hover slot does not enable the action, then the action on the menu stays unresponsive. If the hover slot enables the action, then the menu action becomes responsive and emits the hovered signal.

There are some menu items that do not have toolbar counterparts. I cannot get these to respond to hovered() signals no matter what changes in the program.

It does not seem to matter whether other items on the menu are enabled or disabled, either dynamically or set to enabled on creation. The items that start disabled stay unresponsive only until their corresponding icons are hovered and thereby enabled.

Has anyone else seen similar behaviour? Has something changed in QMenu since Qt 5.4 (or maybe it has been since Qt 5 and I haven't noticed) that could cause this to happen? Some QMenu / QMenuBar flag I am missing?

It is very bad for my users, because now they are locked out of certain operations (like copy and paste!) if I don't have a toolbar counterpart to the menu item.

This is on Windows 10, using either Qt 5.5 and 5.6, MS Visual Studio 2013. I have not reverted to Qt 5.4 to see if this problem exists there (yet).

anda_skoa
4th April 2016, 18:59
Wouldn't it be better to enable/disable actions based on their availability when the availability changes?

Check on hovering doesn't sounds appropriate to me, that would make shortcut based activation impossible.

Cheers,
_

d_stranz
4th April 2016, 19:06
Wouldn't it be better to enable/disable actions based on their availability when the availability changes?

Yes, probably. I've considered such a refactoring. At the time this code was written (years ago), the mechanism worked. It seemed easier to check state and update the menu item when the user tried to access it rather than update many menus items simultaneously on a state change.

But this doesn't address the question of why the hovered() signal isn't emitted for disabled menu items, while it is for disabled toolbar items, even though the QAction instance for each is the same one. This was working for Qt 4.8 and may have worked for earlier versions of Qt 5.

d_stranz
6th April 2016, 20:01
I reverted to Qt 5.4.1 and have confirmed that this behavior does not occur with that version. So this bug was apparently introduced with Qt 5.5.