Repository: silx-kit/silx
Issue: Issue with 3D scene items inheritance

I have the following issue with current master with `example/plot3dSceneWindow.py`:
```
File "examples/plot3dSceneWindow.py", line 136, in <module>
    clipPlane = items.ClipPlane()  # Create a new clipping plane item
  File "silx/gui/plot3d/items/clipplane.py", line 52, in __init__
    Item3D.__init__(self, parent=parent, primitive=plane)
  File "silx/gui/plot3d/items/core.py", line 92, in __init__
    qt.QObject.__init__(self, parent)
TypeError: __init__() missing 1 required positional argument: 'plane'
```
The issue is with `PyQt5` (tested with 5.12.1 and 5.14.2) but with `PySide2` it works fine.

This looks to be due to https://github.com/silx-kit/silx/commit/d9a11d543c5885346562e161ed46a19c19ff23bf
`ClipPlane` is the only item with this issue, so it seems to be related to the fact that the mix-in takes an argument (as `PlaneMixIn` does).

Changed files:
silx/gui/qt/_qt.py, silx/gui/plot/items/roi.py

diff --git a/silx/gui/plot/items/roi.py b/silx/gui/plot/items/roi.py
index 9650f0e51..e8df7321f 100644
--- a/silx/gui/plot/items/roi.py
+++ b/silx/gui/plot/items/roi.py
@@ -766,9 +766,9 @@ class PointROI(RegionOfInterest, items.SymbolMixIn):
         elif event == items.ItemChangedType.EDITABLE:
             editable = self.isEditable()
             if editable:
-                self._marker.sigItemChanged.connect(self.__positionChanged)
+                self._marker.sigItemChanged.connect(self._pointPositionChanged)
             else:
-                self._marker.sigItemChanged.disconnect(self.__positionChanged)
+                self._marker.sigItemChanged.disconnect(self._pointPositionChanged)
             self._marker._setDraggable(editable)
         elif event in [items.ItemChangedType.VISIBLE,
                        items.ItemChangedType.SELECTABLE]:
@@ -794,7 +794,7 @@ class PointROI(RegionOfInterest, items.SymbolMixIn):
             self._marker.setPosition(pos[0], pos[1])
         self.sigRegionChanged.emit()
 
-    def __positionChanged(self, event):
+    def _pointPositionChanged(self, event):
         """Handle position changed events of the marker"""
         if self.__filterReentrant.locked():
             return
@@ -941,9 +941,9 @@ class HorizontalLineROI(RegionOfInterest, items.LineMixIn):
         elif event == items.ItemChangedType.EDITABLE:
             editable = self.isEditable()
             if editable:
-                self._marker.sigItemChanged.connect(self.__positionChanged)
+                self._marker.sigItemChanged.connect(self._linePositionChanged)
             else:
-                self._marker.sigItemChanged.disconnect(self.__positionChanged)
+                self._marker.sigItemChanged.disconnect(self._linePositionChanged)
             self._marker._setDraggable(editable)
         elif event in [items.ItemChangedType.VISIBLE,
                        items.ItemChangedType.SELECTABLE]:
@@ -978,7 +978,7 @@ class HorizontalLineROI(RegionOfInterest, items.LineMixIn):
             self._marker.setPosition(0, pos)
         self.sigRegionChanged.emit()
 
-    def __positionChanged(self, event):
+    def _linePositionChanged(self, event):
         """Handle position changed events of the marker"""
         if self.__filterReentrant.locked():
             return
@@ -1020,9 +1020,9 @@ class VerticalLineROI(RegionOfInterest, items.LineMixIn):
         elif event == items.ItemChangedType.EDITABLE:
             editable = self.isEditable()
             if editable:
-                self._marker.sigItemChanged.connect(self.__positionChanged)
+                self._marker.sigItemChanged.connect(self._linePositionChanged)
             else:
-                self._marker.sigItemChanged.disconnect(self.__positionChanged)
+                self._marker.sigItemChanged.disconnect(self._linePositionChanged)
             self._marker._setDraggable(editable)
         elif event in [items.ItemChangedType.VISIBLE,
                        items.ItemChangedType.SELECTABLE]:
