summaryrefslogtreecommitdiff
path: root/silx/app/view
diff options
context:
space:
mode:
authorAlexandre Marie <alexandre.marie@synchrotron-soleil.fr>2018-12-17 12:28:24 +0100
committerAlexandre Marie <alexandre.marie@synchrotron-soleil.fr>2018-12-17 12:28:24 +0100
commitcebdc9244c019224846cb8d2668080fe386a6adc (patch)
treeaedec55da0f9dd4fc4d6c7eb0f58489a956e2e8c /silx/app/view
parent159ef14fb9e198bb0066ea14e6b980f065de63dd (diff)
New upstream version 0.9.0+dfsg
Diffstat (limited to 'silx/app/view')
-rw-r--r--silx/app/view/About.py44
-rw-r--r--silx/app/view/CustomNxdataWidget.py8
-rw-r--r--silx/app/view/DataPanel.py35
-rw-r--r--silx/app/view/Viewer.py149
-rw-r--r--silx/app/view/test/test_view.py2
5 files changed, 214 insertions, 24 deletions
diff --git a/silx/app/view/About.py b/silx/app/view/About.py
index 07306ef..4b804f2 100644
--- a/silx/app/view/About.py
+++ b/silx/app/view/About.py
@@ -25,7 +25,7 @@
__authors__ = ["V. Valls"]
__license__ = "MIT"
-__date__ = "05/06/2018"
+__date__ = "05/07/2018"
import sys
@@ -147,6 +147,15 @@ class About(qt.QDialog):
template = '<b>%s</b> is <font color="red">not loaded</font>'
return template % name
+ @staticmethod
+ def __formatOptionalFilters(name, isAvailable):
+ """Utils to format availability of features"""
+ if isAvailable:
+ template = '<b>%s</b> is <font color="green">available</font>'
+ else:
+ template = '<b>%s</b> is <font color="red">not available</font>'
+ return template % name
+
def __updateText(self):
"""Update the content of the dialog according to the settings."""
import silx._version
@@ -174,14 +183,29 @@ class About(qt.QDialog):
</p>
"""
- hdf5pluginLoaded = "hdf5plugin" in sys.modules
- fabioLoaded = "fabio" in sys.modules
- h5pyLoaded = "h5py" in sys.modules
-
- optional_lib = []
- optional_lib.append(self.__formatOptionalLibraries("FabIO", fabioLoaded))
- optional_lib.append(self.__formatOptionalLibraries("H5py", h5pyLoaded))
- optional_lib.append(self.__formatOptionalLibraries("hdf5plugin", hdf5pluginLoaded))
+ optionals = []
+ optionals.append(self.__formatOptionalLibraries("H5py", "h5py" in sys.modules))
+ optionals.append(self.__formatOptionalLibraries("FabIO", "fabio" in sys.modules))
+
+ try:
+ import h5py.version
+ if h5py.version.hdf5_version_tuple >= (1, 10, 2):
+ # Previous versions only return True if the filter was first used
+ # to decode a dataset
+ import h5py.h5z
+ FILTER_LZ4 = 32004
+ FILTER_BITSHUFFLE = 32008
+ filters = [
+ ("HDF5 LZ4 filter", FILTER_LZ4),
+ ("HDF5 Bitshuffle filter", FILTER_BITSHUFFLE),
+ ]
+ for name, filterId in filters:
+ isAvailable = h5py.h5z.filter_avail(filterId)
+ optionals.append(self.__formatOptionalFilters(name, isAvailable))
+ else:
+ optionals.append(self.__formatOptionalLibraries("hdf5plugin", "hdf5plugin" in sys.modules))
+ except ImportError:
+ pass
# Access to the logo in SVG or PNG
logo = icons.getQFile("../logo/silx")
@@ -194,7 +218,7 @@ class About(qt.QDialog):
qt_binding=qt.BINDING,
qt_version=qt.qVersion(),
python_version=sys.version.replace("\n", "<br />"),
- optional_lib="<br />".join(optional_lib),
+ optional_lib="<br />".join(optionals),
silx_image_path=logo.fileName()
)
diff --git a/silx/app/view/CustomNxdataWidget.py b/silx/app/view/CustomNxdataWidget.py
index 02ae6c0..72c9940 100644
--- a/silx/app/view/CustomNxdataWidget.py
+++ b/silx/app/view/CustomNxdataWidget.py
@@ -944,10 +944,10 @@ class CustomNxdataWidget(qt.QTreeView):
if edited:
item.setAxesDatasets(datasets)
- dataset = item.getSignalDataset()
- newDataset = self.__replaceDatasetRoot(dataset, removedRoot, loadedRoot)
- if dataset is not newDataset:
- item.setSignalDataset(newDataset)
+ dataset = item.getSignalDataset()
+ newDataset = self.__replaceDatasetRoot(dataset, removedRoot, loadedRoot)
+ if dataset is not newDataset:
+ item.setSignalDataset(newDataset)
def __replaceDatasetRoot(self, dataset, fromRoot, toRoot):
"""
diff --git a/silx/app/view/DataPanel.py b/silx/app/view/DataPanel.py
index 0653f74..5d87381 100644
--- a/silx/app/view/DataPanel.py
+++ b/silx/app/view/DataPanel.py
@@ -25,9 +25,10 @@
__authors__ = ["V. Valls"]
__license__ = "MIT"
-__date__ = "06/06/2018"
+__date__ = "12/10/2018"
import logging
+import os.path
from silx.gui import qt
from silx.gui.data.DataViewerFrame import DataViewerFrame
@@ -45,6 +46,26 @@ class _HeaderLabel(qt.QLabel):
def sizeHint(self):
return qt.QSize(10, 30)
+ def minimumSizeHint(self):
+ return qt.QSize(10, 30)
+
+ def setData(self, filename, path):
+ if filename == "" and path == "":
+ text = ""
+ elif filename == "":
+ text = path
+ else:
+ text = "%s::%s" % (filename, path)
+ self.setText(text)
+ tooltip = ""
+ template = "<li><b>%s</b>: %s</li>"
+ tooltip += template % ("Directory", os.path.dirname(filename))
+ tooltip += template % ("File name", os.path.basename(filename))
+ tooltip += template % ("Data path", path)
+ tooltip = "<ul>%s</ul>" % tooltip
+ tooltip = "<html>%s</html>" % tooltip
+ self.setToolTip(tooltip)
+
def paintEvent(self, event):
painter = qt.QPainter(self)
@@ -101,14 +122,14 @@ class DataPanel(qt.QWidget):
self.__dataTitle.setVisible(True)
if hasattr(data, "name"):
if hasattr(data, "file"):
- label = str(data.file.filename)
- label += "::"
+ filename = str(data.file.filename)
else:
- label = ""
- label += data.name
+ filename = ""
+ path = data.name
else:
- label = ""
- self.__dataTitle.setText(label)
+ filename = ""
+ path = ""
+ self.__dataTitle.setData(filename, path)
def setCustomDataItem(self, item):
self.__customNxdataItem = item
diff --git a/silx/app/view/Viewer.py b/silx/app/view/Viewer.py
index 8f5db60..88ff989 100644
--- a/silx/app/view/Viewer.py
+++ b/silx/app/view/Viewer.py
@@ -25,7 +25,7 @@
__authors__ = ["V. Valls"]
__license__ = "MIT"
-__date__ = "25/06/2018"
+__date__ = "08/10/2018"
import os
@@ -146,6 +146,18 @@ class Viewer(qt.QMainWindow):
toolbar.setStyleSheet("QToolBar { border: 0px }")
action = qt.QAction(toolbar)
+ action.setIcon(icons.getQIcon("view-refresh"))
+ action.setText("Refresh")
+ action.setToolTip("Refresh all selected items")
+ action.triggered.connect(self.__refreshSelected)
+ action.setShortcut(qt.QKeySequence(qt.Qt.ControlModifier + qt.Qt.Key_Plus))
+ toolbar.addAction(action)
+ treeView.addAction(action)
+ self.__refreshAction = action
+
+ toolbar.addSeparator()
+
+ action = qt.QAction(toolbar)
action.setIcon(icons.getQIcon("tree-expand-all"))
action.setText("Expand all")
action.setToolTip("Expand all selected items")
@@ -173,6 +185,135 @@ class Viewer(qt.QMainWindow):
layout.addWidget(treeView)
return widget
+ def __refreshSelected(self):
+ """Refresh all selected items
+ """
+ qt.QApplication.setOverrideCursor(qt.Qt.WaitCursor)
+
+ selection = self.__treeview.selectionModel()
+ indexes = selection.selectedIndexes()
+ selectedItems = []
+ model = self.__treeview.model()
+ h5files = set([])
+ while len(indexes) > 0:
+ index = indexes.pop(0)
+ if index.column() != 0:
+ continue
+ h5 = model.data(index, role=silx.gui.hdf5.Hdf5TreeModel.H5PY_OBJECT_ROLE)
+ rootIndex = index
+ # Reach the root of the tree
+ while rootIndex.parent().isValid():
+ rootIndex = rootIndex.parent()
+ rootRow = rootIndex.row()
+ relativePath = self.__getRelativePath(model, rootIndex, index)
+ selectedItems.append((rootRow, relativePath))
+ h5files.add(h5.file)
+
+ if len(h5files) == 0:
+ qt.QApplication.restoreOverrideCursor()
+ return
+
+ model = self.__treeview.findHdf5TreeModel()
+ for h5 in h5files:
+ self.__synchronizeH5pyObject(h5)
+
+ model = self.__treeview.model()
+ itemSelection = qt.QItemSelection()
+ for rootRow, relativePath in selectedItems:
+ rootIndex = model.index(rootRow, 0, qt.QModelIndex())
+ index = self.__indexFromPath(model, rootIndex, relativePath)
+ if index is None:
+ continue
+ indexEnd = model.index(index.row(), model.columnCount() - 1, index.parent())
+ itemSelection.select(index, indexEnd)
+ selection.select(itemSelection, qt.QItemSelectionModel.ClearAndSelect)
+
+ qt.QApplication.restoreOverrideCursor()
+
+ def __synchronizeH5pyObject(self, h5):
+ model = self.__treeview.findHdf5TreeModel()
+ # This is buggy right now while h5py do not allow to close a file
+ # while references are still used.
+ # FIXME: The architecture have to be reworked to support this feature.
+ # model.synchronizeH5pyObject(h5)
+
+ filename = h5.filename
+ row = model.h5pyObjectRow(h5)
+ index = self.__treeview.model().index(row, 0, qt.QModelIndex())
+ paths = self.__getPathFromExpandedNodes(self.__treeview, index)
+ model.removeH5pyObject(h5)
+ model.insertFile(filename, row)
+ index = self.__treeview.model().index(row, 0, qt.QModelIndex())
+ self.__expandNodesFromPaths(self.__treeview, index, paths)
+
+ def __getRelativePath(self, model, rootIndex, index):
+ """Returns a relative path from an index to his rootIndex.
+
+ If the path is empty the index is also the rootIndex.
+ """
+ path = ""
+ while index.isValid():
+ if index == rootIndex:
+ return path
+ name = model.data(index)
+ if path == "":
+ path = name
+ else:
+ path = name + "/" + path
+ index = index.parent()
+
+ # index is not a children of rootIndex
+ raise ValueError("index is not a children of the rootIndex")
+
+ def __getPathFromExpandedNodes(self, view, rootIndex):
+ """Return relative path from the root index of the extended nodes"""
+ model = view.model()
+ rootPath = None
+ paths = []
+ indexes = [rootIndex]
+ while len(indexes):
+ index = indexes.pop(0)
+ if not view.isExpanded(index):
+ continue
+
+ node = model.data(index, role=silx.gui.hdf5.Hdf5TreeModel.H5PY_ITEM_ROLE)
+ path = node._getCanonicalName()
+ if rootPath is None:
+ rootPath = path
+ path = path[len(rootPath):]
+ paths.append(path)
+
+ for child in range(model.rowCount(index)):
+ childIndex = model.index(child, 0, index)
+ indexes.append(childIndex)
+ return paths
+
+ def __indexFromPath(self, model, rootIndex, path):
+ elements = path.split("/")
+ if elements[0] == "":
+ elements.pop(0)
+ index = rootIndex
+ while len(elements) != 0:
+ element = elements.pop(0)
+ found = False
+ for child in range(model.rowCount(index)):
+ childIndex = model.index(child, 0, index)
+ name = model.data(childIndex)
+ if element == name:
+ index = childIndex
+ found = True
+ break
+ if not found:
+ return None
+ return index
+
+ def __expandNodesFromPaths(self, view, rootIndex, paths):
+ model = view.model()
+ for path in paths:
+ index = self.__indexFromPath(model, rootIndex, path)
+ if index is not None:
+ view.setExpanded(index, True)
+
def __expandAllSelected(self):
"""Expand all selected items of the tree.
@@ -185,6 +326,8 @@ class Viewer(qt.QMainWindow):
model = self.__treeview.model()
while len(indexes) > 0:
index = indexes.pop(0)
+ if index.column() != 0:
+ continue
if isinstance(index, tuple):
index, depth = index
else:
@@ -211,6 +354,8 @@ class Viewer(qt.QMainWindow):
model = self.__treeview.model()
while len(indexes) > 0:
index = indexes.pop(0)
+ if index.column() != 0:
+ continue
if isinstance(index, tuple):
index, depth = index
else:
@@ -682,5 +827,5 @@ class Viewer(qt.QMainWindow):
action.triggered.connect(lambda: self.__treeview.findHdf5TreeModel().removeH5pyObject(h5))
menu.addAction(action)
action = qt.QAction("Synchronize %s" % obj.local_filename, event.source())
- action.triggered.connect(lambda: self.__treeview.findHdf5TreeModel().synchronizeH5pyObject(h5))
+ action.triggered.connect(lambda: self.__synchronizeH5pyObject(h5))
menu.addAction(action)
diff --git a/silx/app/view/test/test_view.py b/silx/app/view/test/test_view.py
index 010cda5..ebcd405 100644
--- a/silx/app/view/test/test_view.py
+++ b/silx/app/view/test/test_view.py
@@ -46,7 +46,7 @@ from silx.app.view.About import About
from silx.app.view.DataPanel import DataPanel
from silx.app.view.CustomNxdataWidget import CustomNxdataWidget
from silx.gui.hdf5._utils import Hdf5DatasetMimeData
-from silx.gui.test.utils import TestCaseQt
+from silx.gui.utils.testutils import TestCaseQt
from silx.io import commonh5
_tmpDirectory = None