schrodinger.ui.qt.table_speed_up module¶
A module for speeding up painting in Qt table and tree views. To use this module:
Add
SpeedUpDelegateViewMixin
to your table or tree view class. If your view uses multiple delegates, useMultipleSpeedUpDelegatesViewMixin
instead.Add
MutlipleRolesRoleModelMixin
to yourtable_helper.RowBasedTableModel
model class.If you have any proxies that don’t modify data (i.e. proxies for sorting or filtering), add
MultipleRolesRoleProxyPassthroughMixin
to them. If you have any proxies that modify data, add`MultipleRolesRoleProxyMixin` to them.If defining custom roles, define roles using an enum that inherits from
MultipleRolesUserRolesEnum
.If using custom delegates, make sure that they inherit from
SpeedUpDelegate
.Additionally, subclass the view’s model (i.e. the top-most proxy) with
FlagCacheProxyMixin
to cache flags() return values.
If adding any code to this file, make sure that it doesn’t cause a slow down for any other panels that make use of this module.
- class schrodinger.ui.qt.table_speed_up.SpeedUpDelegate(parent, data_cache)¶
Bases:
PyQt6.QtWidgets.QStyledItemDelegate
A delegate that speeds up painting by:
Requesting all data at once using the MultipleRoles role instead of calling index.data() once per role.
Caching all data for the most recent indices
This delegate may be instantiated directly or subclassed if custom painting is required. If subclassing, note that data should be accessed via option.data rather than index.data().
- Variables
PAINT_ROLES (frozenset) – A set of all roles used in painting. Subclasses should override this variable if they require data for additional roles.
- PAINT_ROLES = frozenset({ItemDataRole.DisplayRole, ItemDataRole.DecorationRole, ItemDataRole.FontRole, ItemDataRole.TextAlignmentRole, ItemDataRole.BackgroundRole, ItemDataRole.ForegroundRole, ItemDataRole.CheckStateRole})¶
- __init__(parent, data_cache)¶
- Parameters
parent (
QtWidgets.QTableView
) – The parent widgetdata_cache (
DataCache
) – The object to use for caching model data. Note that this cache is shared amongst all delegates and that the view, not the delegate, is responsible for clearing the cache when the model data changes.
- initStyleOption(option, index)¶
Fetch all data from the index and load it into the style option object. In addition to the standard QStyleOptionViewItem attributes, all fetched data is stored in option.data as a dictionary of {role: value}. This way, data that doesn’t directly affect the style options can still be accessed without needing an additional index.data() call.
Note that the code for setting the attributes of
option
(other thandata
) is closely based on QStyledItemDelegage::initStyleOption.See Qt documentation for argument documentation.
- setModel(model)¶
Specify the model that this delegate will be fetching data from. This method must be called as soon as a model is set on the view. The model is cached because call model.data() is about four times faster than calling index.data().
- Parameters
model (
QtCore.QAbstractItemModel
) – The model
- EditNextItem = 1¶
- EditPreviousItem = 2¶
- class EndEditHint(value)¶
Bases:
enum.Enum
An enumeration.
- NoHint = 0¶
- EditNextItem = 1¶
- EditPreviousItem = 2¶
- SubmitModelCache = 3¶
- RevertModelCache = 4¶
- NoHint = 0¶
- RevertModelCache = 4¶
- SubmitModelCache = 3¶
- blockSignals(self, b: bool) bool ¶
- childEvent(self, a0: QChildEvent)¶
- children(self) List[QObject] ¶
- closeEditor¶
closeEditor(self, editor: QWidget, hint: QAbstractItemDelegate.EndEditHint = QAbstractItemDelegate.NoHint) [signal]
- commitData¶
commitData(self, editor: QWidget) [signal]
- connectNotify(self, signal: QMetaMethod)¶
- createEditor(self, parent: QWidget, option: QStyleOptionViewItem, index: QModelIndex) QWidget ¶
- customEvent(self, a0: QEvent)¶
- deleteLater(self)¶
- destroyEditor(self, editor: QWidget, index: QModelIndex)¶
- destroyed¶
destroyed(self, object: typing.Optional[QObject] = None) [signal]
- disconnect(a0: QMetaObject.Connection) bool ¶
- disconnect(self) None
- disconnectNotify(self, signal: QMetaMethod)¶
- displayText(self, value: Any, locale: QLocale) str ¶
- dumpObjectInfo(self)¶
- dumpObjectTree(self)¶
- dynamicPropertyNames(self) List[QByteArray] ¶
- editorEvent(self, event: QEvent, model: QAbstractItemModel, option: QStyleOptionViewItem, index: QModelIndex) bool ¶
- event(self, a0: QEvent) bool ¶
- eventFilter(self, object: QObject, event: QEvent) bool ¶
- findChild(self, type: type, name: str = '', options: Qt.FindChildOption = Qt.FindChildrenRecursively) QObject ¶
- findChild(self, types: Tuple, name: str = '', options: Qt.FindChildOption = Qt.FindChildrenRecursively) QObject
- findChildren(self, type: type, name: str = '', options: Qt.FindChildOption = Qt.FindChildrenRecursively) List[QObject] ¶
- findChildren(self, types: Tuple, name: str = '', options: Qt.FindChildOption = Qt.FindChildrenRecursively) List[QObject]
- findChildren(self, type: type, re: QRegularExpression, options: Qt.FindChildOption = Qt.FindChildrenRecursively) List[QObject]
- findChildren(self, types: Tuple, re: QRegularExpression, options: Qt.FindChildOption = Qt.FindChildrenRecursively) List[QObject]
- helpEvent(self, event: QHelpEvent, view: QAbstractItemView, option: QStyleOptionViewItem, index: QModelIndex) bool ¶
- inherits(self, classname: str) bool ¶
- installEventFilter(self, a0: QObject)¶
- isSignalConnected(self, signal: QMetaMethod) bool ¶
- isWidgetType(self) bool ¶
- isWindowType(self) bool ¶
- itemEditorFactory(self) QItemEditorFactory ¶
- killTimer(self, id: int)¶
- metaObject(self) QMetaObject ¶
- moveToThread(self, thread: QThread)¶
- objectName(self) str ¶
- objectNameChanged¶
objectNameChanged(self, objectName: str) [signal]
- paint(self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex)¶
- parent(self) QObject ¶
- property(self, name: str) Any ¶
- pyqtConfigure(...)¶
Each keyword argument is either the name of a Qt property or a Qt signal. For properties the property is set to the given value which should be of an appropriate type. For signals the signal is connected to the given value which should be a callable.
- receivers(self, signal: PYQT_SIGNAL) int ¶
- removeEventFilter(self, a0: QObject)¶
- sender(self) QObject ¶
- senderSignalIndex(self) int ¶
- setEditorData(self, editor: QWidget, index: QModelIndex)¶
- setItemEditorFactory(self, factory: QItemEditorFactory)¶
- setModelData(self, editor: QWidget, model: QAbstractItemModel, index: QModelIndex)¶
- setObjectName(self, name: str)¶
- setParent(self, a0: QObject)¶
- setProperty(self, name: str, value: Any) bool ¶
- signalsBlocked(self) bool ¶
- sizeHint(self, option: QStyleOptionViewItem, index: QModelIndex) QSize ¶
- sizeHintChanged¶
sizeHintChanged(self, a0: QModelIndex) [signal]
- startTimer(self, interval: int, timerType: Qt.TimerType = Qt.CoarseTimer) int ¶
- staticMetaObject = <PyQt6.QtCore.QMetaObject object>¶
- thread(self) QThread ¶
- timerEvent(self, a0: QTimerEvent)¶
- tr(sourceText: str, disambiguation: typing.Optional[str] = None, n: int = - 1) str ¶
- updateEditorGeometry(self, editor: QWidget, option: QStyleOptionViewItem, index: QModelIndex)¶
- class schrodinger.ui.qt.table_speed_up.DataCache(maxlen=10000)¶
Bases:
dict
A dictionary used for caching model data. The cache will hold data for at most
MAXLEN
indices. When additional data is added, the oldest data will be removed from the cache to avoid excessive memory usage.- __init__(maxlen=10000)¶
- clear() None. Remove all items from D. ¶
- __contains__(key, /)¶
True if the dictionary has the specified key, else False.
- __len__()¶
Return len(self).
- copy() a shallow copy of D ¶
- fromkeys(value=None, /)¶
Create a new dictionary with keys from iterable and values set to value.
- get(key, default=None, /)¶
Return the value for key if key is in the dictionary, else default.
- items() a set-like object providing a view on D’s items ¶
- keys() a set-like object providing a view on D’s keys ¶
- pop(k[, d]) v, remove specified key and return the corresponding value. ¶
If key is not found, d is returned if given, otherwise KeyError is raised
- popitem()¶
Remove and return a (key, value) pair as a 2-tuple.
Pairs are returned in LIFO (last-in, first-out) order. Raises KeyError if the dict is empty.
- setdefault(key, default=None, /)¶
Insert key with a value of default if key is not in the dictionary.
Return the value for key if key is in the dictionary, else default.
- update([E, ]**F) None. Update D from dict/iterable E and F. ¶
If E is present and has a .keys() method, then does: for k in E: D[k] = E[k] If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]
- values() an object providing a view on D’s values ¶
- class schrodinger.ui.qt.table_speed_up.MultipleSpeedUpDelegatesViewMixin(*args, **kwargs)¶
Bases:
object
A mixin for
QtWidgets.QAbstractItemView
subclasses that cache data usingSpeedUpDelegate
(or a subclass) and require multiple delegates. Subclasses are required to instantiate all required delegates and must call setModel() on all delegates from view.setModel().If only a single delegate is required, see
SpeedUpDelegateViewMixin
below.- Variables
DATA_CACHE_SIZE (int) – The maximum length of the
DataCache
cache.
- DATA_CACHE_SIZE = 10000¶
- __init__(*args, **kwargs)¶
- setModel(model)¶
Connect signals so that the cache is cleared whenever it contains stale data. This needs to be done before anything else, so we connect these signals before calling the super-class setModel().
See QAbstractItemView documentation for additional method documentation.
- class schrodinger.ui.qt.table_speed_up.SpeedUpDelegateViewMixin(*args, **kwargs)¶
Bases:
schrodinger.ui.qt.table_speed_up.MultipleSpeedUpDelegatesViewMixin
A mixin for
QtWidgets.QAbstractItemView
subclasses that cache data usingSpeedUpDelegate
(or a subclass) and use a single delegate for the entire table. If multiple delegates are required, seeMultipleSpeedUpDelegateViewMixin
above.- Variables
DELEGATE_CLASS (type) – The class of the delegate for the table. Subclasses may override this, but the provided class must be a subclass of
SpeedUpDelegate
.
- DELEGATE_CLASS¶
- __init__(*args, **kwargs)¶
- setModel(model)¶
Connect signals so that the cache is cleared whenever it contains stale data. This needs to be done before anything else, so we connect these signals before calling the super-class setModel().
See QAbstractItemView documentation for additional method documentation.
- DATA_CACHE_SIZE = 10000¶
- class schrodinger.ui.qt.table_speed_up.MultipleRolesRoleModelMixin(*args, **kwargs)¶
Bases:
schrodinger.ui.qt.table_helper.DataMethodDecoratorMixin
A mixin for models that can provide data for multiple roles at once with the
MultipleRolesUserRolesEnum.MultipleRoles
role. This mixin is intended for use withtable_helper.RowBasedTableModel
subclasses, but may be used with anyQAbstractItemModel
subclass that defines_genDataArgs
,- data(index, role=ItemDataRole.DisplayRole, multiple_roles=None)¶
Provide data for the specified index and role. Subclasses normally do not need to redefine this method. Instead, new methods should be created and decorated with
table_helper.data_method
.- Parameters
index (
QtCore.QModelIndex
) – The index to return data for.role (int) – The role to request data for.
multiple_roles (frozenset) – If
role
equals {MultipleRolesUserRolesEnum.MultipleRoles}, a set of roles to retrieve data for. Ignored otherwise.
- Returns
The requested data. If
role
equals {MultipleRolesUserRolesEnum.MultipleRoles}, will be a dictionary of {role: value}. The dictionary not contain roles that are not provided by this model and may contain additional roles that were not explicitly requested.- Return type
object
- __init__(*args, **kwargs)¶
- class schrodinger.ui.qt.table_speed_up.MultipleRolesRoleProxyMixin(*args, **kwargs)¶
Bases:
schrodinger.ui.qt.table_speed_up.MultipleRolesRoleModelMixin
A mixin for proxy models that can provide data for multiple roles at once with the
MultipleRolesUserRolesEnum.MultipleRoles
role. This mixin is only intended for proxies that provide or modify data. For proxies that sort or filter without modifying data, useMultipleRolesRoleProxyPassthroughMixin
instead.- data(proxy_index, role=ItemDataRole.DisplayRole, multiple_roles=None)¶
Provide data for the specified index and role. Subclasses normally do not need to redefine this method. Instead, new methods should be created and decorated with
table_helper.data_method
.- Parameters
index (
QtCore.QModelIndex
) – The index to return data for.role (int) – The role to request data for.
multiple_roles (frozenset) – If
role
equals {MultipleRolesUserRolesEnum.MultipleRoles}, a set of roles to retrieve data for. Ignored otherwise.
- Returns
The requested data. If
role
equals {MultipleRolesUserRolesEnum.MultipleRoles}, will be a dictionary of {role: value}. The dictionary not contain roles that are not provided by this model and may contain additional roles that were not explicitly requested.- Return type
object
- __init__(*args, **kwargs)¶
- class schrodinger.ui.qt.table_speed_up.MultipleRolesRoleProxyPassthroughMixin¶
Bases:
object
A mixin for proxy models that sort or filter a
MultipleRolesRoleModelMixin
model but don’t provide or modify any data. For proxies that modify or provide data, useMultipleRolesRoleProxyMixin
instead.- data(proxy_index, role, multiple_roles=None)¶
- class schrodinger.ui.qt.table_speed_up.AbstractFlagCacheProxyMixinMetaclass¶
Bases:
PyQt6.sip.wrappertype
A metaclass for
FlagCacheProxyMixin
. It ensures, in the following scenario:class MyModel(FlagCacheProxyMixin, QtCore.QAbstractProxyModel): def flags(self, index): if self.longComplicatedThing(index): return Qt.ItemIsSelectable | Qt.ItemIsEditable else: return Qt.NoItemFlags my_model = MyModel()
that
my_model.flags(index)
will callFlagCacheProxyMixin.flags
first, and thatMyModel.flags
is only called if the desired value is not found in the cache. Without this metaclass,MyModel.flags
would instead be called first andmy_model
would never use the flags cache.- mro()¶
Determine the method resolution order for the specified class. If this class inherits from
QtCore.QAbstractItemModel
, then we make sure that the appropriateAbstractFlagCacheProxyMixin
subclass appears first in the MRO list.- Parameters
cls (
AbstractFlagCacheProxyMixin
) – The class to determine the MRO for- Returns
A list of base class in desired MRO order
- Return type
list(object)
- __init__(*args, **kwargs)¶
- class schrodinger.ui.qt.table_speed_up.AbstractFlagCacheProxyMixin(*args, **kwargs)¶
Bases:
object
A mixin for
QAbstractItemProxyModel
subclasses to cache flags() return values. This class does not implement any caching and should not be used directly. SeeFlagCacheProxyMixin
below instead.Note that if this mixin is used on a non-proxy model - or on a proxy model that changes flags() return values independently of changes to the underlying source model - then the subclass is responsible for calling
self._flag_cache.clear()
whenever the flags() return value changes.- __init__(*args, **kwargs)¶
- setSourceModel(model)¶
When this class is mixed in to a proxy model, connect signals so that the cache is cleared whenever it contains stale data. This needs to be done before anything else, so we connect these signals before calling the super-class setSourceModel().
See QAbstractItemProxyModel documentation for additional method documentation.
- class schrodinger.ui.qt.table_speed_up.FlagCacheProxyMixin(*args, **kwargs)¶
Bases:
schrodinger.ui.qt.table_speed_up.AbstractFlagCacheProxyMixin
A mixin for
QAbstractItemProxyModel
subclasses to cache flags() return values per-cell.- flags(index)¶
- __init__(*args, **kwargs)¶
- setSourceModel(model)¶
When this class is mixed in to a proxy model, connect signals so that the cache is cleared whenever it contains stale data. This needs to be done before anything else, so we connect these signals before calling the super-class setSourceModel().
See QAbstractItemProxyModel documentation for additional method documentation.