summaryrefslogtreecommitdiff
path: root/silx/gui/hdf5/NexusSortFilterProxyModel.py
diff options
context:
space:
mode:
Diffstat (limited to 'silx/gui/hdf5/NexusSortFilterProxyModel.py')
-rw-r--r--silx/gui/hdf5/NexusSortFilterProxyModel.py224
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