4343import shutil
4444import importlib
4545
46- __version__ = "1.1.0.b2"
46+
47+ __version__ = "1.1.0.b3"
4748
4849# Enable support for `from Qt import *`
4950__all__ = []
611612
612613"""
613614_misplaced_members = {
614- "pyside2 " : {
615+ "PySide2 " : {
615616 "QtGui.QStringListModel" : "QtCore.QStringListModel" ,
616617 "QtCore.Property" : "QtCore.Property" ,
617618 "QtCore.Signal" : "QtCore.Signal" ,
621622 "QtCore.QItemSelection" : "QtCore.QItemSelection" ,
622623 "QtCore.QItemSelectionModel" : "QtCore.QItemSelectionModel" ,
623624 },
624- "pyqt5 " : {
625+ "PyQt5 " : {
625626 "QtCore.pyqtProperty" : "QtCore.Property" ,
626627 "QtCore.pyqtSignal" : "QtCore.Signal" ,
627628 "QtCore.pyqtSlot" : "QtCore.Slot" ,
631632 "QtCore.QItemSelection" : "QtCore.QItemSelection" ,
632633 "QtCore.QItemSelectionModel" : "QtCore.QItemSelectionModel" ,
633634 },
634- "pyside " : {
635+ "PySide " : {
635636 "QtGui.QAbstractProxyModel" : "QtCore.QAbstractProxyModel" ,
636637 "QtGui.QSortFilterProxyModel" : "QtCore.QSortFilterProxyModel" ,
637638 "QtGui.QStringListModel" : "QtCore.QStringListModel" ,
642643 "QtCore.Slot" : "QtCore.Slot" ,
643644
644645 },
645- "pyqt4 " : {
646+ "PyQt4 " : {
646647 "QtGui.QAbstractProxyModel" : "QtCore.QAbstractProxyModel" ,
647648 "QtGui.QSortFilterProxyModel" : "QtCore.QSortFilterProxyModel" ,
648649 "QtGui.QItemSelection" : "QtCore.QItemSelection" ,
654655 }
655656}
656657
658+ """ Compatibility Members
659+
660+ This dictionary is used to build Qt.QtCompat objects that provide a consistent
661+ interface for obsolete members, and differences in binding return values.
662+
663+ {
664+ "binding": {
665+ "classname": {
666+ "targetname": "binding_namespace",
667+ }
668+ }
669+ }
670+ """
671+ _compatibility_members = {
672+ "PySide2" : {
673+ "QHeaderView" : {
674+ "sectionsClickable" : "QtWidgets.QHeaderView.sectionsClickable" ,
675+ "setSectionsClickable" :
676+ "QtWidgets.QHeaderView.setSectionsClickable" ,
677+ "sectionResizeMode" : "QtWidgets.QHeaderView.sectionResizeMode" ,
678+ "setSectionResizeMode" :
679+ "QtWidgets.QHeaderView.setSectionResizeMode" ,
680+ "sectionsMovable" : "QtWidgets.QHeaderView.sectionsMovable" ,
681+ "setSectionsMovable" : "QtWidgets.QHeaderView.setSectionsMovable" ,
682+ },
683+ "QFileDialog" : {
684+ "getOpenFileName" : "QtWidgets.QFileDialog.getOpenFileName" ,
685+ "getOpenFileNames" : "QtWidgets.QFileDialog.getOpenFileNames" ,
686+ "getSaveFileName" : "QtWidgets.QFileDialog.getSaveFileName" ,
687+ },
688+ },
689+ "PyQt5" : {
690+ "QHeaderView" : {
691+ "sectionsClickable" : "QtWidgets.QHeaderView.sectionsClickable" ,
692+ "setSectionsClickable" :
693+ "QtWidgets.QHeaderView.setSectionsClickable" ,
694+ "sectionResizeMode" : "QtWidgets.QHeaderView.sectionResizeMode" ,
695+ "setSectionResizeMode" :
696+ "QtWidgets.QHeaderView.setSectionResizeMode" ,
697+ "sectionsMovable" : "QtWidgets.QHeaderView.sectionsMovable" ,
698+ "setSectionsMovable" : "QtWidgets.QHeaderView.setSectionsMovable" ,
699+ },
700+ "QFileDialog" : {
701+ "getOpenFileName" : "QtWidgets.QFileDialog.getOpenFileName" ,
702+ "getOpenFileNames" : "QtWidgets.QFileDialog.getOpenFileNames" ,
703+ "getSaveFileName" : "QtWidgets.QFileDialog.getSaveFileName" ,
704+ },
705+ },
706+ "PySide" : {
707+ "QHeaderView" : {
708+ "sectionsClickable" : "QtWidgets.QHeaderView.isClickable" ,
709+ "setSectionsClickable" : "QtWidgets.QHeaderView.setClickable" ,
710+ "sectionResizeMode" : "QtWidgets.QHeaderView.resizeMode" ,
711+ "setSectionResizeMode" : "QtWidgets.QHeaderView.setResizeMode" ,
712+ "sectionsMovable" : "QtWidgets.QHeaderView.isMovable" ,
713+ "setSectionsMovable" : "QtWidgets.QHeaderView.setMovable" ,
714+ },
715+ "QFileDialog" : {
716+ "getOpenFileName" : "QtWidgets.QFileDialog.getOpenFileName" ,
717+ "getOpenFileNames" : "QtWidgets.QFileDialog.getOpenFileNames" ,
718+ "getSaveFileName" : "QtWidgets.QFileDialog.getSaveFileName" ,
719+ },
720+ },
721+ "PyQt4" : {
722+ "QHeaderView" : {
723+ "sectionsClickable" : "QtWidgets.QHeaderView.isClickable" ,
724+ "setSectionsClickable" : "QtWidgets.QHeaderView.setClickable" ,
725+ "sectionResizeMode" : "QtWidgets.QHeaderView.resizeMode" ,
726+ "setSectionResizeMode" : "QtWidgets.QHeaderView.setResizeMode" ,
727+ "sectionsMovable" : "QtWidgets.QHeaderView.isMovable" ,
728+ "setSectionsMovable" : "QtWidgets.QHeaderView.setMovable" ,
729+ },
730+ "QFileDialog" : {
731+ "getOpenFileName" : "QtWidgets.QFileDialog.getOpenFileName" ,
732+ "getOpenFileNames" : "QtWidgets.QFileDialog.getOpenFileNames" ,
733+ "getSaveFileName" : "QtWidgets.QFileDialog.getSaveFileName" ,
734+ },
735+ },
736+ }
737+
657738
658739def _apply_site_config ():
659740 try :
@@ -663,8 +744,16 @@ def _apply_site_config():
663744 # to _common_members are needed.
664745 pass
665746 else :
666- # Update _common_members with any changes made by QtSiteConfig
667- QtSiteConfig .update_members (_common_members )
747+ # Provide the ability to modify the dicts used to build Qt.py
748+ if hasattr (QtSiteConfig , 'update_members' ):
749+ QtSiteConfig .update_members (_common_members )
750+
751+ if hasattr (QtSiteConfig , 'update_misplaced_members' ):
752+ QtSiteConfig .update_misplaced_members (members = _misplaced_members )
753+
754+ if hasattr (QtSiteConfig , 'update_compatibility_members' ):
755+ QtSiteConfig .update_compatibility_members (
756+ members = _compatibility_members )
668757
669758
670759def _new_module (name ):
@@ -737,10 +826,10 @@ def _wrapinstance(func, ptr, base=None):
737826
738827
739828def _reassign_misplaced_members (binding ):
740- """Parse `_misplaced_members` dict and remap
741- values based on the underlying binding.
829+ """Apply misplaced members from `binding` to Qt.py
742830
743- :param str binding: Top level binding in _misplaced_members.
831+ Arguments:
832+ binding (dict): Misplaced members
744833
745834 """
746835
@@ -766,6 +855,67 @@ def _reassign_misplaced_members(binding):
766855 )
767856
768857
858+ def _build_compatibility_members (binding , decorators = None ):
859+ """Apply `binding` to QtCompat
860+
861+ Arguments:
862+ binding (str): Top level binding in _compatibility_members.
863+ decorators (dict, optional): Provides the ability to decorate the
864+ original Qt methods when needed by a binding. This can be used
865+ to change the returned value to a standard value. The key should
866+ be the classname, the value is a dict where the keys are the
867+ target method names, and the values are the decorator functions.
868+
869+ """
870+
871+ decorators = decorators or dict ()
872+
873+ # Allow optional site-level customization of the compatibility members.
874+ # This method does not need to be implemented in QtSiteConfig.
875+ try :
876+ import QtSiteConfig
877+ except ImportError :
878+ pass
879+ else :
880+ if hasattr (QtSiteConfig , 'update_compatibility_decorators' ):
881+ QtSiteConfig .update_compatibility_decorators (binding , decorators )
882+
883+ _QtCompat = type ("QtCompat" , (object ,), {})
884+
885+ for classname , bindings in _compatibility_members [binding ].items ():
886+ attrs = {}
887+ for target , binding in bindings .items ():
888+ namespaces = binding .split ('.' )
889+ try :
890+ src_object = getattr (Qt , "_" + namespaces [0 ])
891+ except AttributeError as e :
892+ _log ("QtCompat: AttributeError: %s" % e )
893+ # Skip reassignment of non-existing members.
894+ # This can happen if a request was made to
895+ # rename a member that didn't exist, for example
896+ # if QtWidgets isn't available on the target platform.
897+ continue
898+
899+ # Walk down any remaining namespace getting the object assuming
900+ # that if the first namespace exists the rest will exist.
901+ for namespace in namespaces [1 :]:
902+ src_object = getattr (src_object , namespace )
903+
904+ # decorate the Qt method if a decorator was provided.
905+ if target in decorators .get (classname , []):
906+ # staticmethod must be called on the decorated method to
907+ # prevent a TypeError being raised when the decorated method
908+ # is called.
909+ src_object = staticmethod (
910+ decorators [classname ][target ](src_object ))
911+
912+ attrs [target ] = src_object
913+
914+ # Create the QtCompat class and install it into the namespace
915+ compat_class = type (classname , (_QtCompat ,), attrs )
916+ setattr (Qt .QtCompat , classname , compat_class )
917+
918+
769919def _pyside2 ():
770920 """Initialise PySide2
771921
@@ -804,7 +954,8 @@ def _pyside2():
804954 Qt .QtCompat .setSectionResizeMode = \
805955 Qt ._QtWidgets .QHeaderView .setSectionResizeMode
806956
807- _reassign_misplaced_members ("pyside2" )
957+ _reassign_misplaced_members ("PySide2" )
958+ _build_compatibility_members ("PySide2" )
808959
809960
810961def _pyside ():
@@ -850,7 +1001,8 @@ def _pyside():
8501001 )
8511002 )
8521003
853- _reassign_misplaced_members ("pyside" )
1004+ _reassign_misplaced_members ("PySide" )
1005+ _build_compatibility_members ("PySide" )
8541006
8551007
8561008def _pyqt5 ():
@@ -883,7 +1035,8 @@ def _pyqt5():
8831035 Qt .QtCompat .setSectionResizeMode = \
8841036 Qt ._QtWidgets .QHeaderView .setSectionResizeMode
8851037
886- _reassign_misplaced_members ("pyqt5" )
1038+ _reassign_misplaced_members ("PyQt5" )
1039+ _build_compatibility_members ('PyQt5' )
8871040
8881041
8891042def _pyqt4 ():
@@ -963,7 +1116,32 @@ def _pyqt4():
9631116 n )
9641117 )
9651118
966- _reassign_misplaced_members ("pyqt4" )
1119+ _reassign_misplaced_members ("PyQt4" )
1120+
1121+ # QFileDialog QtCompat decorator
1122+ def _standardizeQFileDialog (some_function ):
1123+ """Decorator that makes PyQt4 return conform to other bindings"""
1124+ def wrapper (* args , ** kwargs ):
1125+ ret = (some_function (* args , ** kwargs ))
1126+
1127+ # PyQt4 only returns the selected filename, force it to a
1128+ # standard return of the selected filename, and a empty string
1129+ # for the selected filter
1130+ return ret , ''
1131+
1132+ wrapper .__doc__ = some_function .__doc__
1133+ wrapper .__name__ = some_function .__name__
1134+
1135+ return wrapper
1136+
1137+ decorators = {
1138+ "QFileDialog" : {
1139+ "getOpenFileName" : _standardizeQFileDialog ,
1140+ "getOpenFileNames" : _standardizeQFileDialog ,
1141+ "getSaveFileName" : _standardizeQFileDialog ,
1142+ }
1143+ }
1144+ _build_compatibility_members ('PyQt4' , decorators )
9671145
9681146
9691147def _none ():
0 commit comments