diff options
Diffstat (limited to 'silx/gui/hdf5/NexusSortFilterProxyModel.py')
-rw-r--r-- | silx/gui/hdf5/NexusSortFilterProxyModel.py | 224 |
1 files changed, 0 insertions, 224 deletions
diff --git a/silx/gui/hdf5/NexusSortFilterProxyModel.py b/silx/gui/hdf5/NexusSortFilterProxyModel.py deleted file mode 100644 index 9c3533f..0000000 --- a/silx/gui/hdf5/NexusSortFilterProxyModel.py +++ /dev/null @@ -1,224 +0,0 @@ -# coding: utf-8 -# /*########################################################################## -# -# Copyright (c) 2016-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. -# -# ###########################################################################*/ - -__authors__ = ["V. Valls"] -__license__ = "MIT" -__date__ = "29/11/2018" - - -import logging -import re -import numpy -from .. import qt -from .Hdf5TreeModel import Hdf5TreeModel -import silx.io.utils -from silx.gui import icons - - -_logger = logging.getLogger(__name__) - - -class NexusSortFilterProxyModel(qt.QSortFilterProxyModel): - """Try to sort items according to Nexus structure. Else sort by name.""" - - def __init__(self, parent=None): - qt.QSortFilterProxyModel.__init__(self, parent) - self.__split = re.compile("(\\d+|\\D+)") - self.__iconCache = {} - - def hasChildren(self, parent): - """Returns true if parent has any children; otherwise returns false. - - :param qt.QModelIndex parent: Index of the item to check - :rtype: bool - """ - parent = self.mapToSource(parent) - return self.sourceModel().hasChildren(parent) - - def rowCount(self, parent): - """Returns the number of rows under the given parent. - - :param qt.QModelIndex parent: Index of the item to check - :rtype: int - """ - parent = self.mapToSource(parent) - return self.sourceModel().rowCount(parent) - - def lessThan(self, sourceLeft, sourceRight): - """Returns True if the value of the item referred to by the given - index `sourceLeft` is less than the value of the item referred to by - the given index `sourceRight`, otherwise returns false. - - :param qt.QModelIndex sourceLeft: - :param qt.QModelIndex sourceRight: - :rtype: bool - """ - if sourceLeft.column() != Hdf5TreeModel.NAME_COLUMN: - return super(NexusSortFilterProxyModel, self).lessThan( - sourceLeft, sourceRight) - - # Do not sort child of root (files) - if sourceLeft.parent() == qt.QModelIndex(): - return sourceLeft.row() < sourceRight.row() - - left = self.sourceModel().data(sourceLeft, Hdf5TreeModel.H5PY_ITEM_ROLE) - right = self.sourceModel().data(sourceRight, Hdf5TreeModel.H5PY_ITEM_ROLE) - - if self.__isNXentry(left) and self.__isNXentry(right): - less = self.childDatasetLessThan(left, right, "start_time") - if less is not None: - return less - less = self.childDatasetLessThan(left, right, "end_time") - if less is not None: - return less - - left = self.sourceModel().data(sourceLeft, qt.Qt.DisplayRole) - right = self.sourceModel().data(sourceRight, qt.Qt.DisplayRole) - return self.nameLessThan(left, right) - - def __isNXentry(self, node): - """Returns true if the node is an NXentry""" - class_ = node.h5Class - if class_ is None or class_ != silx.io.utils.H5Type.GROUP: - return False - nxClass = node.obj.attrs.get("NX_class", None) - return nxClass == "NXentry" - - def __isNXnode(self, node): - """Returns true if the node is an NX concept""" - if not hasattr(node, "h5Class"): - return False - class_ = node.h5Class - if class_ is None or class_ != silx.io.utils.H5Type.GROUP: - return False - nxClass = node.obj.attrs.get("NX_class", None) - return nxClass is not None - - def getWordsAndNumbers(self, name): - """ - Returns a list of words and integers composing the name. - - An input `"aaa10bbb50.30"` will return - `["aaa", 10, "bbb", 50, ".", 30]`. - - :param str name: A name - :rtype: List - """ - nonSensitive = self.sortCaseSensitivity() == qt.Qt.CaseInsensitive - words = self.__split.findall(name) - result = [] - for i in words: - if i[0].isdigit(): - i = int(i) - elif nonSensitive: - i = i.lower() - result.append(i) - return result - - def nameLessThan(self, left, right): - """Returns True if the left string is less than the right string. - - Number composing the names are compared as integers, as result "name2" - is smaller than "name10". - - :param str left: A string - :param str right: A string - :rtype: bool - """ - leftList = self.getWordsAndNumbers(left) - rightList = self.getWordsAndNumbers(right) - try: - return leftList < rightList - except TypeError: - # Back to string comparison if list are not type consistent - return left < right - - def childDatasetLessThan(self, left, right, childName): - """ - Reach the same children name of two items and compare their values. - - Returns True if the left one is smaller than the right one. - - :param Hdf5Item left: An item - :param Hdf5Item right: An item - :param str childName: Name of the children to search. Returns None if - the children is not found. - :rtype: bool - """ - try: - left_time = left.obj[childName][()] - right_time = right.obj[childName][()] - if isinstance(left_time, numpy.ndarray): - return left_time[0] < right_time[0] - return left_time < right_time - except KeyboardInterrupt: - raise - except Exception: - _logger.debug("Exception occurred", exc_info=True) - return None - - def __createCompoundIcon(self, backgroundIcon, foregroundIcon): - icon = qt.QIcon() - - sizes = backgroundIcon.availableSizes() - sizes = sorted(sizes, key=lambda s: s.height()) - sizes = filter(lambda s: s.height() < 100, sizes) - sizes = list(sizes) - if len(sizes) > 0: - baseSize = sizes[-1] - else: - baseSize = qt.QSize(32, 32) - - modes = [qt.QIcon.Normal, qt.QIcon.Disabled] - for mode in modes: - pixmap = qt.QPixmap(baseSize) - pixmap.fill(qt.Qt.transparent) - painter = qt.QPainter(pixmap) - painter.drawPixmap(0, 0, backgroundIcon.pixmap(baseSize, mode=mode)) - painter.drawPixmap(0, 0, foregroundIcon.pixmap(baseSize, mode=mode)) - painter.end() - icon.addPixmap(pixmap, mode=mode) - - return icon - - def __getNxIcon(self, baseIcon): - iconHash = baseIcon.cacheKey() - icon = self.__iconCache.get(iconHash, None) - if icon is None: - nxIcon = icons.getQIcon("layer-nx") - icon = self.__createCompoundIcon(baseIcon, nxIcon) - self.__iconCache[iconHash] = icon - return icon - - def data(self, index, role=qt.Qt.DisplayRole): - result = super(NexusSortFilterProxyModel, self).data(index, role) - - if index.column() == Hdf5TreeModel.NAME_COLUMN: - if role == qt.Qt.DecorationRole: - sourceIndex = self.mapToSource(index) - item = self.sourceModel().data(sourceIndex, Hdf5TreeModel.H5PY_ITEM_ROLE) - if self.__isNXnode(item): - result = self.__getNxIcon(result) - return result |