@@ -1057,7 +1057,7 @@ class VerticalLineROI(RegionOfInterest, items.LineMixIn):
             self._marker.setPosition(pos, 0)
         self.sigRegionChanged.emit()
 
-    def __positionChanged(self, event):
+    def _linePositionChanged(self, event):
         """Handle position changed events of the marker"""
         if self.__filterReentrant.locked():
             return
@@ -2526,14 +2526,14 @@ class HorizontalRangeROI(RegionOfInterest, items.LineMixIn):
         self._markerMax._setDraggable(editable)
         self._markerCen._setDraggable(editable)
         if self.isEditable():
-            self._markerMin.sigItemChanged.connect(self.__positionMinChanged)
-            self._markerMax.sigItemChanged.connect(self.__positionMaxChanged)
-            self._markerCen.sigItemChanged.connect(self.__positionCenChanged)
+            self._markerMin.sigItemChanged.connect(self._minPositionChanged)
+            self._markerMax.sigItemChanged.connect(self._maxPositionChanged)
+            self._markerCen.sigItemChanged.connect(self._cenPositionChanged)
             self._markerCen.setLineStyle(":")
         else:
-            self._markerMin.sigItemChanged.disconnect(self.__positionMinChanged)
-            self._markerMax.sigItemChanged.disconnect(self.__positionMaxChanged)
-            self._markerCen.sigItemChanged.disconnect(self.__positionCenChanged)
+            self._markerMin.sigItemChanged.disconnect(self._minPositionChanged)
+            self._markerMax.sigItemChanged.disconnect(self._maxPositionChanged)
+            self._markerCen.sigItemChanged.disconnect(self._cenPositionChanged)
             self._markerCen.setLineStyle(" ")
 
     def _updatePos(self, vmin, vmax):
@@ -2636,7 +2636,7 @@ class HorizontalRangeROI(RegionOfInterest, items.LineMixIn):
             return x, y
         return max(x, vmin), y
 
-    def __positionMinChanged(self, event):
+    def _minPositionChanged(self, event):
         """Handle position changed events of the marker"""
         if self.__filterReentrant.locked():
             return
@@ -2644,7 +2644,7 @@ class HorizontalRangeROI(RegionOfInterest, items.LineMixIn):
             marker = self.sender()
             self.setMin(marker.getXPosition())
 
-    def __positionMaxChanged(self, event):
+    def _maxPositionChanged(self, event):
         """Handle position changed events of the marker"""
         if self.__filterReentrant.locked():
             return
@@ -2652,7 +2652,7 @@ class HorizontalRangeROI(RegionOfInterest, items.LineMixIn):
             marker = self.sender()
             self.setMax(marker.getXPosition())
 
-    def __positionCenChanged(self, event):
+    def _cenPositionChanged(self, event):
         """Handle position changed events of the marker"""
         if self.__filterReentrant.locked():
             return
diff --git a/silx/gui/qt/_qt.py b/silx/gui/qt/_qt.py
index 961534228..29a63548f 100644
--- a/silx/gui/qt/_qt.py
+++ b/silx/gui/qt/_qt.py
@@ -1,7 +1,7 @@
 # coding: utf-8
 # /*##########################################################################
 #
-# Copyright (c) 2004-2019 European Synchrotron Radiation Facility
+# Copyright (c) 2004-2020 European Synchrotron Radiation Facility
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # of this software and associated documentation files (the "Software"), to deal
@@ -224,6 +224,12 @@ elif BINDING == 'PyQt5':
 
     Slot = pyqtSlot
 
+    # Disable PyQt5's cooperative multi-inheritance since other bindings do not provide it.
+    # See https://www.riverbankcomputing.com/static/Docs/PyQt5/multiinheritance.html?highlight=inheritance
+    class _Foo(object): pass
+    class QObject(QObject, _Foo): pass
+
+
 elif BINDING == 'PySide2':
     _logger.debug('Using PySide2 bindings')