Uploaded image for project: 'Qt for Python'
  1. Qt for Python
  2. PYSIDE-1214

Type issues when returning C++ classes which subclass Qt types

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P3: Somewhat important
    • None
    • 5.14.0, 5.12.6
    • PySide, Shiboken
    • None
    • RHEL7
    • Linux/X11
    • 683598e0b008078cb6cc00f2b22a75b6404ccc96 (pyside/pyside-setup/5.14)

    Description

      I don't know if this would strictly be classified as a bug, but it certainly impairs the use of PySide compared to other Python wrappings for Qt (i.e. PyQt).  The issue below demonstrates a problem described in the comments of PYSIDE-1135 (derived classes from QApplication), but it seems to be general behavior within PySide.

      Specifically, when embedding Python in a C++ application, if that application provides subclasses from Qt classes (say MyMenu : QMenu and MyApplication : QApplication) which are not exposed to Python, using PySide functions to access them doesn't return the closest wrapped base class.

      Attached are 3 modified files from the scriptableapplication example, demonstrating the issue described above.  Building scriptableapplication with these files and running the following Python script should hopefully demonstrate what I'm describing:

      from PySide2 import QtWidgets
      
      # ISSUE1: Derived class from QApplication does not fallback to QApplication
      app = QtWidgets.QApplication.instance()
      print "%s is a (%s)" % (str(app), app.metaObject().className())
      
      app.__class__ = QtWidgets.QApplication
      
      # ISSUE2: Derived class from QMenu does not fallback to QMenu
      widgets = app.topLevelWidgets()
      for w in widgets:
          print "%s is a (%s)" % (str(w), w.metaObject().className())
      

      I've seen some comments in the past few days on PYSIDE-1135 about the specific derived QApplication case, but the general failure to fallback seems like a limitation in the embedded case.  The output of the above looks like this (when tested in 5.14.1):

      <PySide2.QtCore.QCoreApplication(0x7fffa756fe30) at 0x21cd830> is a (MyApplication)
      <PySide2.QtWidgets.QWidget(0xa22df0) at 0x282f710> is a (MyMenu)
      <PySide2.QtWidgets.QMenu(0xa3e480) at 0x282f758> is a (QMenu)
      <PySide2.QtWidgets.QMenu(0x82e320) at 0x282f7a0> is a (QMenu)
      <AppLib.MainWindow(0x7fffa756fe40) at 0x282f128> is a (MainWindow)
      <PySide2.QtWidgets.QMenu(0xa34270) at 0x282f7e8> is a (QMenu)
      

      The QMenu instances defined in C++ are properly mapped to Python as PySide2.QtWidgets.QMenu, while the MyMenu instance is mapped to Python as PySide2.QtWidgets.QWidget (rather than the direct QMenu base class).  Having this fallback would be very convenient, as it allows Python code to work with these derived classes as QMenus, even when exposing the C++ derived class to Python is unnecessary.  Coming from an application which has used PyQt historically (which has this behavior), it feels like missing functionality within PySide.

      And just to be explicit, I see this behavior with any kind of classes derived from Qt widgets, I'm just using MyMenu as a representative example.

      Attachments

        1. main.cpp
          3 kB
        2. mainwindow.cpp
          6 kB
        3. mainwindow.h
          3 kB
        4. pyside1214_diag.diff
          3 kB
        5. pyside1214_log.txt
          2 kB
        6. pyside1214_repro_5.diff
          4 kB
        7. pyside1214_repro.diff
          3 kB

        Issue Links

          For Gerrit Dashboard: PYSIDE-1214
          # Subject Branch Project Status CR V

          Activity

            People

              kleint Friedemann Kleint
              aferrall@ilm.com Adam Ferrall-Nunge
              Votes:
              1 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes