|
| 1 | +\page migration_qt6 Migrating Qt5 GUI plugins to Qt6 |
| 2 | + |
| 3 | +Prerequisite Tutorial: \ref plugins |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +Qt5 is planned to be removed in Ubuntu 26.04 LTS. In response to this, |
| 8 | +Gazebo GUI has upgraded its GUI framework from Qt5 to Qt6 in `gz-gui10` |
| 9 | +(Gazebo Jetty). This directly impacts all users who have developed |
| 10 | +their own custom Gazebo GUI plugins in Qt5. |
| 11 | + |
| 12 | +This tutorial will highlight important changes that users need to make |
| 13 | +to migrate their existing Qt5 Gazebo GUI plugins to Qt6. |
| 14 | + |
| 15 | +A Gazebo GUI is made up of C++, QML code, and configuration file, see |
| 16 | +the \ref plugins tutorial for more information. We expect that most of the |
| 17 | +required changes for porting to Qt6 will be in the QML code. |
| 18 | + |
| 19 | +## QML and C++ Integration |
| 20 | + |
| 21 | +In a Gazebo GUI plugin, users can create a QML interface that invokes C++ |
| 22 | +functionality and vice versa. There is one major syntax change to how |
| 23 | +this should be done from `gz-gui10` onwards. Prior to `gz-gui10`, access to |
| 24 | +C++ functions or properties was done with the following syntax in QML: |
| 25 | + |
| 26 | +```qml |
| 27 | +MyClass::FunctionFoo() |
| 28 | +``` |
| 29 | + |
| 30 | +The new syntax for doing this in Qt6 based Gazebo GUI plugin is: |
| 31 | + |
| 32 | +```qml |
| 33 | +_MyClass::FunctionFoo() |
| 34 | +``` |
| 35 | + |
| 36 | +As an example, in the Qt5 based `Screenshot` GUI plugin's QML code, we call |
| 37 | +[Screenshot.OnScreenshot()](https://github.com/gazebosim/gz-gui/blob/e0c95585919d95a01fbf3af9a33c7fcd653ab154/src/plugins/screenshot/Screenshot.qml#L50) |
| 38 | +which inovkes the corresponding [C++ function](https://github.com/gazebosim/gz-gui/blob/e0c95585919d95a01fbf3af9a33c7fcd653ab154/src/plugins/screenshot/Screenshot.cc#L188) |
| 39 | +defined in the `Screenshot` C++ class. |
| 40 | + |
| 41 | +In the Qt6 based Gazebo GUI plugin, the code is changed to |
| 42 | +[\_Screenshot.OnScreeShot()](https://github.com/gazebosim/gz-gui/blob/c7093159ac92031350cdf2c31283e3fdfd944194/src/plugins/screenshot/Screenshot.qml#L50) |
| 43 | +for the QML and C++ binding to work correctly. |
| 44 | + |
| 45 | +This is mainly because Qt6 enforces stricter property rules and that property |
| 46 | +names should not begin with an upper case letter. Gazebo adds an |
| 47 | +underscore prefix to workaround this problem. No changes should be needed on |
| 48 | +the C++ end. |
| 49 | + |
| 50 | +> Note: An alternative approach would be to choose a name that starts |
| 51 | +> with a lower case letter, i.e. `myClass.FunctionFoo()`. However, it was |
| 52 | +> noted that in many cases there exists an QML object with the id `myClass` |
| 53 | +> already which would conflict with the name of the C++ object. For example, the |
| 54 | +> Screenshot GUI plugin has a tool button with the id: |
| 55 | +> [screenshot](https://github.com/gazebosim/gz-gui/blob/c7093159ac92031350cdf2c31283e3fdfd944194/src/plugins/screenshot/Screenshot.qml#L37). |
| 56 | +> Hence a decision was made to add the `_` prefix to avoid any potential |
| 57 | +> naming conflicts. |
| 58 | +
|
| 59 | +## QML Migration |
| 60 | + |
| 61 | +Gazebo gives users the freedom to import any QML modules in their QML code |
| 62 | +and create their UI in a way that is no different from writing other Qt |
| 63 | +programs. So users would need to follow the general |
| 64 | +[porting guide](https://doc.qt.io/qt-6/portingguide.html), paying attention |
| 65 | +to the QML and module changes. Some QML modules and types are obsolete while |
| 66 | +some QML types have significant syntax changes. |
| 67 | + |
| 68 | +Common changes for porting Qt5 QML code to Qt6 include: |
| 69 | +* Importing a newer version of the Qt module, which can be done by removing the |
| 70 | + version number, e.g. `import QtQuick.Dialogs 1.0` becomes |
| 71 | + `import QtQuick.Dialogs`. |
| 72 | +* Adding the `_` prefix to the C++ object name as described in the |
| 73 | + `QML and C++ Integration` section above. |
| 74 | +* QML types requiring more code changes include but not limited to: |
| 75 | + [FileDialog](https://doc.qt.io/qt-6/qml-qtquick-dialogs-filedialog.html) and |
| 76 | + [TreeView](https://doc.qt.io/qt-6/qml-qtquick-treeview.html). |
| 77 | + * This [Qt6 migration pull request](https://github.com/gazebosim/gz-sim/pull/2832/files#diff-a93324029765acbdf791f6e6ed06b1ea2e2886a756f949e7948f7824a57b4e7b) |
| 78 | + shows examples of porting various Qt5 Gazebo GUI plugins to Qt6. |
| 79 | + |
| 80 | +## Qt App and Event Loop |
| 81 | + |
| 82 | +The core of Gazebo GUI sets up the necessary code for running an Qt application |
| 83 | +and its event loop. Here are some related migration notes: |
| 84 | + |
| 85 | +* The main C++ API in Gazebo GUI for retrieving the running Qt Application |
| 86 | +is [App()](https://github.com/gazebosim/gz-gui/blob/e0c95585919d95a01fbf3af9a33c7fcd653ab154/include/gz/gui/Application.hh#L224) |
| 87 | +which essentially returns a |
| 88 | +[qGuiApp](https://doc.qt.io/qt-6/qguiapplication.html#qGuiApp) pointer. |
| 89 | +This pointer is no longer always guaranteed to be non-null. Users should check this |
| 90 | +pointer to make sure it is valid before using it. |
| 91 | +* Users are discouraged from calling |
| 92 | +[QCoreApplication::processEvents](https://doc.qt.io/qt-6/qcoreapplication.html#processEvents) |
| 93 | +manually in Qt6. |
0 commit comments