Add patch for NodeGraphQt PySide6 6.7+ compatibility
The setSelectionArea() API changed in PySide6 6.7 - it now requires
an ItemSelectionOperation parameter before ItemSelectionMode.
Files added:
- patches/nodegraphqt_pyside6_compat.patch: Git-style patch file
- patches/UPSTREAM_ISSUE.md: Issue report for upstream project
- scripts/patch_nodegraphqt.py: Script to auto-apply the patch
The patch fixes rubber band selection errors when dragging in the
node graph viewer. Run after pip install:
python scripts/patch_nodegraphqt.py
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
042be8b49b
commit
ad9a59283c
|
|
@ -0,0 +1,80 @@
|
||||||
|
# PySide6 6.7+ Compatibility Issue: setSelectionArea API Change
|
||||||
|
|
||||||
|
## Issue
|
||||||
|
|
||||||
|
When using NodeGraphQt-QuiltiX-fork with PySide6 6.7+, dragging a rubber band selection in the node graph causes repeated TypeError exceptions:
|
||||||
|
|
||||||
|
```
|
||||||
|
TypeError: 'PySide6.QtWidgets.QGraphicsScene.setSelectionArea' called with wrong argument types:
|
||||||
|
PySide6.QtWidgets.QGraphicsScene.setSelectionArea(QPainterPath, ItemSelectionMode)
|
||||||
|
Supported signatures:
|
||||||
|
PySide6.QtWidgets.QGraphicsScene.setSelectionArea(PySide6.QtGui.QPainterPath, PySide6.QtGui.QTransform)
|
||||||
|
PySide6.QtWidgets.QGraphicsScene.setSelectionArea(PySide6.QtGui.QPainterPath, PySide6.QtCore.Qt.ItemSelectionOperation = Instance(Qt.ReplaceSelection), PySide6.QtCore.Qt.ItemSelectionMode = Instance(Qt.IntersectsItemShape), PySide6.QtGui.QTransform = Default(QTransform))
|
||||||
|
```
|
||||||
|
|
||||||
|
## Root Cause
|
||||||
|
|
||||||
|
The `QGraphicsScene.setSelectionArea()` method signature changed in PySide6 6.7. The old signature allowed:
|
||||||
|
|
||||||
|
```python
|
||||||
|
setSelectionArea(path, mode) # mode = Qt.ItemSelectionMode
|
||||||
|
```
|
||||||
|
|
||||||
|
The new signature requires:
|
||||||
|
|
||||||
|
```python
|
||||||
|
setSelectionArea(path, operation, mode) # operation = Qt.ItemSelectionOperation
|
||||||
|
```
|
||||||
|
|
||||||
|
## Affected File
|
||||||
|
|
||||||
|
`NodeGraphQt/widgets/viewer.py` line 524-526
|
||||||
|
|
||||||
|
## Current Code
|
||||||
|
|
||||||
|
```python
|
||||||
|
self.scene().setSelectionArea(
|
||||||
|
path, QtCore.Qt.IntersectsItemShape
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Fix
|
||||||
|
|
||||||
|
```python
|
||||||
|
self.scene().setSelectionArea(
|
||||||
|
path, QtCore.Qt.ReplaceSelection,
|
||||||
|
QtCore.Qt.IntersectsItemShape
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Environment
|
||||||
|
|
||||||
|
- Python: 3.12
|
||||||
|
- PySide6: 6.6.3.1 (installed by NodeGraphQt-QuiltiX-fork, but issue affects 6.7+)
|
||||||
|
- NodeGraphQt-QuiltiX-fork: 0.7.0
|
||||||
|
|
||||||
|
## Workaround
|
||||||
|
|
||||||
|
Apply this patch after installation:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# In viewer.py, change line 524-526 from:
|
||||||
|
self.scene().setSelectionArea(
|
||||||
|
path, QtCore.Qt.IntersectsItemShape
|
||||||
|
)
|
||||||
|
|
||||||
|
# To:
|
||||||
|
self.scene().setSelectionArea(
|
||||||
|
path, QtCore.Qt.ReplaceSelection,
|
||||||
|
QtCore.Qt.IntersectsItemShape
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
This issue may also exist in:
|
||||||
|
- Original NodeGraphQt
|
||||||
|
- OdenGraphQt
|
||||||
|
- Other forks
|
||||||
|
|
||||||
|
The fix is backward compatible with older PySide6 versions that support the 3-argument signature.
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
--- a/NodeGraphQt/widgets/viewer.py
|
||||||
|
+++ b/NodeGraphQt/widgets/viewer.py
|
||||||
|
@@ -521,8 +521,10 @@ class NodeViewer(QtWidgets.QGraphicsView):
|
||||||
|
path = QtGui.QPainterPath()
|
||||||
|
path.addRect(map_rect)
|
||||||
|
self._rubber_band.setGeometry(rect)
|
||||||
|
+ # PySide6 6.7+ requires ItemSelectionOperation parameter
|
||||||
|
self.scene().setSelectionArea(
|
||||||
|
- path, QtCore.Qt.IntersectsItemShape
|
||||||
|
+ path, QtCore.Qt.ReplaceSelection,
|
||||||
|
+ QtCore.Qt.IntersectsItemShape
|
||||||
|
)
|
||||||
|
self.scene().update(map_rect)
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Patch NodeGraphQt for PySide6 6.7+ compatibility.
|
||||||
|
|
||||||
|
The setSelectionArea() API changed in PySide6 6.7 to require an
|
||||||
|
ItemSelectionOperation parameter. This script patches the installed
|
||||||
|
NodeGraphQt package to work with newer PySide6 versions.
|
||||||
|
|
||||||
|
Issue: setSelectionArea(path, mode) -> setSelectionArea(path, operation, mode)
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python scripts/patch_nodegraphqt.py
|
||||||
|
|
||||||
|
This can be run after `pip install NodeGraphQt-QuiltiX-fork[pyside6]`
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import site
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def find_viewer_file():
|
||||||
|
"""Find the NodeGraphQt viewer.py file in site-packages."""
|
||||||
|
# Check common locations
|
||||||
|
for site_dir in site.getsitepackages() + [site.getusersitepackages()]:
|
||||||
|
viewer_path = Path(site_dir) / "NodeGraphQt" / "widgets" / "viewer.py"
|
||||||
|
if viewer_path.exists():
|
||||||
|
return viewer_path
|
||||||
|
|
||||||
|
# Check virtual environment
|
||||||
|
venv_path = Path(sys.prefix) / "lib"
|
||||||
|
for python_dir in venv_path.glob("python*"):
|
||||||
|
viewer_path = python_dir / "site-packages" / "NodeGraphQt" / "widgets" / "viewer.py"
|
||||||
|
if viewer_path.exists():
|
||||||
|
return viewer_path
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def patch_file(viewer_path: Path) -> bool:
|
||||||
|
"""Apply the PySide6 compatibility patch."""
|
||||||
|
content = viewer_path.read_text()
|
||||||
|
|
||||||
|
# Check if already patched
|
||||||
|
if "Qt.ReplaceSelection" in content:
|
||||||
|
print(f"Already patched: {viewer_path}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# The old code pattern
|
||||||
|
old_code = """self.scene().setSelectionArea(
|
||||||
|
path, QtCore.Qt.IntersectsItemShape
|
||||||
|
)"""
|
||||||
|
|
||||||
|
# The new code with ItemSelectionOperation
|
||||||
|
new_code = """self.scene().setSelectionArea(
|
||||||
|
path, QtCore.Qt.ReplaceSelection,
|
||||||
|
QtCore.Qt.IntersectsItemShape
|
||||||
|
)"""
|
||||||
|
|
||||||
|
if old_code not in content:
|
||||||
|
print(f"Warning: Could not find code to patch in {viewer_path}")
|
||||||
|
print("The file may have a different format or already be modified.")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Apply patch
|
||||||
|
patched_content = content.replace(old_code, new_code)
|
||||||
|
|
||||||
|
# Backup original
|
||||||
|
backup_path = viewer_path.with_suffix(".py.bak")
|
||||||
|
if not backup_path.exists():
|
||||||
|
viewer_path.rename(backup_path)
|
||||||
|
print(f"Backup created: {backup_path}")
|
||||||
|
|
||||||
|
# Write patched file
|
||||||
|
viewer_path.write_text(patched_content)
|
||||||
|
print(f"Patched successfully: {viewer_path}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("NodeGraphQt PySide6 Compatibility Patch")
|
||||||
|
print("=" * 40)
|
||||||
|
|
||||||
|
viewer_path = find_viewer_file()
|
||||||
|
|
||||||
|
if not viewer_path:
|
||||||
|
print("Error: Could not find NodeGraphQt installation.")
|
||||||
|
print("Make sure NodeGraphQt-QuiltiX-fork is installed:")
|
||||||
|
print(" pip install 'NodeGraphQt-QuiltiX-fork[pyside6]'")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
print(f"Found: {viewer_path}")
|
||||||
|
|
||||||
|
if patch_file(viewer_path):
|
||||||
|
print("\nPatch applied successfully!")
|
||||||
|
print("The rubber band selection should now work in PySide6 6.7+")
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
print("\nPatch failed.")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
Loading…
Reference in New Issue