MAINT: fix type error of comparing int and KeyboardModifier#1045
Conversation
corranwebster
left a comment
There was a problem hiding this comment.
1 in the new qt, keyboard related modifiers are moved to
QtCore.Qt.KeyboardModifierfromQtCore.Qt, thus the source of keyboard modifiers should be changed
If you are making this change, you should make the corresponding changes for the mouse buttons (ie. Qt.LeftButton should probably become Qt.MouseButton.LeftButton or something similar).
2 in enable.qt.base_window._create_mouse_event, when the mouse is moved outside the window, the event passed to this function will be a QEvent other than an event from QGui (such as QMouseEvent or QEnterEvent).
Whether the event is defined in QtGui is pretty much irrelevant - what matters is the API it expresses. Don't try to implement the code you have suggested in the snippet in the description as it has the potential to break things badly in the future (eg. if things get moved out of QtGui in the future). Please remove the comment you've added, as it is misleading.
I'm not 100% sure what this is guarding against - the list of events which get routed through this code are fairly small (see
enable/enable/qt/base_window.py
Lines 140 to 174 in d99598a
In any case, please remove the comment you added as it is misleading.
| # The AttributeError is usually trigged when the mouse pointer | ||
| # leaves the ui window since the event of leaving the window | ||
| # is a "QEvent", which doesn't contain x and y positions like | ||
| # QMouseEvent (for mouse movement) or QEnterEvent (for mouse | ||
| # entering the window) from QGui. |
There was a problem hiding this comment.
This is a somewhat misleading comment (whether this path gets triggered is unrelated to whether the event is defined in QtGui) and the reasoning is covered by the comment in lines 453-454.
There was a problem hiding this comment.
Sure, I will remove it. We came up with this comment during my standup with Didrik and thought it may be useful since it shows how the attribute error can happen (by moving the mouse out of the window). What if I keep only this part:
# The AttributeError is usually trigged when the mouse pointer
# leaves the ui window since the event of leaving the window
# is a "QEvent", which doesn't contain x and y positions
?
| modifiers = 0 | ||
| buttons = 0 | ||
| modifiers = QtCore.Qt.KeyboardModifier.NoModifier | ||
| buttons = QtCore.Qt.NoButton |
There was a problem hiding this comment.
Probably should be:
| buttons = QtCore.Qt.NoButton | |
| buttons = QtCore.Qt.MouseButton.NoButton |
or something similar.
| left_down=bool(buttons & QtCore.Qt.LeftButton), | ||
| middle_down=bool(buttons & QtCore.Qt.MiddleButton), | ||
| right_down=bool(buttons & QtCore.Qt.RightButton), |
There was a problem hiding this comment.
Similar comment here: probably should use MouseButton.LeftButton etc.
|
@homosapien-lcy This is blocking getting PySide 6.4+ working for Chaco. Could you please update this? |
Sure, the Japan office was in public holiday last week. I will work on it now. |
I have tried remove the attribute error catch, but then the mouse leaving the window will trigger no attribute error (enable/examples/demo/enable/basic_draw.py demo), so I guess we still needs it. |
|
Perhaps the more interesting question here is: Why does the signature for EDIT: The check in that part of the code is |
…ut QGUI coordinates
Hi John: Good question. But I think the mouse event when leaving the window (QEvent) doesn't contain function to acquire its coordinates, thus even if we use is_qt6 to distinguish the version, we cannot get the coordinate from the event, here are the print out from the dir function for QMounseEvent vs QEvent: We can see that QMouseEvent has "position" while QEvent doesn't have anything similar. Thus we will inevitably try to find the x, y from the global coordinate like in the AttributeError block: |
There are two issues here:
There may be deeper history with Qt4 about why this code was written this way, but I'm not going to dig into that right now, We also need to take into account QWheelEvent, which is the 3rd type of mouse event which this code handles, but I think it's close enough to QMouseEvent on all versions of Qt that it's fine. |
corranwebster
left a comment
There was a problem hiding this comment.
This isn't perfect, but I will merge now to get Chaco unstuck and may make a separate PR to revise the logic to account for the observations above.
Currently when running multiple demos in enable (such as
enable/enable/examples/demo/enable/basic_draw.py), aTypeError: unsupported operand type(s) for &: 'int' and 'KeyboardModifier'will be raised when user moves the mouse outside the ui window.There are two causes of this error:
1 in the new qt, keyboard related modifiers are moved to
QtCore.Qt.KeyboardModifierfromQtCore.Qt, thus the source of keyboard modifiers should be changed2 in
enable.qt.base_window._create_mouse_event, when the mouse is moved outside the window, the event passed to this function will be aQEventother than an event fromQGui(such asQMouseEventorQEnterEvent).QEventdoes not have any attribute related to coordinates x and y which will cause an attribute error that will be caught here https://github.com/enthought/enable/blob/main/enable/qt/base_window.py#L464. After catch, the modifiers and buttons will be changed to integer 0, which are incompatible withKeyboardModifierfor&operation.Thus the changes I implemented are:
1 Change
QtCore.Qtkeyboard modifiers toQtCore.Qt.KeyboardModifierkeyboard modifiers2 Set modifiers and buttons to modifiers and button classes that represent 0
I have also considered change the
_create_mouse_event(https://github.com/enthought/enable/blob/main/enable/qt/base_window.py#L464) function to check whether the event is aQtGuiin order to avoid entering theAttributeError:However for two reasons I consider this undesirable:
1 Some other events that are not
QtGuican also contain position information2 In the future, other edge cases can pass in events that doesn't contain position information, thus
AttributeErroris actually good for handling them in generalThus I decided to keep
AttributeErroras the method to handle events not containing attributes for now.closes #1030