File: C:/Users/fred/anaconda3/Lib/site-packages/qtpy/QtGui.py
# -----------------------------------------------------------------------------
# Copyright © 2014-2015 Colin Duquesnoy
# Copyright © 2009- The Spyder Development Team
#
# Licensed under the terms of the MIT License
# (see LICENSE.txt for details)
# -----------------------------------------------------------------------------
"""Provides QtGui classes and functions."""
from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6, QtModuleNotInstalledError
from ._utils import getattr_missing_optional_dep, possibly_static_exec
_missing_optional_names = {}
_QTOPENGL_NAMES = {
"QOpenGLBuffer",
"QOpenGLContext",
"QOpenGLContextGroup",
"QOpenGLDebugLogger",
"QOpenGLDebugMessage",
"QOpenGLFramebufferObject",
"QOpenGLFramebufferObjectFormat",
"QOpenGLPixelTransferOptions",
"QOpenGLShader",
"QOpenGLShaderProgram",
"QOpenGLTexture",
"QOpenGLTextureBlitter",
"QOpenGLVersionProfile",
"QOpenGLVertexArrayObject",
"QOpenGLWindow",
}
def __getattr__(name):
"""Custom getattr to chain and wrap errors due to missing optional deps."""
raise getattr_missing_optional_dep(
name,
module_name=__name__,
optional_names=_missing_optional_names,
)
if PYQT5:
from PyQt5.QtGui import *
# Backport items moved to QtGui in Qt6
from PyQt5.QtWidgets import (
QAction,
QActionGroup,
QFileSystemModel,
QShortcut,
QUndoCommand,
)
elif PYQT6:
from PyQt6 import QtGui
from PyQt6.QtGui import *
# Attempt to import QOpenGL* classes, but if that fails,
# don't raise an exception until the name is explicitly accessed.
# See https://github.com/spyder-ide/qtpy/pull/387/
try:
from PyQt6.QtOpenGL import *
except ImportError as error:
for name in _QTOPENGL_NAMES:
_missing_optional_names[name] = {
"name": "PyQt6.QtOpenGL",
"missing_package": "pyopengl",
"import_error": error,
}
QFontMetrics.width = lambda self, *args, **kwargs: self.horizontalAdvance(
*args,
**kwargs,
)
QFontMetricsF.width = lambda self, *args, **kwargs: self.horizontalAdvance(
*args,
**kwargs,
)
# Map missing/renamed methods
QDrag.exec_ = lambda self, *args, **kwargs: self.exec(*args, **kwargs)
QGuiApplication.exec_ = lambda *args, **kwargs: possibly_static_exec(
QGuiApplication,
*args,
**kwargs,
)
QTextDocument.print_ = lambda self, *args, **kwargs: self.print(
*args,
**kwargs,
)
# Allow unscoped access for enums inside the QtGui module
from .enums_compat import promote_enums
promote_enums(QtGui)
del QtGui
elif PYSIDE2:
from PySide2.QtGui import *
# Backport items moved to QtGui in Qt6
from PySide2.QtWidgets import (
QAction,
QActionGroup,
QFileSystemModel,
QShortcut,
QUndoCommand,
)
if hasattr(QFontMetrics, "horizontalAdvance"):
# Needed to prevent raising a DeprecationWarning when using QFontMetrics.width
QFontMetrics.width = (
lambda self, *args, **kwargs: self.horizontalAdvance(
*args,
**kwargs,
)
)
elif PYSIDE6:
from PySide6.QtGui import *
# Attempt to import QOpenGL* classes, but if that fails,
# don't raise an exception until the name is explicitly accessed.
# See https://github.com/spyder-ide/qtpy/pull/387/
try:
from PySide6.QtOpenGL import *
except ImportError as error:
for name in _QTOPENGL_NAMES:
_missing_optional_names[name] = {
"name": "PySide6.QtOpenGL",
"missing_package": "pyopengl",
"import_error": error,
}
# Backport `QFileSystemModel` moved to QtGui in Qt6
from PySide6.QtWidgets import QFileSystemModel
QFontMetrics.width = lambda self, *args, **kwargs: self.horizontalAdvance(
*args,
**kwargs,
)
QFontMetricsF.width = lambda self, *args, **kwargs: self.horizontalAdvance(
*args,
**kwargs,
)
# Map DeprecationWarning methods
QDrag.exec_ = lambda self, *args, **kwargs: self.exec(*args, **kwargs)
QGuiApplication.exec_ = lambda *args, **kwargs: possibly_static_exec(
QGuiApplication,
*args,
**kwargs,
)
if PYSIDE2 or PYSIDE6:
# PySide{2,6} do not accept the `mode` keyword argument in
# QTextCursor.movePosition() even though it is a valid optional argument
# as per C++ API. Fix this by monkeypatching.
#
# Notes:
#
# * The `mode` argument is called `arg__2` in PySide{2,6} as per
# QTextCursor.movePosition.__doc__ and __signature__. Using `arg__2` as
# keyword argument works as intended, so does using a positional
# argument. Tested with PySide2 5.15.0, 5.15.2.1 and 5.15.3 and PySide6
# 6.3.0; older version, down to PySide 1, are probably affected as well [1].
#
# * PySide2 5.15.0 and 5.15.2.1 silently ignore invalid keyword arguments,
# i.e. passing the `mode` keyword argument has no effect and doesn`t
# raise an exception. Older versions, down to PySide 1, are probably
# affected as well [1]. At least PySide2 5.15.3 and PySide6 6.3.0 raise an
# exception when `mode` or any other invalid keyword argument is passed.
#
# [1] https://bugreports.qt.io/browse/PYSIDE-185
movePosition = QTextCursor.movePosition
def movePositionPatched(
self,
operation: QTextCursor.MoveOperation,
mode: QTextCursor.MoveMode = QTextCursor.MoveAnchor,
n: int = 1,
) -> bool:
return movePosition(self, operation, mode, n)
QTextCursor.movePosition = movePositionPatched
if PYQT5 or PYSIDE2:
# Part of the fix for https://github.com/spyder-ide/qtpy/issues/394
from qtpy.QtCore import QPointF as __QPointF
QNativeGestureEvent.x = lambda self: self.localPos().toPoint().x()
QNativeGestureEvent.y = lambda self: self.localPos().toPoint().y()
QNativeGestureEvent.position = lambda self: self.localPos()
QNativeGestureEvent.globalX = lambda self: self.globalPos().x()
QNativeGestureEvent.globalY = lambda self: self.globalPos().y()
QNativeGestureEvent.globalPosition = lambda self: __QPointF(
float(self.globalPos().x()),
float(self.globalPos().y()),
)
QEnterEvent.position = lambda self: self.localPos()
QEnterEvent.globalPosition = lambda self: __QPointF(
float(self.globalX()),
float(self.globalY()),
)
QTabletEvent.position = lambda self: self.posF()
QTabletEvent.globalPosition = lambda self: self.globalPosF()
QHoverEvent.x = lambda self: self.pos().x()
QHoverEvent.y = lambda self: self.pos().y()
QHoverEvent.position = lambda self: self.posF()
# No `QHoverEvent.globalPosition`, `QHoverEvent.globalX`,
# nor `QHoverEvent.globalY` in the Qt5 docs.
QMouseEvent.position = lambda self: self.localPos()
QMouseEvent.globalPosition = lambda self: __QPointF(
float(self.globalX()),
float(self.globalY()),
)
# Follow similar approach for `QDropEvent` and child classes
QDropEvent.position = lambda self: self.posF()
if PYQT6 or PYSIDE6:
# Part of the fix for https://github.com/spyder-ide/qtpy/issues/394
for _class in (
QNativeGestureEvent,
QEnterEvent,
QTabletEvent,
QHoverEvent,
QMouseEvent,
):
for _obsolete_function in (
"pos",
"x",
"y",
"globalPos",
"globalX",
"globalY",
):
if hasattr(_class, _obsolete_function):
delattr(_class, _obsolete_function)
QSinglePointEvent.pos = lambda self: self.position().toPoint()
QSinglePointEvent.posF = lambda self: self.position()
QSinglePointEvent.localPos = lambda self: self.position()
QSinglePointEvent.x = lambda self: self.position().toPoint().x()
QSinglePointEvent.y = lambda self: self.position().toPoint().y()
QSinglePointEvent.globalPos = lambda self: self.globalPosition().toPoint()
QSinglePointEvent.globalX = (
lambda self: self.globalPosition().toPoint().x()
)
QSinglePointEvent.globalY = (
lambda self: self.globalPosition().toPoint().y()
)
# Follow similar approach for `QDropEvent` and child classes
QDropEvent.pos = lambda self: self.position().toPoint()
QDropEvent.posF = lambda self: self.position()