2222uic = None
2323QT_API : Optional [str ] = None
2424QT_VERSION_STR : Optional [str ] = None
25+ PYQT_VERSION_STR : Optional [str ] = None
2526BINDING_VERSION_STR : Optional [str ] = None
2627_MODULES = []
2728_FAILED_IMPORT : Optional [Exception ] = None
@@ -1165,6 +1166,7 @@ def _import_binding(name: str) -> Tuple:
11651166 uicMod ,
11661167 QtCoreMod .QT_VERSION_STR ,
11671168 QtCoreMod .PYQT_VERSION_STR ,
1169+ QtCoreMod .PYQT_VERSION_STR ,
11681170 )
11691171
11701172 if name == "pyside6" :
@@ -1217,6 +1219,7 @@ def _import_binding(name: str) -> Tuple:
12171219 QtUiToolsMod ,
12181220 QtCoreMod .__version__ , # PySide binds Qt version here
12191221 QtCoreMod .__version__ ,
1222+ QtCoreMod .__version__ ,
12201223 )
12211224
12221225 if name == "pyqt5" :
@@ -1267,6 +1270,7 @@ def _import_binding(name: str) -> Tuple:
12671270 uicMod ,
12681271 QtCoreMod .QT_VERSION_STR ,
12691272 QtCoreMod .PYQT_VERSION_STR ,
1273+ QtCoreMod .PYQT_VERSION_STR ,
12701274 )
12711275
12721276 if name == "pyside2" :
@@ -1323,6 +1327,7 @@ def _import_binding(name: str) -> Tuple:
13231327 QtUiToolsMod ,
13241328 QtCoreMod .__version__ ,
13251329 QtCoreMod .__version__ ,
1330+ QtCoreMod .__version__ ,
13261331 )
13271332
13281333 raise ImportError (f"Unknown binding '{ name } '" )
@@ -1331,7 +1336,7 @@ def _import_binding(name: str) -> Tuple:
13311336def _select_binding () -> str :
13321337 """Select and load the first available binding."""
13331338 global QtCore , QtGui , QtWidgets , QtSvg , QtWebEngineCore , QtWebEngineWidgets , QtWebChannel , QtWebKitWidgets
1334- global Signal , Slot , Property , QRegularExpression , QState , QStateMachine , uic , QT_API , QT_VERSION_STR , BINDING_VERSION_STR , _MODULES
1339+ global Signal , Slot , Property , QRegularExpression , QState , QStateMachine , uic , QT_API , QT_VERSION_STR , PYQT_VERSION_STR , BINDING_VERSION_STR , _MODULES
13351340 global _FAILED_IMPORT , _SELECTING
13361341
13371342 if _FAILED_IMPORT :
@@ -1366,6 +1371,7 @@ def _select_binding() -> str:
13661371 QStateMachine ,
13671372 uic ,
13681373 QT_VERSION_STR ,
1374+ PYQT_VERSION_STR ,
13691375 BINDING_VERSION_STR ,
13701376 ) = _import_binding (candidate )
13711377 logger .info (
@@ -1420,12 +1426,106 @@ def load_ui(path: str, baseinstance=None):
14201426 from importlib import import_module
14211427
14221428 QtUiTools = import_module ("PySide6.QtUiTools" if QT_API == "pyside6" else "PySide2.QtUiTools" ) # type: ignore
1423- loader = QtUiTools .QUiLoader ()
1429+ if baseinstance is not None :
1430+ class UiLoader (QtUiTools .QUiLoader ):
1431+ def __init__ (self , base ):
1432+ super ().__init__ (base )
1433+ self .base = base
1434+
1435+ def createWidget (self , class_name , parent = None , name = "" ):
1436+ if parent is None and self .base is not None :
1437+ return self .base
1438+ widget = super ().createWidget (class_name , parent , name )
1439+ if self .base is not None and name :
1440+ setattr (self .base , name , widget )
1441+ return widget
1442+
1443+ def createAction (self , parent = None , name = "" ):
1444+ if parent is None and self .base is not None :
1445+ parent = self .base
1446+ action = super ().createAction (parent , name )
1447+ if self .base is not None and name :
1448+ setattr (self .base , name , action )
1449+ return action
1450+
1451+ loader = UiLoader (baseinstance )
1452+ setattr (baseinstance , "_qt_ui_loader" , loader )
1453+ else :
1454+ loader = QtUiTools .QUiLoader ()
14241455 ui_file = QtCore .QFile (path )
14251456 if not ui_file .open (QtCore .QFile .ReadOnly ):
14261457 raise IOError (f"Cannot open UI file: { path } " )
14271458 try :
1428- return loader .load (ui_file , baseinstance )
1459+ widget = loader .load (ui_file )
1460+ if baseinstance is not None :
1461+ if widget is not None and widget is not baseinstance :
1462+ setattr (baseinstance , "_qt_loaded_ui" , widget )
1463+ main_window_type = getattr (QtWidgets , "QMainWindow" , None )
1464+ if main_window_type and isinstance (baseinstance , main_window_type ) and isinstance (widget , main_window_type ):
1465+ central = widget .centralWidget ()
1466+ if central is not None :
1467+ baseinstance .setCentralWidget (central )
1468+ menubar = widget .menuBar ()
1469+ if menubar is not None :
1470+ baseinstance .setMenuBar (menubar )
1471+ statusbar = widget .statusBar ()
1472+ if statusbar is not None :
1473+ baseinstance .setStatusBar (statusbar )
1474+ tool_bar_type = getattr (QtWidgets , "QToolBar" , None )
1475+ if tool_bar_type :
1476+ for toolbar in widget .findChildren (tool_bar_type ):
1477+ baseinstance .addToolBar (toolbar )
1478+ dock_type = getattr (QtWidgets , "QDockWidget" , None )
1479+ if dock_type :
1480+ for dock in widget .findChildren (dock_type ):
1481+ try :
1482+ area = widget .dockWidgetArea (dock )
1483+ except Exception :
1484+ area = None
1485+ if area is None or area == QtCore .Qt .NoDockWidgetArea :
1486+ baseinstance .addDockWidget (QtCore .Qt .LeftDockWidgetArea , dock )
1487+ else :
1488+ baseinstance .addDockWidget (area , dock )
1489+ if widget is not None :
1490+ main_window_type = getattr (QtWidgets , "QMainWindow" , None )
1491+ if main_window_type and isinstance (baseinstance , main_window_type ):
1492+ root = baseinstance
1493+ else :
1494+ root = widget
1495+ else :
1496+ root = baseinstance
1497+ qaction_type = getattr (QtGui , "QAction" , None )
1498+ actions = []
1499+ seen = set ()
1500+ if qaction_type is not None :
1501+ for holder in (root , baseinstance , loader ):
1502+ if holder is None :
1503+ continue
1504+ for act in holder .findChildren (qaction_type ):
1505+ ident = id (act )
1506+ if ident in seen :
1507+ continue
1508+ seen .add (ident )
1509+ actions .append (act )
1510+ for act in actions :
1511+ try :
1512+ act .setParent (baseinstance )
1513+ except Exception :
1514+ pass
1515+ for obj in root .findChildren (QtCore .QObject ):
1516+ obj_name = obj .objectName ()
1517+ if obj_name and not hasattr (baseinstance , obj_name ):
1518+ setattr (baseinstance , obj_name , obj )
1519+ if widget is not None and widget is not baseinstance :
1520+ widget_type = getattr (QtWidgets , "QWidget" , None )
1521+ if widget_type and isinstance (baseinstance , widget_type ) and isinstance (widget , widget_type ):
1522+ try :
1523+ if baseinstance .layout () is None and widget .layout () is not None :
1524+ baseinstance .setLayout (widget .layout ())
1525+ except Exception :
1526+ pass
1527+ return baseinstance
1528+ return widget
14291529 finally :
14301530 ui_file .close ()
14311531
@@ -1500,6 +1600,7 @@ def __getattr__(name):
15001600 "QLibraryInfo" ,
15011601 "QT_API" ,
15021602 "QT_VERSION_STR" ,
1603+ "PYQT_VERSION_STR" ,
15031604 "BINDING_VERSION_STR" ,
15041605 "ensure_binding" ,
15051606 "load_ui" ,
0 commit comments