Skip to content

Port QtVCP from PyQt5 to QtPy#3881

Open
bgermann wants to merge 1 commit intoLinuxCNC:masterfrom
bgermann:qtpy
Open

Port QtVCP from PyQt5 to QtPy#3881
bgermann wants to merge 1 commit intoLinuxCNC:masterfrom
bgermann:qtpy

Conversation

@bgermann
Copy link
Copy Markdown

@bgermann bgermann commented Mar 27, 2026

Replace all PyQt5-specific imports and idioms with their QtPy equivalents, making the codebase compatible with PyQt5 and PyQt6.

Import changes:

  • Replace from PyQt5.XXX import with from qtpy.XXX import
  • Replace bare from PyQt5 import XXX with from qtpy import XXX
  • Replace pyqtSignal, pyqtSlot, pyqtProperty with the qtpy canonical names Signal, Slot, Property
  • Port PyQt5.QtDesigner imports to qtpy.QtDesigner
  • Port PyQt5.Qsci imports to qtpy.Qsci

PDFViewer: add QtPdf backend as Qt6 alternative to popplerqt5

  • Try qtpy.QtPdf.QPdfDocument first; fall back to popplerqt5
  • Use QPdfDocumentRenderOptions with Annotations flag for render quality matching the popplerqt5 Antialiasing/TextAntialiasing hints

sys_notify: make DBus main loop integration backend-agnostic

  • Try dbus.mainloop.pyqt5, then pyqt6.

qtplasmac handlers: replace find_spec("PyQt5.QtWebEngineWidgets")

  • Use a module-level _WEBENGINE_AVAILABLE flag set by try/import of qtpy.QtWebEngineWidgets in the qtplasmac handler

plugins/status_label_plugin: fix pyqtProperty descriptor check

  • Replace fragile 'PyQt5.QtCore.pyqtProperty' in str(...) with isinstance(..., Property) to work across all Qt bindings

@bgermann bgermann mentioned this pull request Mar 27, 2026
@andypugh andypugh requested a review from c-morley March 27, 2026 20:36
@andypugh
Copy link
Copy Markdown
Collaborator

@c-morley The description sounds like a good approach. What do you think?

@snowgoer540
Copy link
Copy Markdown
Contributor

Made some time to apply this to the project and test it out.

After installing the necessary pyqt dependency, I get these in the terminal window when running the qtplasmac GUI:

QSocketNotifier: Can only be used with threads started with QThread
QSocketNotifier: Can only be used with threads started with QThread
QSocketNotifier: Can only be used with threads started with QThread
QSocketNotifier: Can only be used with threads started with QThread

@bgermann
Copy link
Copy Markdown
Author

bgermann commented Mar 27, 2026

QSocketNotifier: Can only be used with threads started with QThread

I have removed the dbus.mainloop.glib fallback (which was added for PySide which we do not need to support) so this should be fixed.

@snowgoer540
Copy link
Copy Markdown
Contributor

It still gave the same QSocketNotifier message. In order to fix it, I had to change the order of the import test to prefer testing pyqt5 first.

From:
for _mod in ('dbus.mainloop.pyqt6', 'dbus.mainloop.pyqt5'):

To:
for _mod in ('dbus.mainloop.pyqt5', 'dbus.mainloop.pyqt6'):

Replace all PyQt5-specific imports and idioms with their QtPy
equivalents, making the codebase compatible with PyQt5 and PyQt6.

Import changes:
- Replace `from PyQt5.XXX import` with `from qtpy.XXX import`
- Replace bare `from PyQt5 import XXX` with `from qtpy import XXX`
- Replace `pyqtSignal`, `pyqtSlot`, `pyqtProperty` with the qtpy
  canonical names `Signal`, `Slot`, `Property`
- Port `PyQt5.QtDesigner` imports to `qtpy.QtDesigner`
- Port `PyQt5.Qsci` imports to `qtpy.Qsci`

PDFViewer: add QtPdf backend as Qt6 alternative to popplerqt5
- Try `qtpy.QtPdf.QPdfDocument` first; fall back to popplerqt5
- Use `QPdfDocumentRenderOptions` with Annotations flag for render
  quality matching the popplerqt5 Antialiasing/TextAntialiasing hints

sys_notify: make DBus main loop integration backend-agnostic
- Try dbus.mainloop.pyqt5, then dbus.mainloop.pyqt6.

qtplasmac handlers: replace `find_spec("PyQt5.QtWebEngineWidgets")`
- Use a module-level `_WEBENGINE_AVAILABLE` flag set by try/import
  of `qtpy.QtWebEngineWidgets` in the qtplasmac handler.

plugins/status_label_plugin: fix pyqtProperty descriptor check
- Replace fragile `'PyQt5.QtCore.pyqtProperty' in str(...)` with
  `isinstance(..., Property)` to work across all Qt bindings
@bgermann
Copy link
Copy Markdown
Author

It still gave the same QSocketNotifier message. In order to fix it, I had to change the order of the import test to prefer testing pyqt5 first.

Applied to the PR.

Copy link
Copy Markdown
Contributor

@snowgoer540 snowgoer540 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From a QtPlasmaC standpoint this seems ok to merge. It will require RIP users to install the python3-qtpy dependency.

Will require @c-morley 's review prior to merging, he is much much more familiar with all of the core qtvcp stuff, and has many more affected GUIs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants