1 # -----------------------------------------------------------------------------
2 # Copyright © 2014-2015 Colin Duquesnoy
3 # Copyright © 2009- The Spyder Development Team
5 # Licensed under the terms of the MIT License
6 # (see LICENSE.txt for details)
7 # -----------------------------------------------------------------------------
9 """Provides QtGui classes and functions."""
11 from . import PYQT5
, PYQT6
, PYSIDE2
, PYSIDE6
, QtModuleNotInstalledError
12 from ._utils
import getattr_missing_optional_dep
, possibly_static_exec
14 _missing_optional_names
= {}
19 "QOpenGLContextGroup",
21 "QOpenGLDebugMessage",
22 "QOpenGLFramebufferObject",
23 "QOpenGLFramebufferObjectFormat",
24 "QOpenGLPixelTransferOptions",
26 "QOpenGLShaderProgram",
28 "QOpenGLTextureBlitter",
29 "QOpenGLVersionProfile",
30 "QOpenGLVertexArrayObject",
35 def __getattr__(name
):
36 """Custom getattr to chain and wrap errors due to missing optional deps."""
37 raise getattr_missing_optional_dep(
40 optional_names
=_missing_optional_names
,
45 from PyQt5
.QtGui
import *
47 # Backport items moved to QtGui in Qt6
48 from PyQt5
.QtWidgets
import (
57 from PyQt6
import QtGui
58 from PyQt6
.QtGui
import *
60 # Attempt to import QOpenGL* classes, but if that fails,
61 # don't raise an exception until the name is explicitly accessed.
62 # See https://github.com/spyder-ide/qtpy/pull/387/
64 from PyQt6
.QtOpenGL
import *
65 except ImportError as error
:
66 for name
in _QTOPENGL_NAMES
:
67 _missing_optional_names
[name
] = {
68 "name": "PyQt6.QtOpenGL",
69 "missing_package": "pyopengl",
70 "import_error": error
,
73 QFontMetrics
.width
= lambda self
, *args
, **kwargs
: self
.horizontalAdvance(
77 QFontMetricsF
.width
= lambda self
, *args
, **kwargs
: self
.horizontalAdvance(
82 # Map missing/renamed methods
83 QDrag
.exec_
= lambda self
, *args
, **kwargs
: self
.exec(*args
, **kwargs
)
84 QGuiApplication
.exec_
= lambda *args
, **kwargs
: possibly_static_exec(
89 QTextDocument
.print_
= lambda self
, *args
, **kwargs
: self
.print(
94 # Allow unscoped access for enums inside the QtGui module
95 from .enums_compat
import promote_enums
100 from PySide2
.QtGui
import *
102 # Backport items moved to QtGui in Qt6
103 from PySide2
.QtWidgets
import (
111 if hasattr(QFontMetrics
, "horizontalAdvance"):
112 # Needed to prevent raising a DeprecationWarning when using QFontMetrics.width
113 QFontMetrics
.width
= (
114 lambda self
, *args
, **kwargs
: self
.horizontalAdvance(
120 from PySide6
.QtGui
import *
122 # Attempt to import QOpenGL* classes, but if that fails,
123 # don't raise an exception until the name is explicitly accessed.
124 # See https://github.com/spyder-ide/qtpy/pull/387/
126 from PySide6
.QtOpenGL
import *
127 except ImportError as error
:
128 for name
in _QTOPENGL_NAMES
:
129 _missing_optional_names
[name
] = {
130 "name": "PySide6.QtOpenGL",
131 "missing_package": "pyopengl",
132 "import_error": error
,
135 # Backport `QFileSystemModel` moved to QtGui in Qt6
136 from PySide6
.QtWidgets
import QFileSystemModel
138 QFontMetrics
.width
= lambda self
, *args
, **kwargs
: self
.horizontalAdvance(
142 QFontMetricsF
.width
= lambda self
, *args
, **kwargs
: self
.horizontalAdvance(
147 # Map DeprecationWarning methods
148 QDrag
.exec_
= lambda self
, *args
, **kwargs
: self
.exec(*args
, **kwargs
)
149 QGuiApplication
.exec_
= lambda *args
, **kwargs
: possibly_static_exec(
155 if PYSIDE2
or PYSIDE6
:
156 # PySide{2,6} do not accept the `mode` keyword argument in
157 # QTextCursor.movePosition() even though it is a valid optional argument
158 # as per C++ API. Fix this by monkeypatching.
162 # * The `mode` argument is called `arg__2` in PySide{2,6} as per
163 # QTextCursor.movePosition.__doc__ and __signature__. Using `arg__2` as
164 # keyword argument works as intended, so does using a positional
165 # argument. Tested with PySide2 5.15.0, 5.15.2.1 and 5.15.3 and PySide6
166 # 6.3.0; older version, down to PySide 1, are probably affected as well [1].
168 # * PySide2 5.15.0 and 5.15.2.1 silently ignore invalid keyword arguments,
169 # i.e. passing the `mode` keyword argument has no effect and doesn`t
170 # raise an exception. Older versions, down to PySide 1, are probably
171 # affected as well [1]. At least PySide2 5.15.3 and PySide6 6.3.0 raise an
172 # exception when `mode` or any other invalid keyword argument is passed.
174 # [1] https://bugreports.qt.io/browse/PYSIDE-185
175 movePosition
= QTextCursor
.movePosition
177 def movePositionPatched(
179 operation
: QTextCursor
.MoveOperation
,
180 mode
: QTextCursor
.MoveMode
= QTextCursor
.MoveAnchor
,
183 return movePosition(self
, operation
, mode
, n
)
185 QTextCursor
.movePosition
= movePositionPatched
188 # Part of the fix for https://github.com/spyder-ide/qtpy/issues/394
189 from qtpy
.QtCore
import QPointF
as __QPointF
191 QNativeGestureEvent
.x
= lambda self
: self
.localPos().toPoint().x()
192 QNativeGestureEvent
.y
= lambda self
: self
.localPos().toPoint().y()
193 QNativeGestureEvent
.position
= lambda self
: self
.localPos()
194 QNativeGestureEvent
.globalX
= lambda self
: self
.globalPos().x()
195 QNativeGestureEvent
.globalY
= lambda self
: self
.globalPos().y()
196 QNativeGestureEvent
.globalPosition
= lambda self
: __QPointF(
197 float(self
.globalPos().x()),
198 float(self
.globalPos().y()),
200 QEnterEvent
.position
= lambda self
: self
.localPos()
201 QEnterEvent
.globalPosition
= lambda self
: __QPointF(
202 float(self
.globalX()),
203 float(self
.globalY()),
205 QTabletEvent
.position
= lambda self
: self
.posF()
206 QTabletEvent
.globalPosition
= lambda self
: self
.globalPosF()
207 QHoverEvent
.x
= lambda self
: self
.pos().x()
208 QHoverEvent
.y
= lambda self
: self
.pos().y()
209 QHoverEvent
.position
= lambda self
: self
.posF()
210 # No `QHoverEvent.globalPosition`, `QHoverEvent.globalX`,
211 # nor `QHoverEvent.globalY` in the Qt5 docs.
212 QMouseEvent
.position
= lambda self
: self
.localPos()
213 QMouseEvent
.globalPosition
= lambda self
: __QPointF(
214 float(self
.globalX()),
215 float(self
.globalY()),
218 # Follow similar approach for `QDropEvent` and child classes
219 QDropEvent
.position
= lambda self
: self
.posF()
221 # Part of the fix for https://github.com/spyder-ide/qtpy/issues/394
229 for _obsolete_function
in (
237 if hasattr(_class
, _obsolete_function
):
238 delattr(_class
, _obsolete_function
)
239 QSinglePointEvent
.pos
= lambda self
: self
.position().toPoint()
240 QSinglePointEvent
.posF
= lambda self
: self
.position()
241 QSinglePointEvent
.localPos
= lambda self
: self
.position()
242 QSinglePointEvent
.x
= lambda self
: self
.position().toPoint().x()
243 QSinglePointEvent
.y
= lambda self
: self
.position().toPoint().y()
244 QSinglePointEvent
.globalPos
= lambda self
: self
.globalPosition().toPoint()
245 QSinglePointEvent
.globalX
= (
246 lambda self
: self
.globalPosition().toPoint().x()
248 QSinglePointEvent
.globalY
= (
249 lambda self
: self
.globalPosition().toPoint().y()
252 # Follow similar approach for `QDropEvent` and child classes
253 QDropEvent
.pos
= lambda self
: self
.position().toPoint()
254 QDropEvent
.posF
= lambda self
: self
.position()