123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- """ Defines miscellaneous Qt-related helper classes and functions.
- """
- import inspect
- from qtpy import QtCore, QtGui
- from ipython_genutils.py3compat import iteritems
- from traitlets import HasTraits, TraitType
- #-----------------------------------------------------------------------------
- # Metaclasses
- #-----------------------------------------------------------------------------
- MetaHasTraits = type(HasTraits)
- MetaQObject = type(QtCore.QObject)
- class MetaQObjectHasTraits(MetaQObject, MetaHasTraits):
- """ A metaclass that inherits from the metaclasses of HasTraits and QObject.
- Using this metaclass allows a class to inherit from both HasTraits and
- QObject. Using SuperQObject instead of QObject is highly recommended. See
- QtKernelManager for an example.
- """
- def __new__(mcls, name, bases, classdict):
- # FIXME: this duplicates the code from MetaHasTraits.
- # I don't think a super() call will help me here.
- for k,v in iteritems(classdict):
- if isinstance(v, TraitType):
- v.name = k
- elif inspect.isclass(v):
- if issubclass(v, TraitType):
- vinst = v()
- vinst.name = k
- classdict[k] = vinst
- cls = MetaQObject.__new__(mcls, name, bases, classdict)
- return cls
- def __init__(mcls, name, bases, classdict):
- # Note: super() did not work, so we explicitly call these.
- MetaQObject.__init__(mcls, name, bases, classdict)
- MetaHasTraits.__init__(mcls, name, bases, classdict)
- #-----------------------------------------------------------------------------
- # Classes
- #-----------------------------------------------------------------------------
- def superQ(QClass):
- """ Permits the use of super() in class hierarchies that contain Qt classes.
- Unlike QObject, SuperQObject does not accept a QObject parent. If it did,
- super could not be emulated properly (all other classes in the heierarchy
- would have to accept the parent argument--they don't, of course, because
- they don't inherit QObject.)
- This class is primarily useful for attaching signals to existing non-Qt
- classes. See QtKernelManagerMixin for an example.
- """
- class SuperQClass(QClass):
- def __new__(cls, *args, **kw):
- # We initialize QClass as early as possible. Without this, Qt complains
- # if SuperQClass is not the first class in the super class list.
- inst = QClass.__new__(cls)
- QClass.__init__(inst)
- return inst
- def __init__(self, *args, **kw):
- # Emulate super by calling the next method in the MRO, if there is one.
- mro = self.__class__.mro()
- for qt_class in QClass.mro():
- mro.remove(qt_class)
- next_index = mro.index(SuperQClass) + 1
- if next_index < len(mro):
- mro[next_index].__init__(self, *args, **kw)
- return SuperQClass
- SuperQObject = superQ(QtCore.QObject)
- #-----------------------------------------------------------------------------
- # Functions
- #-----------------------------------------------------------------------------
- def get_font(family, fallback=None):
- """Return a font of the requested family, using fallback as alternative.
- If a fallback is provided, it is used in case the requested family isn't
- found. If no fallback is given, no alternative is chosen and Qt's internal
- algorithms may automatically choose a fallback font.
- Parameters
- ----------
- family : str
- A font name.
- fallback : str
- A font name.
- Returns
- -------
- font : QFont object
- """
- font = QtGui.QFont(family)
- # Check whether we got what we wanted using QFontInfo, since exactMatch()
- # is overly strict and returns false in too many cases.
- font_info = QtGui.QFontInfo(font)
- if fallback is not None and font_info.family() != family:
- font = QtGui.QFont(fallback)
- return font
|