Closed vp1981 closed 1 week ago
xasy
doesn't run yet with this patch but I've committed it to the qt6
branch (along with regenerated windows/*.ui
files) for further development:
xasy
Traceback (most recent call last):
File "/u/bowman/bin/xasy", line 18, in <module>
sys.exit(main(sys.argv) or 0)
^^^^^^^^^^^^^^
File "/u/bowman/bin/xasy", line 12, in main
mainWin1 = MainWindow1()
^^^^^^^^^^^^^
File "/u/bowman/asymptote/GUI/Window1.py", line 331, in __init__
self.populateOpenRecent()
File "/u/bowman/asymptote/GUI/Window1.py", line 1204, in populateOpenRecent
action = Qw.QAction(path, self, triggered = lambda state, path = path: self.actionOpen(fileName = path))
^^^^^^^^^^
AttributeError: module 'PyQt6.QtWidgets' has no attribute 'QAction'
Hello.
I found one other missed part in the previous patch and also fixed this issue.
From e5eeb94cad2e73d76df68f0a3536faf61b4a2306 Mon Sep 17 00:00:00 2001
From: Vladimir Lomov <vladimir@bnode.bkoty.ru>
Date: Thu, 27 Jun 2024 13:44:52 +0800
Subject: [PATCH 2/2] Migrate to python pyqt6
Signed-off-by: Vladimir Lomov <vladimir@bnode.bkoty.ru>
---
GUI/ContextWindow.py | 6 +++---
GUI/CustMatTransform.py | 6 +++---
GUI/GuidesManager.py | 4 ++--
GUI/InplaceAddObj.py | 4 ++--
GUI/PrimitiveShape.py | 4 ++--
GUI/SetCustomAnchor.py | 6 +++---
GUI/Widg_addLabel.py | 4 ++--
GUI/Widg_addPolyOpt.py | 4 ++--
GUI/Widg_editBezier.py | 4 ++--
GUI/Window1.py | 29 ++++++++++++++---------------
GUI/labelEditor.py | 8 ++++----
GUI/requirements.txt | 8 ++++----
GUI/xasy.py | 8 +++-----
GUI/xasy2asy.py | 8 ++++----
GUI/xasyArgs.py | 2 +-
GUI/xasyBezierInterface.py | 6 +++---
GUI/xasySvg.py | 4 ++--
GUI/xasyTransform.py | 4 ++--
Makefile.in | 4 ++--
19 files changed, 60 insertions(+), 63 deletions(-)
diff --git a/GUI/ContextWindow.py b/GUI/ContextWindow.py
index 53044726..b5bf3f1a 100644
--- a/GUI/ContextWindow.py
+++ b/GUI/ContextWindow.py
@@ -1,8 +1,8 @@
#!/usr/bin/env python3
-import PyQt5.QtWidgets as Qw
-import PyQt5.QtGui as Qg
-import PyQt5.QtCore as Qc
+import PyQt6.QtWidgets as Qw
+import PyQt6.QtGui as Qg
+import PyQt6.QtCore as Qc
import xasyVersion
import xasyUtils as xu
diff --git a/GUI/CustMatTransform.py b/GUI/CustMatTransform.py
index 0a66807d..4ffcde19 100644
--- a/GUI/CustMatTransform.py
+++ b/GUI/CustMatTransform.py
@@ -1,8 +1,8 @@
#!/usr/bin/env python3
-import PyQt5.QtWidgets as QtWidgets
-import PyQt5.QtGui as QtGui
-import PyQt5.QtCore as QtCore
+import PyQt6.QtWidgets as QtWidgets
+import PyQt6.QtGui as QtGui
+import PyQt6.QtCore as QtCore
import numpy as numpy
import xasy2asy as xasy2asy
from pyUIClass.custMatTransform import Ui_Dialog
diff --git a/GUI/GuidesManager.py b/GUI/GuidesManager.py
index fd317439..cdfd4cdb 100644
--- a/GUI/GuidesManager.py
+++ b/GUI/GuidesManager.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
-import PyQt5.QtGui as QtGui
-import PyQt5.QtCore as QtCore
+import PyQt6.QtGui as QtGui
+import PyQt6.QtCore as QtCore
import numpy as numpy
class Guide:
diff --git a/GUI/InplaceAddObj.py b/GUI/InplaceAddObj.py
index 9bacd5f5..a0437a72 100644
--- a/GUI/InplaceAddObj.py
+++ b/GUI/InplaceAddObj.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
-import PyQt5.QtCore as QtCore
-import PyQt5.QtGui as QtGui
+import PyQt6.QtCore as QtCore
+import PyQt6.QtGui as QtGui
import xasy2asy as xasy2asy
import PrimitiveShape
diff --git a/GUI/PrimitiveShape.py b/GUI/PrimitiveShape.py
index bbb24148..09aa40f6 100644
--- a/GUI/PrimitiveShape.py
+++ b/GUI/PrimitiveShape.py
@@ -3,8 +3,8 @@
import xasy2asy as xasy2asy
import numpy as numpy
import math
-import PyQt5.QtCore as QtCore
-import PyQt5.QtGui as QtGui
+import PyQt6.QtCore as QtCore
+import PyQt6.QtGui as QtGui
class PrimitiveShape:
diff --git a/GUI/SetCustomAnchor.py b/GUI/SetCustomAnchor.py
index e4414fec..1eb58234 100644
--- a/GUI/SetCustomAnchor.py
+++ b/GUI/SetCustomAnchor.py
@@ -1,8 +1,8 @@
#!/usr/bin/env python3
-import PyQt5.QtWidgets as QtWidgets
-import PyQt5.QtGui as QtGui
-import PyQt5.QtCore as QtCore
+import PyQt6.QtWidgets as QtWidgets
+import PyQt6.QtGui as QtGui
+import PyQt6.QtCore as QtCore
from pyUIClass.setCustomAnchor import Ui_Dialog
diff --git a/GUI/Widg_addLabel.py b/GUI/Widg_addLabel.py
index a5a65035..7a12dfd3 100644
--- a/GUI/Widg_addLabel.py
+++ b/GUI/Widg_addLabel.py
@@ -1,8 +1,8 @@
#!/usr/bin/env python3
from pyUIClass.widg_addLabel import Ui_Form
-import PyQt5.QtWidgets as QtWidgets
-import PyQt5.QtGui as QtGui
+import PyQt6.QtWidgets as QtWidgets
+import PyQt6.QtGui as QtGui
import labelEditor
import xasyUtils as xu
diff --git a/GUI/Widg_addPolyOpt.py b/GUI/Widg_addPolyOpt.py
index 3d1e419d..8434c0ca 100644
--- a/GUI/Widg_addPolyOpt.py
+++ b/GUI/Widg_addPolyOpt.py
@@ -1,8 +1,8 @@
#!/usr/bin/env python3
from pyUIClass.widg_addPolyOpt import Ui_Form
-import PyQt5.QtWidgets as QtWidgets
-import PyQt5.QtGui as QtGui
+import PyQt6.QtWidgets as QtWidgets
+import PyQt6.QtGui as QtGui
import sys
diff --git a/GUI/Widg_editBezier.py b/GUI/Widg_editBezier.py
index 161715e0..b3b50327 100644
--- a/GUI/Widg_editBezier.py
+++ b/GUI/Widg_editBezier.py
@@ -2,8 +2,8 @@
from pyUIClass.widg_editBezier import Ui_Form
-import PyQt5.QtWidgets as QtWidgets
-import PyQt5.QtCore as QtCore
+import PyQt6.QtWidgets as QtWidgets
+import PyQt6.QtCore as QtCore
class LockMode:
noLock = 0
diff --git a/GUI/Window1.py b/GUI/Window1.py
index 1e65b235..0cade188 100644
--- a/GUI/Window1.py
+++ b/GUI/Window1.py
@@ -2,9 +2,9 @@
from pyUIClass.window1 import Ui_MainWindow
-import PyQt5.QtWidgets as Qw
-import PyQt5.QtGui as Qg
-import PyQt5.QtCore as Qc
+import PyQt6.QtWidgets as Qw
+import PyQt6.QtGui as Qg
+import PyQt6.QtCore as Qc
import xasyVersion
import numpy as np
@@ -203,7 +203,7 @@ class MainWindow1(Qw.QMainWindow):
self.panOffset = [0, 0]
# Keyboard can focus outside of textboxes
- self.setFocusPolicy(Qc.Qt.StrongFocus)
+ self.setFocusPolicy(Qc.Qt.FocusPolicy.StrongFocus)
super().setMouseTracking(True)
# setMouseTracking(True)
@@ -1121,7 +1121,7 @@ class MainWindow1(Qw.QMainWindow):
"""Inverts the mapping of the key
Input map is in format 'Action' : 'Key Sequence' """
for action, key in self.keyMaps.options.items():
- shortcut = Qw.QShortcut(self)
+ shortcut = Qg.QShortcut(self)
shortcut.setKey(Qg.QKeySequence(key))
# hate doing this, but python doesn't have explicit way to pass a
@@ -1146,7 +1146,7 @@ class MainWindow1(Qw.QMainWindow):
#We include this function to keep the general program flow consistent
def closeEvent(self, event):
- if self.actionClose() == Qw.QMessageBox.Cancel:
+ if self.actionClose() == Qw.QMessageBox.StandardButton.Cancel:
event.ignore()
def actionNewFile(self):
@@ -1201,7 +1201,7 @@ class MainWindow1(Qw.QMainWindow):
for count, path in enumerate(self.openRecent.pathList):
if count > 8:
break
- action = Qw.QAction(path, self, triggered = lambda state, path = path: self.actionOpen(fileName = path))
+ action = Qg.QAction(path, self, triggered = lambda state, path = path: self.actionOpen(fileName = path))
self.ui.menuOpenRecent.addAction(action)
self.ui.menuOpenRecent.addSeparator()
self.ui.menuOpenRecent.addAction("Clear", self.actionClearRecent)
@@ -1361,7 +1361,7 @@ class MainWindow1(Qw.QMainWindow):
if self.mainCanvas.isActive():
self.mainCanvas.end()
self.canvSize = self.ui.imgFrame.size()*devicePixelRatio
- self.ui.imgFrame.setSizePolicy(Qw.QSizePolicy.Ignored, Qw.QSizePolicy.Ignored)
+ self.ui.imgFrame.setSizePolicy(Qw.QSizePolicy.Policy.Ignored, Qw.QSizePolicy.Policy.Ignored)
self.canvasPixmap = Qg.QPixmap(self.canvSize)
self.canvasPixmap.setDevicePixelRatio(devicePixelRatio)
self.postCanvasPixmap = Qg.QPixmap(self.canvSize)
@@ -1746,7 +1746,7 @@ class MainWindow1(Qw.QMainWindow):
def createMainCanvas(self):
self.canvSize = devicePixelRatio*self.ui.imgFrame.size()
- self.ui.imgFrame.setSizePolicy(Qw.QSizePolicy.Ignored, Qw.QSizePolicy.Ignored)
+ self.ui.imgFrame.setSizePolicy(Qw.QSizePolicy.Policy.Ignored, Qw.QSizePolicy.Policy.Ignored)
factor=0.5/devicePixelRatio;
x, y = self.canvSize.width()*factor, self.canvSize.height()*factor
@@ -1762,9 +1762,8 @@ class MainWindow1(Qw.QMainWindow):
self.postCanvasPixmap.setDevicePixelRatio(devicePixelRatio)
self.mainCanvas = Qg.QPainter(self.canvasPixmap)
- self.mainCanvas.setRenderHint(Qg.QPainter.Antialiasing)
- self.mainCanvas.setRenderHint(Qg.QPainter.SmoothPixmapTransform)
- self.mainCanvas.setRenderHint(Qg.QPainter.HighQualityAntialiasing)
+ self.mainCanvas.setRenderHint(Qg.QPainter.RenderHint.Antialiasing)
+ self.mainCanvas.setRenderHint(Qg.QPainter.RenderHint.SmoothPixmapTransform)
self.xasyDrawObj['canvas'] = self.mainCanvas
self.mainTransformation = Qg.QTransform()
@@ -1921,7 +1920,7 @@ class MainWindow1(Qw.QMainWindow):
def updateScreen(self):
self.finalPixmap = Qg.QPixmap(self.canvSize)
self.finalPixmap.setDevicePixelRatio(devicePixelRatio)
- self.finalPixmap.fill(Qc.Qt.black)
+ self.finalPixmap.fill(Qg.QColorConstants.Svg.black)
with Qg.QPainter(self.finalPixmap) as finalPainter:
drawPoint = Qc.QPoint(0, 0)
finalPainter.drawPixmap(drawPoint, self.canvasPixmap)
@@ -2017,7 +2016,7 @@ class MainWindow1(Qw.QMainWindow):
preCanvas.setTransform(self.getScrsTransform())
if self.drawAxes:
- preCanvas.setPen(Qc.Qt.gray)
+ preCanvas.setPen(Qg.QColorConstants.Svg.gray)
self.makePenCosmetic(preCanvas)
preCanvas.drawLine(Qc.QLine(-9999, 0, 9999, 0))
preCanvas.drawLine(Qc.QLine(0, -9999, 0, 9999))
@@ -2069,7 +2068,7 @@ class MainWindow1(Qw.QMainWindow):
painter.restore()
def postDraw(self):
- self.postCanvasPixmap.fill(Qc.Qt.transparent)
+ self.postCanvasPixmap.fill(Qg.QColorConstants.Transparent)
with Qg.QPainter(self.postCanvasPixmap) as postCanvas:
postCanvas.setRenderHints(self.mainCanvas.renderHints())
postCanvas.setTransform(self.getScrsTransform())
diff --git a/GUI/labelEditor.py b/GUI/labelEditor.py
index 7da1c5f9..aacc3422 100644
--- a/GUI/labelEditor.py
+++ b/GUI/labelEditor.py
@@ -1,10 +1,10 @@
#!/usr/bin/env python3
from pyUIClass.labelTextEditor import Ui_Dialog
-import PyQt5.QtWidgets as QtWidgets
-import PyQt5.QtSvg as QtSvg
-import PyQt5.QtGui as QtGui
-import PyQt5.QtCore as QtCore
+import PyQt6.QtWidgets as QtWidgets
+import PyQt6.QtSvg as QtSvg
+import PyQt6.QtGui as QtGui
+import PyQt6.QtCore as QtCore
import xasyArgs as xasyArgs
import xasy2asy as xasy2asy
import xasyOptions as xasyOptions
diff --git a/GUI/requirements.txt b/GUI/requirements.txt
index 6e0a4419..62fcb415 100644
--- a/GUI/requirements.txt
+++ b/GUI/requirements.txt
@@ -1,4 +1,4 @@
-numpy==1.22.0
-cson==0.7
-PyQt5==5.11
-rsvg-convert==2.42.3
+numpy==2.0.0
+cson==0.8
+PyQt6==6.7.0
+rsvg-convert==2.58.1
diff --git a/GUI/xasy.py b/GUI/xasy.py
index a078690b..6bbfb7f6 100755
--- a/GUI/xasy.py
+++ b/GUI/xasy.py
@@ -1,19 +1,17 @@
#!/usr/bin/env python3
import sys, signal, os
-import PyQt5.QtWidgets as QtWidgets
-import PyQt5.QtCore as QtCore
+import PyQt6.QtWidgets as QtWidgets
+import PyQt6.QtCore as QtCore
from Window1 import MainWindow1
def main(args):
os.environ["QT_LOGGING_RULES"]="*.debug=false;qt.qpa.*=false"
- QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps,True)
- QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling,True)
qtApp = QtWidgets.QApplication(args)
signal.signal(signal.SIGINT,signal.SIG_DFL)
mainWin1 = MainWindow1()
mainWin1.show()
- return qtApp.exec_()
+ return qtApp.exec()
if __name__ == '__main__':
diff --git a/GUI/xasy2asy.py b/GUI/xasy2asy.py
index cf1edb8a..eccd5a3a 100644
--- a/GUI/xasy2asy.py
+++ b/GUI/xasy2asy.py
@@ -9,10 +9,10 @@
#
###########################################################################
-import PyQt5.QtWidgets as QtWidgets
-import PyQt5.QtGui as QtGui
-import PyQt5.QtCore as QtCore
-import PyQt5.QtSvg as QtSvg
+import PyQt6.QtWidgets as QtWidgets
+import PyQt6.QtGui as QtGui
+import PyQt6.QtCore as QtCore
+import PyQt6.QtSvg as QtSvg
import numpy as numpy
diff --git a/GUI/xasyArgs.py b/GUI/xasyArgs.py
index b9e1518f..82c11259 100644
--- a/GUI/xasyArgs.py
+++ b/GUI/xasyArgs.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
import argparse
import xasyVersion
-import PyQt5.QtCore as QtCore
+import PyQt6.QtCore as QtCore
# Add arguments here.
diff --git a/GUI/xasyBezierInterface.py b/GUI/xasyBezierInterface.py
index abe8d9b0..4fd67bc9 100644
--- a/GUI/xasyBezierInterface.py
+++ b/GUI/xasyBezierInterface.py
@@ -1,9 +1,9 @@
#!/usr/bin/env python3
-import PyQt5.QtWidgets as QtWidgets
-import PyQt5.QtCore as QtCore
-import PyQt5.QtGui as QtGui
+import PyQt6.QtWidgets as QtWidgets
+import PyQt6.QtCore as QtCore
+import PyQt6.QtGui as QtGui
import xasy2asy as xasy2asy
import xasyUtils as xasyUtils
import Widg_editBezier as Web
diff --git a/GUI/xasySvg.py b/GUI/xasySvg.py
index 7261dc5b..8aa5ec60 100644
--- a/GUI/xasySvg.py
+++ b/GUI/xasySvg.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
-import PyQt5.QtGui as QtGui
-import PyQt5.QtWidgets as QtWidgets
+import PyQt6.QtGui as QtGui
+import PyQt6.QtWidgets as QtWidgets
import io
import subprocess
import sys
diff --git a/GUI/xasyTransform.py b/GUI/xasyTransform.py
index cb70bf1e..da444906 100644
--- a/GUI/xasyTransform.py
+++ b/GUI/xasyTransform.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
import xasy2asy as xasy2asy
-import PyQt5.QtGui as QtGui
-import PyQt5.QtCore as QtCore
+import PyQt6.QtGui as QtGui
+import PyQt6.QtCore as QtCore
import numpy as numpy
import math
diff --git a/Makefile.in b/Makefile.in
index 1c7866fe..35d1245f 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -19,8 +19,8 @@ CMAKE ?= cmake
PERL ?= perl
PYTHON ?= python3
BISON ?= bison
-PYRCC ?= pyrcc5
-PYUIC ?= pyuic5
+PYRCC ?= pyrcc6
+PYUIC ?= pyuic6
# Libraries needed to make asymptote.so.
# We have to remove OpenGL, threading, GC, etc from this.
--
2.45.2
Sorry, no PR this yet (I couldn't get how to work with PR, plain patches are more simple for me).
Could you please post a patch relative to the qt6 branch, which already contains your previous patch? Or better, I could give you developer access if you send me your GitHub user ID.
Ok, this one
From 1fe21e1e9acb5bb528aa6fa6f304073912317aff Mon Sep 17 00:00:00 2001
From: Vladimir Lomov <vladimir@bnode.bkoty.ru>
Date: Fri, 28 Jun 2024 09:15:01 +0800
Subject: [PATCH] Fixed QAction and QSizePolicy issues
- QAction is now part of QGui;
- QSizePolicy flags are now accessible via QSizePolicy.Policy.
Signed-off-by: Vladimir Lomov <vladimir@bnode.bkoty.ru>
---
GUI/Window1.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/GUI/Window1.py b/GUI/Window1.py
index b7ccbedd..38e06e87 100644
--- a/GUI/Window1.py
+++ b/GUI/Window1.py
@@ -1201,7 +1201,7 @@ class MainWindow1(Qw.QMainWindow):
for count, path in enumerate(self.openRecent.pathList):
if count > 8:
break
- action = Qw.QAction(path, self, triggered = lambda state, path = path: self.actionOpen(fileName = path))
+ action = Qg.QAction(path, self, triggered = lambda state, path = path: self.actionOpen(fileName = path))
self.ui.menuOpenRecent.addAction(action)
self.ui.menuOpenRecent.addSeparator()
self.ui.menuOpenRecent.addAction("Clear", self.actionClearRecent)
@@ -1361,7 +1361,7 @@ class MainWindow1(Qw.QMainWindow):
if self.mainCanvas.isActive():
self.mainCanvas.end()
self.canvSize = self.ui.imgFrame.size()*devicePixelRatio
- self.ui.imgFrame.setSizePolicy(Qw.QSizePolicy.Policy.Ignored, Qw.QSizePolicy.Ignored)
+ self.ui.imgFrame.setSizePolicy(Qw.QSizePolicy.Policy.Ignored, Qw.QSizePolicy.Policy.Ignored)
self.canvasPixmap = Qg.QPixmap(self.canvSize)
self.canvasPixmap.setDevicePixelRatio(devicePixelRatio)
self.postCanvasPixmap = Qg.QPixmap(self.canvSize)
@@ -1746,7 +1746,7 @@ class MainWindow1(Qw.QMainWindow):
def createMainCanvas(self):
self.canvSize = devicePixelRatio*self.ui.imgFrame.size()
- self.ui.imgFrame.setSizePolicy(Qw.QSizePolicy.Policy.Ignored, Qw.QSizePolicy.Ignored)
+ self.ui.imgFrame.setSizePolicy(Qw.QSizePolicy.Policy.Ignored, Qw.QSizePolicy.Policy.Ignored)
factor=0.5/devicePixelRatio;
x, y = self.canvSize.width()*factor, self.canvSize.height()*factor
--
2.45.2
Ok, I've applied that patch to the qt6 branch, without these two extraneous lines, which should be removed:
--
2.45.2
xasy now loads but the icons are missing...
Another issue... xasy examples/venn.asy Traceback (most recent call last): File "/u/bowman/asymptote/GUI/Window1.py", line 1485, in mouseMoveEvent selectedIndex, selKeyList = self.selectObject() ^^^^^^^^^^^^^^^^^^^ File "/u/bowman/asymptote/GUI/Window1.py", line 1803, in selectObject if obj.collide(canvasCoords) and (obj.key, obj.keyIndex) not in self.hiddenKeys: ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/u/bowman/asymptote/GUI/xasy2asy.py", line 1869, in collide return self.boundingBox.marginsAdded(newMargin).contains(coords) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TypeError: arguments did not match any overloaded call: contains(self, p: QPointF): argument 1 has unexpected type 'QPoint' contains(self, r: QRectF): argument 1 has unexpected type 'QPoint' contains(self, ax: float, ay: float): argument 1 has unexpected type 'QPoint' Traceback (most recent call last): File "/u/bowman/asymptote/GUI/Window1.py", line 1485, in mouseMoveEvent selectedIndex, selKeyList = self.selectObject() ^^^^^^^^^^^^^^^^^^^ File "/u/bowman/asymptote/GUI/Window1.py", line 1803, in selectObject if obj.collide(canvasCoords) and (obj.key, obj.keyIndex) not in self.hiddenKeys: ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/u/bowman/asymptote/GUI/xasy2asy.py", line 1869, in collide return self.boundingBox.marginsAdded(newMargin).contains(coords) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TypeError: arguments did not match any overloaded call: contains(self, p: QPointF): argument 1 has unexpected type 'QPoint' contains(self, r: QRectF): argument 1 has unexpected type 'QPoint' contains(self, ax: float, ay: float): argument 1 has unexpected type 'QPoint' Abort (core dumped)
Before I dive into it, could you enlighten me, should we use QPoint
or QPointF
? The former uses integers and the latter uses floats. If both are used, then I will carefully go through the code to see how they are used.
I think you want to use QPointF everywhere.
Hello.
I prepared (rude) patch to make
xasy
use python-pyqt6. I only checked that thexasy
is run, but actually I don't use it.Below is a patch, this is the source.