pyqt5qt-creatorpyqgis

ui files made with qt creator have invalid syntax for qgis


I made a UI in QT Creator that only has QDialogButtonBox:
default buttons

When I save it out, the .ui file looks like:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>ProjectDialogBase</class>
 <widget class="QDialog" name="ProjectDialogBase">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>184</width>
    <height>47</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Settings</string>
  </property>
  <widget class="QDialogButtonBox" name="button_box">
   <property name="geometry">
    <rect>
     <x>-10</x>
     <y>10</y>
     <width>181</width>
     <height>23</height>
    </rect>
   </property>
   <property name="orientation">
    <enum>Qt::Orientation::Horizontal</enum>
   </property>
   <property name="standardButtons">
    <set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
   </property>
  </widget>
 </widget>
 <resources/>
 <connections>
  <connection>
   <sender>button_box</sender>
   <signal>rejected()</signal>
   <receiver>ProjectDialogBase</receiver>
   <slot>reject()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>20</x>
     <y>20</y>
    </hint>
    <hint type="destinationlabel">
     <x>20</x>
     <y>20</y>
    </hint>
   </hints>
  </connection>
  <connection>
   <sender>button_box</sender>
   <signal>accepted()</signal>
   <receiver>ProjectDialogBase</receiver>
   <slot>accept()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>20</x>
     <y>20</y>
    </hint>
    <hint type="destinationlabel">
     <x>20</x>
     <y>20</y>
    </hint>
   </hints>
  </connection>
 </connections>
</ui>

When I zip it up and try to import it into QGIS in a plugin, the file fails to compile:

  File "/home/username/.var/app/org.qgis.qgis/data/QGIS/QGIS3/profiles/default/python/plugins/sync/interfaces/settings_dialogue.py", line 8, in 
    FORM_CLASS, _ = uic.loadUiType(os.path.join(os.path.dirname(__file__), 'settings_dialogue.ui'))
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/share/qgis/python/qgis/PyQt/uic/__init__.py", line 36, in __loadUiType
    return __PyQtLoadUiType(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/lib/python3.11/site-packages/PyQt5/uic/__init__.py", line 207, in loadUiType
    exec(code_string.getvalue(), ui_globals)
  File "", line 10
    self.button_box.setOrientation(QtCore.Qt.Qt::Orientation::Horizontal)
                                               ^
SyntaxError: invalid syntax

Reverting the changes in the file shows that all the enum values were changed from Qt::Horizontal to Qt::Orientation::Horizontal and QDialogButtonBox::Cancel to QDialogButtonBox::StandardButton::Cancel. Was there an update to QT Creator that made the two incompatible? They're both installed through flatpak, QGIS is 3.38.3 and QT Creator is 14.0.2.


Solution

  • Thanks to some discussion with musicamante I have a better idea what's going on:

    The changed happened a few versions ago for Qt Designer (and therefore the parts of Creator using its elements), which introduced full namespaces for all enums, in order to make it full compliant with the same aspect in Python (IIRC). The latest PyQt versions should be able to cope with that, so the problem may be that QGIS doesn't have a properly updated pyuic.

    Printing QT_VERSION_STR inside qgis's python console (Plugins > Python Console) shows 5.15.10, so at this point it's a few years old:

    from qgis.PyQt.QtCore import QT_VERSION_STR
    print(QT_VERSION_STR)
    5.15.10
    

    The easiest solution without downgrading versions (flatpak makes that a little difficult) was to use VSCode's find text feature with (Q\w+?)::\w+?::(\w+) and replace it with $1::$2. My ui files are small so it's easy to verify that the replacement was correct.