Skip to content
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

PR: Make QMenu.addAction and QToolBar.addAction compatible with Qt6 arguments' order #437

Merged
13 changes: 10 additions & 3 deletions qtpy/QtWidgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
# -----------------------------------------------------------------------------

"""Provides widget classes and functions."""
from functools import wraps
from functools import partialmethod, wraps

from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtModuleNotInstalledError
from ._utils import possibly_static_exec, getattr_missing_optional_dep
from packaging.version import parse

from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6, QT_VERSION as _qt_version
from ._utils import add_action, possibly_static_exec, getattr_missing_optional_dep


_missing_optional_names = {}
Expand Down Expand Up @@ -114,3 +116,8 @@ def _directory_to_dir_(*args, **kwargs):
QFileDialog.getOpenFileName = _dir_to_directory(QFileDialog.getOpenFileName)
QFileDialog.getOpenFileNames = _dir_to_directory(QFileDialog.getOpenFileNames)
QFileDialog.getSaveFileName = _dir_to_directory(QFileDialog.getSaveFileName)

# Make `addAction` compatible with Qt6 >= 6.3
if PYQT5 or PYSIDE2 or parse(_qt_version) < parse('6.3'):
dalthviz marked this conversation as resolved.
Show resolved Hide resolved
QMenu.addAction = partialmethod(add_action, old_add_action=QMenu.addAction)
QToolBar.addAction = partialmethod(add_action, old_add_action=QToolBar.addAction)
54 changes: 54 additions & 0 deletions qtpy/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,57 @@ def possibly_static_exec_(cls, *args, **kwargs):
return args[0].exec_(*args[1:], **kwargs)
else:
return cls.exec_(*args, **kwargs)


def add_action(self, *args, old_add_action):
"""Re-order arguments of `addAction` to backport compatibility with Qt>=6.3."""
from qtpy.QtCore import QObject
from qtpy.QtGui import QIcon, QKeySequence
from qtpy.QtWidgets import QAction

action: QAction
icon: QIcon
text: str
shortcut: QKeySequence | QKeySequence.StandardKey | str | int
receiver: QObject
member: bytes
if all(isinstance(arg, t)
for arg, t in zip(args, [str,
(QKeySequence, QKeySequence.StandardKey, str, int),
QObject,
bytes])):
if len(args) == 2:
text, shortcut = args
action = old_add_action(self, text)
action.setShortcut(shortcut)
elif len(args) == 3:
text, shortcut, receiver = args
action = old_add_action(self, text, receiver)
action.setShortcut(shortcut)
elif len(args) == 4:
text, shortcut, receiver, member = args
action = old_add_action(self, text, receiver, member, shortcut)
else:
return old_add_action(self, *args)
return action
elif all(isinstance(arg, t)
for arg, t in zip(args, [QIcon,
str,
(QKeySequence, QKeySequence.StandardKey, str, int),
QObject,
bytes])):
if len(args) == 3:
icon, text, shortcut = args
action = old_add_action(self, icon, text)
action.setShortcut(QKeySequence(shortcut))
elif len(args) == 4:
icon, text, shortcut, receiver = args
action = old_add_action(self, icon, text, receiver)
action.setShortcut(QKeySequence(shortcut))
elif len(args) == 5:
icon, text, shortcut, receiver, member = args
action = old_add_action(self, icon, text, receiver, member, QKeySequence(shortcut))
else:
return old_add_action(self, *args)
return action
return old_add_action(self, *args)
12 changes: 12 additions & 0 deletions qtpy/tests/test_qtwidgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ def test_QMenu_functions(qtbot):
window = QtWidgets.QMainWindow()
menu = QtWidgets.QMenu(window)
menu.addAction('QtPy')
menu.addAction('QtPy with a shortcut', QtGui.QKeySequence.UnknownKey)
menu.addAction(QtGui.QIcon(), 'QtPy with an icon and a shortcut', QtGui.QKeySequence.UnknownKey)
window.show()

with qtbot.waitExposed(window):
Expand All @@ -115,6 +117,16 @@ def test_QMenu_functions(qtbot):
QtWidgets.QMenu.exec_(menu.actions(), QtCore.QPoint(1, 1))


@pytest.mark.skipif(
sys.platform == 'darwin' and sys.version_info[:2] == (3, 7),
reason="Stalls on macOS CI with Python 3.7")
def test_QToolBar_functions(qtbot):
"""Test `QtWidgets.QToolBar.addAction` compatibility with Qt6 arguments' order."""
toolbar = QtWidgets.QToolBar()
toolbar.addAction('QtPy with a shortcut', QtGui.QKeySequence.UnknownKey)
toolbar.addAction(QtGui.QIcon(), 'QtPy with an icon and a shortcut', QtGui.QKeySequence.UnknownKey)


@pytest.mark.skipif(PYQT5 and PYQT_VERSION.startswith('5.9'),
reason="A specific setup with at least sip 4.9.9 is needed for PyQt5 5.9.*"
"to work with scoped enum access")
Expand Down
Loading