diff options
Diffstat (limited to 'silx/gui/plot3d/_model/core.py')
-rw-r--r-- | silx/gui/plot3d/_model/core.py | 372 |
1 files changed, 0 insertions, 372 deletions
diff --git a/silx/gui/plot3d/_model/core.py b/silx/gui/plot3d/_model/core.py deleted file mode 100644 index e8e0820..0000000 --- a/silx/gui/plot3d/_model/core.py +++ /dev/null @@ -1,372 +0,0 @@ -# coding: utf-8 -# /*########################################################################## -# -# Copyright (c) 2017-2018 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 -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# -# ###########################################################################*/ -""" -This module provides base classes to implement models for 3D scene content. -""" - -from __future__ import absolute_import, division - -__authors__ = ["T. Vincent"] -__license__ = "MIT" -__date__ = "11/01/2018" - - -import collections -import weakref - -from ....utils.weakref import WeakMethodProxy -from ... import qt - - -class BaseRow(qt.QObject): - """Base class for rows of the tree model. - - The root node parent MUST be set to the QAbstractItemModel it belongs to. - By default item is enabled. - - :param children: Iterable of BaseRow to start with (not signaled) - """ - - def __init__(self, children=()): - self.__modelRef = None - self.__parentRef = None - super(BaseRow, self).__init__() - self.__children = [] - for row in children: - assert isinstance(row, BaseRow) - row.setParent(self) - self.__children.append(row) - self.__flags = collections.defaultdict(lambda: qt.Qt.ItemIsEnabled) - self.__tooltip = None - - def setParent(self, parent): - """Override :meth:`QObject.setParent` to cache model and parent""" - self.__parentRef = None if parent is None else weakref.ref(parent) - - if isinstance(parent, qt.QAbstractItemModel): - model = parent - elif isinstance(parent, BaseRow): - model = parent.model() - else: - model = None - - self._updateModel(model) - - super(BaseRow, self).setParent(parent) - - def parent(self): - """Override :meth:`QObject.setParent` to use cached parent - - :rtype: Union[QObject, None]""" - return self.__parentRef() if self.__parentRef is not None else None - - def _updateModel(self, model): - """Update the model this row belongs to""" - if model != self.model(): - self.__modelRef = weakref.ref(model) if model is not None else None - for child in self.children(): - child._updateModel(model) - - def model(self): - """Return the model this node belongs to or None if not in a model. - - :rtype: Union[QAbstractItemModel, None] - """ - return self.__modelRef() if self.__modelRef is not None else None - - def index(self, column=0): - """Return corresponding index in the model or None if not in a model. - - :param int column: The column to make the index for - :rtype: Union[QModelIndex, None] - """ - parent = self.parent() - model = self.model() - - if model is None: # Not in a model - return None - elif parent is model: # Root node - return qt.QModelIndex() - else: - index = parent.index() - row = parent.children().index(self) - return model.index(row, column, index) - - def columnCount(self): - """Returns number of columns (default: 2) - - :rtype: int - """ - return 2 - - def children(self): - """Returns the list of children nodes - - :rtype: tuple of Node - """ - return tuple(self.__children) - - def rowCount(self): - """Returns number of rows - - :rtype: int - """ - return len(self.__children) - - def addRow(self, row, index=None): - """Add a node to the children - - :param BaseRow row: The node to add - :param int index: The index at which to insert it or - None to append - """ - if index is None: - index = self.rowCount() - assert index <= self.rowCount() - - model = self.model() - - if model is not None: - parent = self.index() - model.beginInsertRows(parent, index, index) - - self.__children.insert(index, row) - row.setParent(self) - - if model is not None: - model.endInsertRows() - - def removeRow(self, row): - """Remove a row from the children list. - - It removes either a node or a row index. - - :param row: BaseRow object or index of row to remove - :type row: Union[BaseRow, int] - """ - if isinstance(row, BaseRow): - row = self.__children.index(row) - else: - row = int(row) - assert row < self.rowCount() - - model = self.model() - - if model is not None: - index = self.index() - model.beginRemoveRows(index, row, row) - - node = self.__children.pop(row) - node.setParent(None) - - if model is not None: - model.endRemoveRows() - - def data(self, column, role): - """Returns data for given column and role - - :param int column: Column index for this row - :param int role: The role to get - :return: Corresponding data (Default: None) - """ - if role == qt.Qt.ToolTipRole and self.__tooltip is not None: - return self.__tooltip - else: - return None - - def setData(self, column, value, role): - """Set data for given column and role - - :param int column: Column index for this row - :param value: The data to set - :param int role: The role to set - :return: True on success, False on failure - :rtype: bool - """ - return False - - def setToolTip(self, tooltip): - """Set the tooltip of the whole row. - - If None there is no tooltip. - - :param Union[str, None] tooltip: - """ - self.__tooltip = tooltip - - def setFlags(self, flags, column=None): - """Set the static flags to return. - - Default is ItemIsEnabled for all columns. - - :param int column: The column for which to set the flags - :param flags: Item flags - """ - if column is None: - self.__flags = collections.defaultdict(lambda: flags) - else: - self.__flags[column] = flags - - def flags(self, column): - """Returns flags for given column - - :rtype: int - """ - return self.__flags[column] - - -class StaticRow(BaseRow): - """Row with static data. - - :param tuple display: List of data for DisplayRole for each column - :param dict roles: Optional mapping of roles to list of data. - :param children: Iterable of BaseRow to start with (not signaled) - """ - - def __init__(self, display=('', None), roles=None, children=()): - super(StaticRow, self).__init__(children) - self._dataByRoles = {} if roles is None else roles - self._dataByRoles[qt.Qt.DisplayRole] = display - - def data(self, column, role): - if role in self._dataByRoles: - data = self._dataByRoles[role] - if column < len(data): - return data[column] - return super(StaticRow, self).data(column, role) - - def columnCount(self): - return len(self._dataByRoles[qt.Qt.DisplayRole]) - - -class ProxyRow(BaseRow): - """Provides a node to proxy a data accessible through functions. - - Warning: Only weak reference are kept on fget and fset. - - :param str name: The name of this node - :param callable fget: A callable returning the data - :param callable fset: - An optional callable setting the data with data as a single argument. - :param notify: - An optional signal emitted when data has changed. - :param callable toModelData: - An optional callable to convert from fget - callable to data returned by the model. - :param callable fromModelData: - An optional callable converting data provided to the model to - data for fset. - :param editorHint: Data to provide as UserRole for editor selection/setup - """ - - def __init__(self, - name='', - fget=None, - fset=None, - notify=None, - toModelData=None, - fromModelData=None, - editorHint=None): - - super(ProxyRow, self).__init__() - self.__name = name - self.__editorHint = editorHint - - assert fget is not None - self._fget = WeakMethodProxy(fget) - self._fset = WeakMethodProxy(fset) if fset is not None else None - if fset is not None: - self.setFlags(qt.Qt.ItemIsEnabled | qt.Qt.ItemIsEditable, 1) - self._toModelData = toModelData - self._fromModelData = fromModelData - - if notify is not None: - notify.connect(self._notified) # TODO support sigItemChanged flags - - def _notified(self, *args, **kwargs): - """Send update to the model upon signal notifications""" - index = self.index(column=1) - model = self.model() - if model is not None: - model.dataChanged.emit(index, index) - - def data(self, column, role): - if column == 0: - if role == qt.Qt.DisplayRole: - return self.__name - - elif column == 1: - if role == qt.Qt.UserRole: # EditorHint - return self.__editorHint - elif role == qt.Qt.DisplayRole or (role == qt.Qt.EditRole and - self._fset is not None): - data = self._fget() - if self._toModelData is not None: - data = self._toModelData(data) - return data - - return super(ProxyRow, self).data(column, role) - - def setData(self, column, value, role): - if role == qt.Qt.EditRole and self._fset is not None: - if self._fromModelData is not None: - value = self._fromModelData(value) - self._fset(value) - return True - - return super(ProxyRow, self).setData(column, value, role) - - -class ColorProxyRow(ProxyRow): - """Provides a proxy to a QColor property. - - The color is returned through the decorative role. - - See :class:`ProxyRow` - """ - - def data(self, column, role): - if column == 1: # Show color as decoration, not text - if role == qt.Qt.DisplayRole: - return None - if role == qt.Qt.DecorationRole: - role = qt.Qt.DisplayRole - return super(ColorProxyRow, self).data(column, role) - - -class AngleDegreeRow(ProxyRow): - """ProxyRow patching display of column 1 to add degree symbol - - See :class:`ProxyRow` - """ - - def __init__(self, *args, **kwargs): - super(AngleDegreeRow, self).__init__(*args, **kwargs) - - def data(self, column, role): - if column == 1 and role == qt.Qt.DisplayRole: - return u'%g°' % super(AngleDegreeRow, self).data(column, role) - else: - return super(AngleDegreeRow, self).data(column, role) |