Plugin migration to be compatible with Qt5 and Qt6 - qgis/QGIS GitHub Wiki

Qt 5 to 6 migration for PyQGIS

It's possible to make a plugin for both Qt5 and Qt6.

Script

To run this script, you need QGIS with Qt6 but without Qt5.

  1. Install Python dependencies:

    pip install astpretty tokenize-rt
    
  2. Install additional system dependencies. Typically on Debian based-images:

    sudo apt install python3-pyqt6 python3-pyqt6.qtsvg python3-pyqt6.qsci
    
  3. Download the pyqt5_to_pyqt6 script

  4. You should check that PyQt5 is not available in the Python environment, the script will work better

  5. Run it with:

pyqt5_to_pyqt6.py /path/to/plugin
  1. If your plugin is intended to support more than one major QGIS version (e.g. both QGIS 3 and 4), you must explicitly set qgisMaximumVersion in metadata.txt, for example: qgisMaximumVersion=4.99. Otherwise your plugin will not be loaded by QGIS 4. However, if your plugin only targets QGIS 4 and no longer supports QGIS 3.x, simply set qgisMinimumVersion=4.0 and do not define qgisMaximumVersion (as it's optional).

[!NOTE] Due to a recent change just before the release of QGIS 4.0.0, the use of supportsQt6=True (which was indicated in blogposts, documentation, or this wiki before) is not needed anymore and can be safely removed. Tags qgisMinimumVersion (required) and qgisMaximumVersion (optional) should be used instead with adapted values. See the migration guide on the official plugins repository.

This will get you in the right direction but might not do all necessary changes. Make sure to test your plugin thoroughly. Consider using an IDE with inspection that can notify you about broken imports, bad usage or non-existent references.

Use OSGeo4W shell (for Windows users)

Install a QGIS 4 first, see for example "Latest Version for Windows (4.0)" on https://qgis.org/download and start the "OSGeo4W Shell" (starting the start menu entry or by running OSGeo4W.bat from the install directory). From THAT command window, run the following:

REM all from within the OSGeo4W Shell window!
curl -LO https://raw.githubusercontent.com/qgis/QGIS/refs/heads/master/scripts/pyqt5_to_pyqt6/pyqt5_to_pyqt6.py
pip install astpretty tokenize-rt
python-qgis pyqt5_to_pyqt6.py "path/to/plugin"

If all went well the script silently ends and you will have QgsMapLayer.VectorLayer -> QgsMapLayer.LayerType.VectorLayer and QMessageBox.Ok -> QMessageBox.StandardButton.Ok which will work both in Qt5/QGIS3 and Qt6/QGIS4.

Use Docker image

A bundled image with QGIS based on Qt6 and the migration script is available: https://github.com/qgis/pyqgis4-checker. Check the documentation!

Official C++ documentation

Differences Between PyQt6 and PyQt5 (Riverbank Computing)

https://www.riverbankcomputing.com/static/Docs/PyQt6/pyqt5_differences.html "gives an overview of the differences between PyQt6 and PyQt5. This is not an exhaustive list and does not go into the detail of the differences between the Qt v6 and Qt v5 APIs."

Manual conversion

To make a code working for both versions, it's mostly about how enums are called. For instance, according to Qt Namespace :

Working only in PyQt5 Working for both PyQt5 and PyQt6
Qt.UserRole Qt.ItemDataRole.UserRole
Qt.WaitCursor Qt.CursorShape.WaitCursor
Qt.blue Qt.GlobalColor.blue
etc. etc.

Same for QGIS enums:

Working only in PyQt5 Working for both PyQt5 and PyQt6
Qgis.Critical Qgis.MessageLevel.Critical
QgsWkbTypes.PolygonGeometry QgsWkbTypes.GeometryType.PolygonGeometry
QgsMapLayer.VectorLayer  QgsMapLayer.LayerType.VectorLayer