summaryrefslogtreecommitdiff
path: root/silx/gui/dialog
diff options
context:
space:
mode:
authorPicca Frédéric-Emmanuel <picca@synchrotron-soleil.fr>2019-05-28 08:16:16 +0200
committerPicca Frédéric-Emmanuel <picca@synchrotron-soleil.fr>2019-05-28 08:16:16 +0200
commit7287b75301a53bae723579b145448d43304272af (patch)
treedf6d1a4595f3352a8c90ce9cba0e71ea0269e98b /silx/gui/dialog
parent3e5dcad207c1eadeb74fb53f524c3a94fbe19096 (diff)
parenta763e5d1b3921b3194f3d4e94ab9de3fbe08bbdd (diff)
Update upstream source from tag 'upstream/0.10.1+dfsg'
Update to upstream version '0.10.1+dfsg' with Debian dir 6b2d4eeabb68177b2b91df4d7527306d5e19409d
Diffstat (limited to 'silx/gui/dialog')
-rw-r--r--silx/gui/dialog/AbstractDataFileDialog.py56
-rw-r--r--silx/gui/dialog/ColormapDialog.py355
-rw-r--r--silx/gui/dialog/DataFileDialog.py10
-rw-r--r--silx/gui/dialog/FileTypeComboBox.py39
-rw-r--r--silx/gui/dialog/ImageFileDialog.py5
-rw-r--r--silx/gui/dialog/SafeFileSystemModel.py6
-rw-r--r--silx/gui/dialog/test/test_colormapdialog.py36
-rw-r--r--silx/gui/dialog/test/test_datafiledialog.py115
-rw-r--r--silx/gui/dialog/test/test_imagefiledialog.py117
-rw-r--r--silx/gui/dialog/utils.py6
10 files changed, 394 insertions, 351 deletions
diff --git a/silx/gui/dialog/AbstractDataFileDialog.py b/silx/gui/dialog/AbstractDataFileDialog.py
index 40045fe..c660cd7 100644
--- a/silx/gui/dialog/AbstractDataFileDialog.py
+++ b/silx/gui/dialog/AbstractDataFileDialog.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2016 European Synchrotron Radiation Facility
+# 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
@@ -28,29 +28,36 @@ This module contains an :class:`AbstractDataFileDialog`.
__authors__ = ["V. Valls"]
__license__ = "MIT"
-__date__ = "05/03/2018"
+__date__ = "03/12/2018"
import sys
import os
import logging
-import numpy
import functools
+from distutils.version import LooseVersion
+
+import numpy
+import six
+
import silx.io.url
from silx.gui import qt
from silx.gui.hdf5.Hdf5TreeModel import Hdf5TreeModel
from . import utils
-from silx.third_party import six
from .FileTypeComboBox import FileTypeComboBox
-try:
- import fabio
-except ImportError:
- fabio = None
+
+import fabio
_logger = logging.getLogger(__name__)
+DEFAULT_SIDEBAR_URL = True
+"""Set it to false to disable initilializing of the sidebar urls with the
+default Qt list. This could allow to disable a behaviour known to segfault on
+some version of PyQt."""
+
+
class _IconProvider(object):
FileDialogToParentDir = qt.QStyle.SP_CustomBase + 1
@@ -143,14 +150,22 @@ class _SideBar(qt.QListView):
:rtype: List[str]
"""
urls = []
- if qt.qVersion().startswith("5.") and sys.platform in ["linux", "linux2"]:
+ version = LooseVersion(qt.qVersion())
+ feed_sidebar = True
+
+ if not DEFAULT_SIDEBAR_URL:
+ _logger.debug("Skip default sidebar URLs (from setted variable)")
+ feed_sidebar = False
+ elif version.version[0] == 4 and sys.platform in ["win32"]:
+ # Avoid locking the GUI 5min in case of use of network driver
+ _logger.debug("Skip default sidebar URLs (avoid lock when using network drivers)")
+ feed_sidebar = False
+ elif version < LooseVersion("5.11.2") and qt.BINDING == "PyQt5" and sys.platform in ["linux", "linux2"]:
# Avoid segfault on PyQt5 + gtk
_logger.debug("Skip default sidebar URLs (avoid PyQt5 segfault)")
- pass
- elif qt.qVersion().startswith("4.") and sys.platform in ["win32"]:
- # Avoid 5min of locked GUI relative to network driver
- _logger.debug("Skip default sidebar URLs (avoid lock when using network drivers)")
- else:
+ feed_sidebar = False
+
+ if feed_sidebar:
# Get default shortcut
# There is no other way
d = qt.QFileDialog(self)
@@ -1061,8 +1076,6 @@ class AbstractDataFileDialog(qt.QDialog):
def __openFabioFile(self, filename):
self.__closeFile()
try:
- if fabio is None:
- raise ImportError("Fabio module is not available")
self.__fabio = fabio.open(filename)
self.__openedFiles.append(self.__fabio)
self.__selectedFile = filename
@@ -1108,10 +1121,10 @@ class AbstractDataFileDialog(qt.QDialog):
if codec.is_autodetect():
if self.__isSilxHavePriority(filename):
openners.append(self.__openSilxFile)
- if fabio is not None and self._isFabioFilesSupported():
+ if self._isFabioFilesSupported():
openners.append(self.__openFabioFile)
else:
- if fabio is not None and self._isFabioFilesSupported():
+ if self._isFabioFilesSupported():
openners.append(self.__openFabioFile)
openners.append(self.__openSilxFile)
elif codec.is_silx_codec():
@@ -1159,10 +1172,9 @@ class AbstractDataFileDialog(qt.QDialog):
is_fabio_have_priority = not codec.is_silx_codec() and not self.__isSilxHavePriority(path)
if is_fabio_decoder or is_fabio_have_priority:
# Then it's flat frame container
- if fabio is not None:
- self.__openFabioFile(path)
- if self.__fabio is not None:
- selectedData = _FabioData(self.__fabio)
+ self.__openFabioFile(path)
+ if self.__fabio is not None:
+ selectedData = _FabioData(self.__fabio)
else:
assert(False)
diff --git a/silx/gui/dialog/ColormapDialog.py b/silx/gui/dialog/ColormapDialog.py
index cbbfa5a..9950ad4 100644
--- a/silx/gui/dialog/ColormapDialog.py
+++ b/silx/gui/dialog/ColormapDialog.py
@@ -63,9 +63,10 @@ from __future__ import division
__authors__ = ["V.A. Sole", "T. Vincent", "H. Payno"]
__license__ = "MIT"
-__date__ = "23/05/2018"
+__date__ = "27/11/2018"
+import enum
import logging
import numpy
@@ -73,10 +74,10 @@ import numpy
from .. import qt
from ..colors import Colormap, preferredColormaps
from ..plot import PlotWidget
+from ..plot.items.axis import Axis
from silx.gui.widgets.FloatEdit import FloatEdit
import weakref
from silx.math.combo import min_max
-from silx.third_party import enum
from silx.gui import icons
from silx.math.histogram import Histogramnd
@@ -154,39 +155,59 @@ class _ColormapNameCombox(qt.QComboBox):
qt.QComboBox.__init__(self, parent)
self.__initItems()
- ORIGINAL_NAME = qt.Qt.UserRole + 1
+ LUT_NAME = qt.Qt.UserRole + 1
+ LUT_COLORS = qt.Qt.UserRole + 2
def __initItems(self):
for colormapName in preferredColormaps():
index = self.count()
self.addItem(str.title(colormapName))
- self.setItemIcon(index, self.getIconPreview(colormapName))
- self.setItemData(index, colormapName, role=self.ORIGINAL_NAME)
+ self.setItemIcon(index, self.getIconPreview(name=colormapName))
+ self.setItemData(index, colormapName, role=self.LUT_NAME)
- def getIconPreview(self, colormapName):
+ def getIconPreview(self, name=None, colors=None):
"""Return an icon preview from a LUT name.
This icons are cached into a global structure.
- :param str colormapName: str
+ :param str name: Name of the LUT
+ :param numpy.ndarray colors: Colors identify the LUT
:rtype: qt.QIcon
"""
- if colormapName not in _colormapIconPreview:
- icon = self.createIconPreview(colormapName)
- _colormapIconPreview[colormapName] = icon
- return _colormapIconPreview[colormapName]
-
- def createIconPreview(self, colormapName):
+ if name is not None:
+ iconKey = name
+ else:
+ iconKey = tuple(colors)
+ icon = _colormapIconPreview.get(iconKey, None)
+ if icon is None:
+ icon = self.createIconPreview(name, colors)
+ _colormapIconPreview[iconKey] = icon
+ return icon
+
+ def createIconPreview(self, name=None, colors=None):
"""Create and return an icon preview from a LUT name.
This icons are cached into a global structure.
- :param str colormapName: Name of the LUT
+ :param str name: Name of the LUT
+ :param numpy.ndarray colors: Colors identify the LUT
:rtype: qt.QIcon
"""
- colormap = Colormap(colormapName)
+ colormap = Colormap(name)
size = 32
- lut = colormap.getNColors(size)
+ if name is not None:
+ lut = colormap.getNColors(size)
+ else:
+ lut = colors
+ if len(lut) > size:
+ # Down sample
+ step = int(len(lut) / size)
+ lut = lut[::step]
+ elif len(lut) < size:
+ # Over sample
+ indexes = numpy.arange(size) / float(size) * (len(lut) - 1)
+ indexes = indexes.astype("int")
+ lut = lut[indexes]
if lut is None or len(lut) == 0:
return qt.QIcon()
@@ -204,18 +225,50 @@ class _ColormapNameCombox(qt.QComboBox):
return qt.QIcon(pixmap)
def getCurrentName(self):
- return self.itemData(self.currentIndex(), self.ORIGINAL_NAME)
+ return self.itemData(self.currentIndex(), self.LUT_NAME)
+
+ def getCurrentColors(self):
+ return self.itemData(self.currentIndex(), self.LUT_COLORS)
+
+ def findLutName(self, name):
+ return self.findData(name, role=self.LUT_NAME)
+
+ def findLutColors(self, lut):
+ for index in range(self.count()):
+ if self.itemData(index, role=self.LUT_NAME) is not None:
+ continue
+ colors = self.itemData(index, role=self.LUT_COLORS)
+ if colors is None:
+ continue
+ if numpy.array_equal(colors, lut):
+ return index
+ return -1
+
+ def setCurrentLut(self, colormap):
+ name = colormap.getName()
+ if name is not None:
+ self._setCurrentName(name)
+ else:
+ lut = colormap.getColormapLUT()
+ self._setCurrentLut(lut)
- def findColormap(self, name):
- return self.findData(name, role=self.ORIGINAL_NAME)
+ def _setCurrentLut(self, lut):
+ index = self.findLutColors(lut)
+ if index == -1:
+ index = self.count()
+ self.addItem("Custom")
+ self.setItemIcon(index, self.getIconPreview(colors=lut))
+ self.setItemData(index, None, role=self.LUT_NAME)
+ self.setItemData(index, lut, role=self.LUT_COLORS)
+ self.setCurrentIndex(index)
- def setCurrentName(self, name):
- index = self.findColormap(name)
+ def _setCurrentName(self, name):
+ index = self.findLutName(name)
if index < 0:
index = self.count()
self.addItem(str.title(name))
- self.setItemIcon(index, self.getIconPreview(name))
- self.setItemData(index, name, role=self.ORIGINAL_NAME)
+ self.setItemIcon(index, self.getIconPreview(name=name))
+ self.setItemData(index, name, role=self.LUT_NAME)
self.setCurrentIndex(index)
@@ -255,6 +308,7 @@ class ColormapDialog(qt.QDialog):
the self.setcolormap is a callback)
"""
+ self.__displayInvalidated = False
self._histogramData = None
self._minMaxWasEdited = False
self._initialRange = None
@@ -276,20 +330,19 @@ class ColormapDialog(qt.QDialog):
# Colormap row
self._comboBoxColormap = _ColormapNameCombox(parent=formWidget)
- self._comboBoxColormap.currentIndexChanged[int].connect(self._updateName)
+ self._comboBoxColormap.currentIndexChanged[int].connect(self._updateLut)
formLayout.addRow('Colormap:', self._comboBoxColormap)
# Normalization row
self._normButtonLinear = qt.QRadioButton('Linear')
self._normButtonLinear.setChecked(True)
self._normButtonLog = qt.QRadioButton('Log')
- self._normButtonLog.toggled.connect(self._activeLogNorm)
normButtonGroup = qt.QButtonGroup(self)
normButtonGroup.setExclusive(True)
normButtonGroup.addButton(self._normButtonLinear)
normButtonGroup.addButton(self._normButtonLog)
- self._normButtonLinear.toggled[bool].connect(self._updateLinearNorm)
+ normButtonGroup.buttonClicked[qt.QAbstractButton].connect(self._updateNormalization)
normLayout = qt.QHBoxLayout()
normLayout.setContentsMargins(0, 0, 0, 0)
@@ -388,9 +441,17 @@ class ColormapDialog(qt.QDialog):
self.setFixedSize(self.sizeHint())
self._applyColormap()
+ def _displayLater(self):
+ self.__displayInvalidated = True
+
def showEvent(self, event):
self.visibleChanged.emit(True)
super(ColormapDialog, self).showEvent(event)
+ if self.isVisible():
+ if self.__displayInvalidated:
+ self._applyColormap()
+ self._updateDataInPlot()
+ self.__displayInvalidated = False
def closeEvent(self, event):
if not self.isModal():
@@ -434,6 +495,54 @@ class ColormapDialog(qt.QDialog):
def sizeHint(self):
return self.layout().minimumSize()
+ def _computeView(self, dataMin, dataMax):
+ """Compute the location of the view according to the bound of the data
+
+ :rtype: Tuple(float, float)
+ """
+ marginRatio = 1.0 / 6.0
+ scale = self._plot.getXAxis().getScale()
+
+ if self._dataRange is not None:
+ if scale == Axis.LOGARITHMIC:
+ minRange = self._dataRange[1]
+ else:
+ minRange = self._dataRange[0]
+ maxRange = self._dataRange[2]
+ if minRange is not None:
+ dataMin = min(dataMin, minRange)
+ dataMax = max(dataMax, maxRange)
+
+ if self._histogramData is not None:
+ info = min_max(self._histogramData[1])
+ if scale == Axis.LOGARITHMIC:
+ minHisto = info.min_positive
+ else:
+ minHisto = info.minimum
+ maxHisto = info.maximum
+ if minHisto is not None:
+ dataMin = min(dataMin, minHisto)
+ dataMax = max(dataMax, maxHisto)
+
+ if scale == Axis.LOGARITHMIC:
+ epsilon = numpy.finfo(numpy.float32).eps
+ if dataMin == 0:
+ dataMin = epsilon
+ if dataMax < dataMin:
+ dataMax = dataMin + epsilon
+ marge = marginRatio * abs(numpy.log10(dataMax) - numpy.log10(dataMin))
+ viewMin = 10**(numpy.log10(dataMin) - marge)
+ viewMax = 10**(numpy.log10(dataMax) + marge)
+ else: # scale == Axis.LINEAR:
+ marge = marginRatio * abs(dataMax - dataMin)
+ if marge < 0.0001:
+ # Smaller that the QLineEdit precision
+ marge = 0.0001
+ viewMin = dataMin - marge
+ viewMax = dataMax + marge
+
+ return viewMin, viewMax
+
def _plotUpdate(self, updateMarkers=True):
"""Update the plot content
@@ -454,27 +563,8 @@ class ColormapDialog(qt.QDialog):
if minData > maxData:
# avoid a full collapse
minData, maxData = maxData, minData
- minimum = minData
- maximum = maxData
-
- if self._dataRange is not None:
- minRange = self._dataRange[0]
- maxRange = self._dataRange[2]
- minimum = min(minimum, minRange)
- maximum = max(maximum, maxRange)
- if self._histogramData is not None:
- minHisto = self._histogramData[1][0]
- maxHisto = self._histogramData[1][-1]
- minimum = min(minimum, minHisto)
- maximum = max(maximum, maxHisto)
-
- marge = abs(maximum - minimum) / 6.0
- if marge < 0.0001:
- # Smaller that the QLineEdit precision
- marge = 0.0001
-
- minView, maxView = minimum - marge, maximum + marge
+ minView, maxView = self._computeView(minData, maxData)
if updateMarkers:
# Save the state in we are not moving the markers
@@ -483,6 +573,9 @@ class ColormapDialog(qt.QDialog):
minView = min(minView, self._initialRange[0])
maxView = max(maxView, self._initialRange[1])
+ if minView > minData:
+ # Hide the min range
+ minData = minView
x = [minView, minData, maxData, maxView]
y = [0, 0, 1, 1]
@@ -493,26 +586,37 @@ class ColormapDialog(qt.QDialog):
linestyle='-',
resetzoom=False)
+ scale = self._plot.getXAxis().getScale()
+
if updateMarkers:
- minDraggable = (self._colormap().isEditable() and
- not self._minValue.isAutoChecked())
- self._plot.addXMarker(
- self._minValue.getFiniteValue(),
- legend='Min',
- text='Min',
- draggable=minDraggable,
- color='blue',
- constraint=self._plotMinMarkerConstraint)
-
- maxDraggable = (self._colormap().isEditable() and
- not self._maxValue.isAutoChecked())
- self._plot.addXMarker(
- self._maxValue.getFiniteValue(),
- legend='Max',
- text='Max',
- draggable=maxDraggable,
- color='blue',
- constraint=self._plotMaxMarkerConstraint)
+ posMin = self._minValue.getFiniteValue()
+ posMax = self._maxValue.getFiniteValue()
+
+ def isDisplayable(pos):
+ if scale == Axis.LOGARITHMIC:
+ return pos > 0.0
+ return True
+
+ if isDisplayable(posMin):
+ minDraggable = (self._colormap().isEditable() and
+ not self._minValue.isAutoChecked())
+ self._plot.addXMarker(
+ posMin,
+ legend='Min',
+ text='Min',
+ draggable=minDraggable,
+ color='blue',
+ constraint=self._plotMinMarkerConstraint)
+ if isDisplayable(posMax):
+ maxDraggable = (self._colormap().isEditable() and
+ not self._maxValue.isAutoChecked())
+ self._plot.addXMarker(
+ posMax,
+ legend='Max',
+ text='Max',
+ draggable=maxDraggable,
+ color='blue',
+ constraint=self._plotMaxMarkerConstraint)
self._plot.resetZoom()
@@ -546,7 +650,7 @@ class ColormapDialog(qt.QDialog):
"""Compute the data range as used by :meth:`setDataRange`.
:param data: The data to process
- :rtype: Tuple(float, float, float)
+ :rtype: List[Union[None,float]]
"""
if data is None or len(data) == 0:
return None, None, None
@@ -558,8 +662,6 @@ class ColormapDialog(qt.QDialog):
if dataRange is not None:
min_positive = dataRange.min_positive
- if min_positive is None:
- min_positive = float('nan')
dataRange = dataRange.minimum, min_positive, dataRange.maximum
if dataRange is None or len(dataRange) != 3:
@@ -571,7 +673,7 @@ class ColormapDialog(qt.QDialog):
return dataRange
@staticmethod
- def computeHistogram(data):
+ def computeHistogram(data, scale=Axis.LINEAR):
"""Compute the data histogram as used by :meth:`setHistogram`.
:param data: The data to process
@@ -588,7 +690,12 @@ class ColormapDialog(qt.QDialog):
if len(_data) == 0:
return None, None
+ if scale == Axis.LOGARITHMIC:
+ _data = numpy.log10(_data)
xmin, xmax = min_max(_data, min_positive=False, finite=True)
+ if xmin is None:
+ return None, None
+
nbins = min(256, int(numpy.sqrt(_data.size)))
data_range = xmin, xmax
@@ -601,7 +708,10 @@ class ColormapDialog(qt.QDialog):
_data = _data.ravel().astype(numpy.float32)
histogram = Histogramnd(_data, n_bins=nbins, histo_range=data_range)
- return histogram.histo, histogram.edges[0]
+ bins = histogram.edges[0]
+ if scale == Axis.LOGARITHMIC:
+ bins = 10**bins
+ return histogram.histo, bins
def _getData(self):
if self._data is None:
@@ -624,7 +734,10 @@ class ColormapDialog(qt.QDialog):
else:
self._data = weakref.ref(data, self._dataAboutToFinalize)
- self._updateDataInPlot()
+ if self.isVisible():
+ self._updateDataInPlot()
+ else:
+ self._displayLater()
def _setDataInPlotMode(self, mode):
if self._dataInPlotMode == mode:
@@ -660,10 +773,15 @@ class ColormapDialog(qt.QDialog):
self.setDataRange(*result)
elif mode == _DataInPlotMode.HISTOGRAM:
# The histogram should be done in a worker thread
- result = self.computeHistogram(data)
+ result = self.computeHistogram(data, scale=self._plot.getXAxis().getScale())
self.setHistogram(*result)
self.setDataRange()
+ def _invalidateHistogram(self):
+ """Recompute the histogram if it is displayed"""
+ if self._dataInPlotMode == _DataInPlotMode.HISTOGRAM:
+ self._updateDataInPlot()
+
def _colormapAboutToFinalize(self, weakrefColormap):
"""Callback when the data weakref is about to be finalized."""
if self._colormap is weakrefColormap:
@@ -727,9 +845,9 @@ class ColormapDialog(qt.QDialog):
"""
colormap = self.getColormap()
if colormap is not None and self._colormapStoredState is not None:
- if self._colormap()._toDict() != self._colormapStoredState:
+ if colormap != self._colormapStoredState:
self._ignoreColormapChange = True
- colormap._setFromDict(self._colormapStoredState)
+ colormap.setFromColormap(self._colormapStoredState)
self._ignoreColormapChange = False
self._applyColormap()
@@ -740,12 +858,18 @@ class ColormapDialog(qt.QDialog):
:param float positiveMin: The positive minimum of the data
:param float maximum: The maximum of the data
"""
- if minimum is None or positiveMin is None or maximum is None:
+ scale = self._plot.getXAxis().getScale()
+ if scale == Axis.LOGARITHMIC:
+ dataMin, dataMax = positiveMin, maximum
+ else:
+ dataMin, dataMax = minimum, maximum
+
+ if dataMin is None or dataMax is None:
self._dataRange = None
self._plot.remove(legend='Range', kind='histogram')
else:
hist = numpy.array([1])
- bin_edges = numpy.array([minimum, maximum])
+ bin_edges = numpy.array([dataMin, dataMax])
self._plot.addHistogram(hist,
bin_edges,
legend="Range",
@@ -801,7 +925,7 @@ class ColormapDialog(qt.QDialog):
"""
colormap = self.getColormap()
if colormap is not None:
- self._colormapStoredState = colormap._toDict()
+ self._colormapStoredState = colormap.copy()
else:
self._colormapStoredState = None
@@ -830,8 +954,11 @@ class ColormapDialog(qt.QDialog):
self._colormap = colormap
self.storeCurrentState()
- self._updateResetButton()
- self._applyColormap()
+ if self.isVisible():
+ self._applyColormap()
+ else:
+ self._updateResetButton()
+ self._displayLater()
def _updateResetButton(self):
resetButton = self._buttonsNonModal.button(qt.QDialogButtonBox.Reset)
@@ -839,7 +966,7 @@ class ColormapDialog(qt.QDialog):
colormap = self.getColormap()
if colormap is not None and colormap.isEditable():
# can reset only in the case the colormap changed
- rStateEnabled = colormap._toDict() != self._colormapStoredState
+ rStateEnabled = colormap != self._colormapStoredState
resetButton.setEnabled(rStateEnabled)
def _applyColormap(self):
@@ -856,12 +983,8 @@ class ColormapDialog(qt.QDialog):
self._maxValue.setEnabled(False)
else:
self._ignoreColormapChange = True
-
- if colormap.getName() is not None:
- name = colormap.getName()
- self._comboBoxColormap.setCurrentName(name)
- self._comboBoxColormap.setEnabled(self._colormap().isEditable())
-
+ self._comboBoxColormap.setCurrentLut(colormap)
+ self._comboBoxColormap.setEnabled(colormap.isEditable())
assert colormap.getNormalization() in Colormap.NORMALIZATIONS
self._normButtonLinear.setChecked(
colormap.getNormalization() == Colormap.LINEAR)
@@ -870,12 +993,17 @@ class ColormapDialog(qt.QDialog):
vmin = colormap.getVMin()
vmax = colormap.getVMax()
dataRange = colormap.getColormapRange()
- self._normButtonLinear.setEnabled(self._colormap().isEditable())
- self._normButtonLog.setEnabled(self._colormap().isEditable())
+ self._normButtonLinear.setEnabled(colormap.isEditable())
+ self._normButtonLog.setEnabled(colormap.isEditable())
self._minValue.setValue(vmin or dataRange[0], isAuto=vmin is None)
self._maxValue.setValue(vmax or dataRange[1], isAuto=vmax is None)
- self._minValue.setEnabled(self._colormap().isEditable())
- self._maxValue.setEnabled(self._colormap().isEditable())
+ self._minValue.setEnabled(colormap.isEditable())
+ self._maxValue.setEnabled(colormap.isEditable())
+
+ axis = self._plot.getXAxis()
+ scale = axis.LINEAR if colormap.getNormalization() == Colormap.LINEAR else axis.LOGARITHMIC
+ axis.setScale(scale)
+
self._ignoreColormapChange = False
self._plotUpdate()
@@ -908,26 +1036,47 @@ class ColormapDialog(qt.QDialog):
self._plotUpdate()
self._updateResetButton()
- def _updateName(self):
+ def _updateLut(self):
if self._ignoreColormapChange is True:
return
- if self._colormap():
+ colormap = self._colormap()
+ if colormap is not None:
self._ignoreColormapChange = True
- self._colormap().setName(
- self._comboBoxColormap.getCurrentName())
+ name = self._comboBoxColormap.getCurrentName()
+ if name is not None:
+ colormap.setName(name)
+ else:
+ lut = self._comboBoxColormap.getCurrentColors()
+ colormap.setColormapLUT(lut)
self._ignoreColormapChange = False
- def _updateLinearNorm(self, isNormLinear):
+ def _updateNormalization(self, button):
if self._ignoreColormapChange is True:
return
+ if not button.isChecked():
+ return
+
+ if button is self._normButtonLinear:
+ norm = Colormap.LINEAR
+ scale = Axis.LINEAR
+ elif button is self._normButtonLog:
+ norm = Colormap.LOGARITHM
+ scale = Axis.LOGARITHMIC
+ else:
+ assert(False)
- if self._colormap():
+ colormap = self.getColormap()
+ if colormap is not None:
self._ignoreColormapChange = True
- norm = Colormap.LINEAR if isNormLinear else Colormap.LOGARITHM
- self._colormap().setNormalization(norm)
+ colormap.setNormalization(norm)
+ axis = self._plot.getXAxis()
+ axis.setScale(scale)
self._ignoreColormapChange = False
+ self._invalidateHistogram()
+ self._updateMinMaxData()
+
def _minMaxTextEdited(self, text):
"""Handle _minValue and _maxValue textEdited signal"""
self._minMaxWasEdited = True
@@ -975,13 +1124,3 @@ class ColormapDialog(qt.QDialog):
else:
# Use QDialog keyPressEvent
super(ColormapDialog, self).keyPressEvent(event)
-
- def _activeLogNorm(self, isLog):
- if self._ignoreColormapChange is True:
- return
- if self._colormap():
- self._ignoreColormapChange = True
- norm = Colormap.LOGARITHM if isLog is True else Colormap.LINEAR
- self._colormap().setNormalization(norm)
- self._ignoreColormapChange = False
- self._updateMinMaxData()
diff --git a/silx/gui/dialog/DataFileDialog.py b/silx/gui/dialog/DataFileDialog.py
index 7ff1258..d2d76a3 100644
--- a/silx/gui/dialog/DataFileDialog.py
+++ b/silx/gui/dialog/DataFileDialog.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2016 European Synchrotron Radiation Facility
+# 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
@@ -30,16 +30,14 @@ __authors__ = ["V. Valls"]
__license__ = "MIT"
__date__ = "14/02/2018"
+import enum
import logging
from silx.gui import qt
from silx.gui.hdf5.Hdf5Formatter import Hdf5Formatter
import silx.io
from .AbstractDataFileDialog import AbstractDataFileDialog
-from silx.third_party import enum
-try:
- import fabio
-except ImportError:
- fabio = None
+
+import fabio
_logger = logging.getLogger(__name__)
diff --git a/silx/gui/dialog/FileTypeComboBox.py b/silx/gui/dialog/FileTypeComboBox.py
index 07b11cf..92529bc 100644
--- a/silx/gui/dialog/FileTypeComboBox.py
+++ b/silx/gui/dialog/FileTypeComboBox.py
@@ -28,12 +28,9 @@ This module contains utilitaries used by other dialog modules.
__authors__ = ["V. Valls"]
__license__ = "MIT"
-__date__ = "06/02/2018"
+__date__ = "17/01/2019"
-try:
- import fabio
-except ImportError:
- fabio = None
+import fabio
import silx.io
from silx.gui import qt
@@ -82,7 +79,7 @@ class FileTypeComboBox(qt.QComboBox):
def __initItems(self):
self.clear()
- if fabio is not None and self.__fabioUrlSupported:
+ if self.__fabioUrlSupported:
self.__insertFabioFormats()
self.__insertSilxFormats()
self.__insertAllSupported()
@@ -138,21 +135,36 @@ class FileTypeComboBox(qt.QComboBox):
def __insertFabioFormats(self):
formats = fabio.fabioformats.get_classes(reader=True)
+ from fabio import fabioutils
+ if hasattr(fabioutils, "COMPRESSED_EXTENSIONS"):
+ compressedExtensions = fabioutils.COMPRESSED_EXTENSIONS
+ else:
+ # Support for fabio < 0.9
+ compressedExtensions = set(["gz", "bz2"])
+
extensions = []
allExtensions = set([])
+ def extensionsIterator(reader):
+ for extension in reader.DEFAULT_EXTENSIONS:
+ yield "*.%s" % extension
+ for compressedExtension in compressedExtensions:
+ for extension in reader.DEFAULT_EXTENSIONS:
+ yield "*.%s.%s" % (extension, compressedExtension)
+
for reader in formats:
if not hasattr(reader, "DESCRIPTION"):
continue
if not hasattr(reader, "DEFAULT_EXTENSIONS"):
continue
- ext = reader.DEFAULT_EXTENSIONS
- ext = ["*.%s" % e for e in ext]
+ displayext = reader.DEFAULT_EXTENSIONS
+ displayext = ["*.%s" % e for e in displayext]
+ ext = list(extensionsIterator(reader))
allExtensions.update(ext)
if ext == []:
ext = ["*"]
- extensions.append((reader.DESCRIPTION, ext, reader.codec_name()))
+ extensions.append((reader.DESCRIPTION, displayext, ext, reader.codec_name()))
extensions = list(sorted(extensions))
allExtensions = list(sorted(list(allExtensions)))
@@ -162,13 +174,14 @@ class FileTypeComboBox(qt.QComboBox):
self.setItemData(index, Codec(any_fabio=True), role=self.CODEC_ROLE)
for e in extensions:
+ description, displayExt, allExt, _codecName = e
index = self.count()
if len(e[1]) < 10:
- self.addItem("%s%s (%s)" % (self.INDENTATION, e[0], " ".join(e[1])))
+ self.addItem("%s%s (%s)" % (self.INDENTATION, description, " ".join(displayExt)))
else:
- self.addItem(e[0])
- codec = Codec(fabio_codec=e[2])
- self.setItemData(index, e[1], role=self.EXTENSIONS_ROLE)
+ self.addItem("%s%s" % (self.INDENTATION, description))
+ codec = Codec(fabio_codec=_codecName)
+ self.setItemData(index, allExt, role=self.EXTENSIONS_ROLE)
self.setItemData(index, codec, role=self.CODEC_ROLE)
def itemExtensions(self, index):
diff --git a/silx/gui/dialog/ImageFileDialog.py b/silx/gui/dialog/ImageFileDialog.py
index c324071..ef6b472 100644
--- a/silx/gui/dialog/ImageFileDialog.py
+++ b/silx/gui/dialog/ImageFileDialog.py
@@ -36,10 +36,7 @@ from silx.gui import qt
from silx.gui.plot.PlotWidget import PlotWidget
from .AbstractDataFileDialog import AbstractDataFileDialog
import silx.io
-try:
- import fabio
-except ImportError:
- fabio = None
+import fabio
_logger = logging.getLogger(__name__)
diff --git a/silx/gui/dialog/SafeFileSystemModel.py b/silx/gui/dialog/SafeFileSystemModel.py
index 198e089..26954e3 100644
--- a/silx/gui/dialog/SafeFileSystemModel.py
+++ b/silx/gui/dialog/SafeFileSystemModel.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2016 European Synchrotron Radiation Facility
+# 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
@@ -34,8 +34,10 @@ import sys
import os.path
import logging
import weakref
+
+import six
+
from silx.gui import qt
-from silx.third_party import six
from .SafeFileIconProvider import SafeFileIconProvider
_logger = logging.getLogger(__name__)
diff --git a/silx/gui/dialog/test/test_colormapdialog.py b/silx/gui/dialog/test/test_colormapdialog.py
index 6e50193..cbc9de1 100644
--- a/silx/gui/dialog/test/test_colormapdialog.py
+++ b/silx/gui/dialog/test/test_colormapdialog.py
@@ -26,13 +26,11 @@
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "23/05/2018"
+__date__ = "09/11/2018"
-import doctest
import unittest
-from silx.gui.utils.testutils import qWaitForWindowExposedAndActivate
from silx.gui import qt
from silx.gui.dialog import ColormapDialog
from silx.gui.utils.testutils import TestCaseQt
@@ -47,23 +45,6 @@ import numpy.random
_qapp = qt.QApplication.instance() or qt.QApplication([])
-def _tearDownQt(docTest):
- """Tear down to use for test from docstring.
-
- Checks that dialog widget is displayed
- """
- dialogWidget = docTest.globs['dialog']
- qWaitForWindowExposedAndActivate(dialogWidget)
- dialogWidget.setAttribute(qt.Qt.WA_DeleteOnClose)
- dialogWidget.close()
- del dialogWidget
- _qapp.processEvents()
-
-
-cmapDocTestSuite = doctest.DocTestSuite(ColormapDialog, tearDown=_tearDownQt)
-"""Test suite of tests from the module's docstrings."""
-
-
class TestColormapDialog(TestCaseQt, ParametricTestCase):
"""Test the ColormapDialog."""
def setUp(self):
@@ -86,10 +67,12 @@ class TestColormapDialog(TestCaseQt, ParametricTestCase):
editing the same colormap"""
colormapDiag2 = ColormapDialog.ColormapDialog()
colormapDiag2.setColormap(self.colormap)
+ colormapDiag2.show()
self.colormapDiag.setColormap(self.colormap)
+ self.colormapDiag.show()
- self.colormapDiag._comboBoxColormap.setCurrentName('red')
- self.colormapDiag._normButtonLog.setChecked(True)
+ self.colormapDiag._comboBoxColormap._setCurrentName('red')
+ self.colormapDiag._normButtonLog.click()
self.assertTrue(self.colormap.getName() == 'red')
self.assertTrue(self.colormapDiag.getColormap().getName() == 'red')
self.assertTrue(self.colormap.getNormalization() == 'log')
@@ -178,6 +161,7 @@ class TestColormapDialog(TestCaseQt, ParametricTestCase):
def testSetColormapIsCorrect(self):
"""Make sure the interface fir the colormap when set a new colormap"""
self.colormap.setName('red')
+ self.colormapDiag.show()
for norm in (Colormap.NORMALIZATIONS):
for autoscale in (True, False):
if autoscale is True:
@@ -211,7 +195,7 @@ class TestColormapDialog(TestCaseQt, ParametricTestCase):
self.colormapDiag.show()
del self.colormap
self.assertTrue(self.colormapDiag.getColormap() is None)
- self.colormapDiag._comboBoxColormap.setCurrentName('blue')
+ self.colormapDiag._comboBoxColormap._setCurrentName('blue')
def testColormapEditedOutside(self):
"""Make sure the GUI is still up to date if the colormap is modified
@@ -274,7 +258,7 @@ class TestColormapDialog(TestCaseQt, ParametricTestCase):
cb = self.colormapDiag._comboBoxColormap
self.assertTrue(cb.getCurrentName() == colormapName)
cb.setCurrentIndex(0)
- index = cb.findColormap(colormapName)
+ index = cb.findLutName(colormapName)
assert index is not 0 # if 0 then the rest of the test has no sense
cb.setCurrentIndex(index)
self.assertTrue(cb.getCurrentName() == colormapName)
@@ -283,6 +267,7 @@ class TestColormapDialog(TestCaseQt, ParametricTestCase):
"""Test that the colormapDialog is correctly updated when changing the
colormap editable status"""
colormap = Colormap(normalization='linear', vmin=1.0, vmax=10.0)
+ self.colormapDiag.show()
self.colormapDiag.setColormap(colormap)
for editable in (True, False):
with self.subTest(editable=editable):
@@ -302,7 +287,7 @@ class TestColormapDialog(TestCaseQt, ParametricTestCase):
# False
self.colormapDiag.setModal(False)
colormap.setEditable(True)
- self.colormapDiag._normButtonLog.setChecked(True)
+ self.colormapDiag._normButtonLog.click()
resetButton = self.colormapDiag._buttonsNonModal.button(qt.QDialogButtonBox.Reset)
self.assertTrue(resetButton.isEnabled())
colormap.setEditable(False)
@@ -387,7 +372,6 @@ class TestColormapAction(TestCaseQt):
def suite():
test_suite = unittest.TestSuite()
- test_suite.addTest(cmapDocTestSuite)
for testClass in (TestColormapDialog, TestColormapAction):
test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(
testClass))
diff --git a/silx/gui/dialog/test/test_datafiledialog.py b/silx/gui/dialog/test/test_datafiledialog.py
index aff6bc4..06f8961 100644
--- a/silx/gui/dialog/test/test_datafiledialog.py
+++ b/silx/gui/dialog/test/test_datafiledialog.py
@@ -36,16 +36,8 @@ import shutil
import os
import io
import weakref
-
-try:
- import fabio
-except ImportError:
- fabio = None
-try:
- import h5py
-except ImportError:
- h5py = None
-
+import fabio
+import h5py
import silx.io.url
from silx.gui import qt
from silx.gui.utils import testutils
@@ -62,36 +54,33 @@ def setUpModule():
data = numpy.arange(100 * 100)
data.shape = 100, 100
- if fabio is not None:
- filename = _tmpDirectory + "/singleimage.edf"
- image = fabio.edfimage.EdfImage(data=data)
- image.write(filename)
-
- if h5py is not None:
- filename = _tmpDirectory + "/data.h5"
- f = h5py.File(filename, "w")
- f["scalar"] = 10
- f["image"] = data
- f["cube"] = [data, data + 1, data + 2]
- f["complex_image"] = data * 1j
- f["group/image"] = data
- f["nxdata/foo"] = 10
- f["nxdata"].attrs["NX_class"] = u"NXdata"
- f.close()
-
- if h5py is not None:
- directory = os.path.join(_tmpDirectory, "data")
- os.mkdir(directory)
- filename = os.path.join(directory, "data.h5")
- f = h5py.File(filename, "w")
- f["scalar"] = 10
- f["image"] = data
- f["cube"] = [data, data + 1, data + 2]
- f["complex_image"] = data * 1j
- f["group/image"] = data
- f["nxdata/foo"] = 10
- f["nxdata"].attrs["NX_class"] = u"NXdata"
- f.close()
+ filename = _tmpDirectory + "/singleimage.edf"
+ image = fabio.edfimage.EdfImage(data=data)
+ image.write(filename)
+
+ filename = _tmpDirectory + "/data.h5"
+ f = h5py.File(filename, "w")
+ f["scalar"] = 10
+ f["image"] = data
+ f["cube"] = [data, data + 1, data + 2]
+ f["complex_image"] = data * 1j
+ f["group/image"] = data
+ f["nxdata/foo"] = 10
+ f["nxdata"].attrs["NX_class"] = u"NXdata"
+ f.close()
+
+ directory = os.path.join(_tmpDirectory, "data")
+ os.mkdir(directory)
+ filename = os.path.join(directory, "data.h5")
+ f = h5py.File(filename, "w")
+ f["scalar"] = 10
+ f["image"] = data
+ f["cube"] = [data, data + 1, data + 2]
+ f["complex_image"] = data * 1j
+ f["group/image"] = data
+ f["nxdata/foo"] = 10
+ f["nxdata"].attrs["NX_class"] = u"NXdata"
+ f.close()
filename = _tmpDirectory + "/badformat.h5"
with io.open(filename, "wb") as f:
@@ -185,8 +174,6 @@ class TestDataFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.assertEqual(dialog.result(), qt.QDialog.Rejected)
def testSelectRoot_Activate(self):
- if fabio is None:
- self.skipTest("fabio is missing")
dialog = self.createDialog()
browser = testutils.findChildren(dialog, qt.QWidget, name="browser")[0]
dialog.show()
@@ -211,8 +198,6 @@ class TestDataFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.assertEqual(dialog.result(), qt.QDialog.Accepted)
def testSelectGroup_Activate(self):
- if fabio is None:
- self.skipTest("fabio is missing")
dialog = self.createDialog()
browser = testutils.findChildren(dialog, qt.QWidget, name="browser")[0]
dialog.show()
@@ -243,8 +228,6 @@ class TestDataFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.assertEqual(dialog.result(), qt.QDialog.Accepted)
def testSelectDataset_Activate(self):
- if fabio is None:
- self.skipTest("fabio is missing")
dialog = self.createDialog()
browser = testutils.findChildren(dialog, qt.QWidget, name="browser")[0]
dialog.show()
@@ -275,8 +258,6 @@ class TestDataFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.assertEqual(dialog.result(), qt.QDialog.Accepted)
def testClickOnBackToParentTool(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -307,8 +288,6 @@ class TestDataFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.assertSamePath(url.text(), _tmpDirectory)
def testClickOnBackToRootTool(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -332,8 +311,6 @@ class TestDataFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
# self.assertFalse(button.isEnabled())
def testClickOnBackToDirectoryTool(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -361,8 +338,6 @@ class TestDataFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.allowedLeakingWidgets = 1
def testClickOnHistoryTools(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -402,8 +377,6 @@ class TestDataFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.assertSamePath(url.text(), path3)
def testSelectImageFromEdf(self):
- if fabio is None:
- self.skipTest("fabio is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -417,8 +390,6 @@ class TestDataFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.assertSamePath(dialog.selectedUrl(), url.path())
def testSelectImage(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -433,8 +404,6 @@ class TestDataFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.assertSamePath(dialog.selectedUrl(), path)
def testSelectScalar(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -449,8 +418,6 @@ class TestDataFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.assertSamePath(dialog.selectedUrl(), path)
def testSelectGroup(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -467,8 +434,6 @@ class TestDataFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.assertSamePath(uri.data_path(), "/group")
def testSelectRoot(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -485,8 +450,6 @@ class TestDataFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.assertSamePath(uri.data_path(), "/")
def testSelectH5_Activate(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -533,10 +496,6 @@ class TestDataFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
return selectable
def testFilterExtensions(self):
- if h5py is None:
- self.skipTest("h5py is missing")
- if fabio is None:
- self.skipTest("fabio is missing")
dialog = self.createDialog()
browser = testutils.findChildren(dialog, qt.QWidget, name="browser")[0]
dialog.show()
@@ -558,8 +517,6 @@ class TestDataFileDialog_FilterDataset(testutils.TestCaseQt, _UtilsMixin):
return dialog
def testSelectGroup_Activate(self):
- if fabio is None:
- self.skipTest("fabio is missing")
dialog = self.createDialog()
browser = testutils.findChildren(dialog, qt.QWidget, name="browser")[0]
dialog.show()
@@ -585,8 +542,6 @@ class TestDataFileDialog_FilterDataset(testutils.TestCaseQt, _UtilsMixin):
self.assertFalse(button.isEnabled())
def testSelectDataset_Activate(self):
- if fabio is None:
- self.skipTest("fabio is missing")
dialog = self.createDialog()
browser = testutils.findChildren(dialog, qt.QWidget, name="browser")[0]
dialog.show()
@@ -632,8 +587,6 @@ class TestDataFileDialog_FilterGroup(testutils.TestCaseQt, _UtilsMixin):
return dialog
def testSelectGroup_Activate(self):
- if fabio is None:
- self.skipTest("fabio is missing")
dialog = self.createDialog()
browser = testutils.findChildren(dialog, qt.QWidget, name="browser")[0]
dialog.show()
@@ -666,8 +619,6 @@ class TestDataFileDialog_FilterGroup(testutils.TestCaseQt, _UtilsMixin):
self.assertRaises(Exception, dialog.selectedData)
def testSelectDataset_Activate(self):
- if fabio is None:
- self.skipTest("fabio is missing")
dialog = self.createDialog()
browser = testutils.findChildren(dialog, qt.QWidget, name="browser")[0]
dialog.show()
@@ -711,8 +662,6 @@ class TestDataFileDialog_FilterNXdata(testutils.TestCaseQt, _UtilsMixin):
return dialog
def testSelectGroupRefused_Activate(self):
- if fabio is None:
- self.skipTest("fabio is missing")
dialog = self.createDialog()
browser = testutils.findChildren(dialog, qt.QWidget, name="browser")[0]
dialog.show()
@@ -740,8 +689,6 @@ class TestDataFileDialog_FilterNXdata(testutils.TestCaseQt, _UtilsMixin):
self.assertRaises(Exception, dialog.selectedData)
def testSelectNXdataAccepted_Activate(self):
- if fabio is None:
- self.skipTest("fabio is missing")
dialog = self.createDialog()
browser = testutils.findChildren(dialog, qt.QWidget, name="browser")[0]
dialog.show()
@@ -944,8 +891,6 @@ class TestDataFileDialogApi(testutils.TestCaseQt, _UtilsMixin):
self.assertIsNone(dialog._selectedData())
def testBadSubpath(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
self.qWaitForPendingActions(dialog)
@@ -965,8 +910,6 @@ class TestDataFileDialogApi(testutils.TestCaseQt, _UtilsMixin):
self.assertEqual(url.data_path(), "/group")
def testUnsupportedSlicingPath(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
self.qWaitForPendingActions(dialog)
dialog.selectUrl(_tmpDirectory + "/data.h5?path=/cube&slice=0")
diff --git a/silx/gui/dialog/test/test_imagefiledialog.py b/silx/gui/dialog/test/test_imagefiledialog.py
index 66469f3..068dcb9 100644
--- a/silx/gui/dialog/test/test_imagefiledialog.py
+++ b/silx/gui/dialog/test/test_imagefiledialog.py
@@ -36,16 +36,8 @@ import shutil
import os
import io
import weakref
-
-try:
- import fabio
-except ImportError:
- fabio = None
-try:
- import h5py
-except ImportError:
- h5py = None
-
+import fabio
+import h5py
import silx.io.url
from silx.gui import qt
from silx.gui.utils import testutils
@@ -63,42 +55,39 @@ def setUpModule():
data = numpy.arange(100 * 100)
data.shape = 100, 100
- if fabio is not None:
- filename = _tmpDirectory + "/singleimage.edf"
- image = fabio.edfimage.EdfImage(data=data)
- image.write(filename)
-
- filename = _tmpDirectory + "/multiframe.edf"
- image = fabio.edfimage.EdfImage(data=data)
- image.appendFrame(data=data + 1)
- image.appendFrame(data=data + 2)
- image.write(filename)
-
- filename = _tmpDirectory + "/singleimage.msk"
- image = fabio.fit2dmaskimage.Fit2dMaskImage(data=data % 2 == 1)
- image.write(filename)
-
- if h5py is not None:
- filename = _tmpDirectory + "/data.h5"
- f = h5py.File(filename, "w")
- f["scalar"] = 10
- f["image"] = data
- f["cube"] = [data, data + 1, data + 2]
- f["complex_image"] = data * 1j
- f["group/image"] = data
- f.close()
-
- if h5py is not None:
- directory = os.path.join(_tmpDirectory, "data")
- os.mkdir(directory)
- filename = os.path.join(directory, "data.h5")
- f = h5py.File(filename, "w")
- f["scalar"] = 10
- f["image"] = data
- f["cube"] = [data, data + 1, data + 2]
- f["complex_image"] = data * 1j
- f["group/image"] = data
- f.close()
+ filename = _tmpDirectory + "/singleimage.edf"
+ image = fabio.edfimage.EdfImage(data=data)
+ image.write(filename)
+
+ filename = _tmpDirectory + "/multiframe.edf"
+ image = fabio.edfimage.EdfImage(data=data)
+ image.appendFrame(data=data + 1)
+ image.appendFrame(data=data + 2)
+ image.write(filename)
+
+ filename = _tmpDirectory + "/singleimage.msk"
+ image = fabio.fit2dmaskimage.Fit2dMaskImage(data=data % 2 == 1)
+ image.write(filename)
+
+ filename = _tmpDirectory + "/data.h5"
+ f = h5py.File(filename, "w")
+ f["scalar"] = 10
+ f["image"] = data
+ f["cube"] = [data, data + 1, data + 2]
+ f["complex_image"] = data * 1j
+ f["group/image"] = data
+ f.close()
+
+ directory = os.path.join(_tmpDirectory, "data")
+ os.mkdir(directory)
+ filename = os.path.join(directory, "data.h5")
+ f = h5py.File(filename, "w")
+ f["scalar"] = 10
+ f["image"] = data
+ f["cube"] = [data, data + 1, data + 2]
+ f["complex_image"] = data * 1j
+ f["group/image"] = data
+ f.close()
filename = _tmpDirectory + "/badformat.edf"
with io.open(filename, "wb") as f:
@@ -192,8 +181,6 @@ class TestImageFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.assertEqual(dialog.result(), qt.QDialog.Rejected)
def testDisplayAndClickOpen(self):
- if fabio is None:
- self.skipTest("fabio is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -259,8 +246,6 @@ class TestImageFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.assertEqual(dialog.viewMode(), qt.QFileDialog.List)
def testClickOnBackToParentTool(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -291,8 +276,6 @@ class TestImageFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.assertSamePath(url.text(), _tmpDirectory)
def testClickOnBackToRootTool(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -316,8 +299,6 @@ class TestImageFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
# self.assertFalse(button.isEnabled())
def testClickOnBackToDirectoryTool(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -345,8 +326,6 @@ class TestImageFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.allowedLeakingWidgets = 1
def testClickOnHistoryTools(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -386,8 +365,6 @@ class TestImageFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.assertSamePath(url.text(), path3)
def testSelectImageFromEdf(self):
- if fabio is None:
- self.skipTest("fabio is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -402,8 +379,6 @@ class TestImageFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.assertSamePath(dialog.selectedUrl(), path)
def testSelectImageFromEdf_Activate(self):
- if fabio is None:
- self.skipTest("fabio is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -426,8 +401,6 @@ class TestImageFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.assertSamePath(dialog.selectedUrl(), path)
def testSelectFrameFromEdf(self):
- if fabio is None:
- self.skipTest("fabio is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -444,8 +417,6 @@ class TestImageFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.assertSamePath(dialog.selectedUrl(), path)
def testSelectImageFromMsk(self):
- if fabio is None:
- self.skipTest("fabio is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -460,8 +431,6 @@ class TestImageFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.assertSamePath(dialog.selectedUrl(), path)
def testSelectImageFromH5(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -476,8 +445,6 @@ class TestImageFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.assertSamePath(dialog.selectedUrl(), path)
def testSelectH5_Activate(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -498,8 +465,6 @@ class TestImageFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
self.assertSamePath(dialog.selectedUrl(), path)
def testSelectFrameFromH5(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
dialog.show()
self.qWaitForWindowExposed(dialog)
@@ -541,10 +506,6 @@ class TestImageFileDialogInteraction(testutils.TestCaseQt, _UtilsMixin):
return selectable
def testFilterExtensions(self):
- if h5py is None:
- self.skipTest("h5py is missing")
- if fabio is None:
- self.skipTest("fabio is missing")
dialog = self.createDialog()
browser = testutils.findChildren(dialog, qt.QWidget, name="browser")[0]
filters = testutils.findChildren(dialog, qt.QWidget, name="fileTypeCombo")[0]
@@ -745,16 +706,12 @@ class TestImageFileDialogApi(testutils.TestCaseQt, _UtilsMixin):
self.assertSamePath(dialog.directory(), _tmpDirectory)
def testBadDataType(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
dialog.selectUrl(_tmpDirectory + "/data.h5::/complex_image")
self.qWaitForPendingActions(dialog)
self.assertIsNone(dialog._selectedData())
def testBadDataShape(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
dialog.selectUrl(_tmpDirectory + "/data.h5::/unknown")
self.qWaitForPendingActions(dialog)
@@ -773,8 +730,6 @@ class TestImageFileDialogApi(testutils.TestCaseQt, _UtilsMixin):
self.assertIsNone(dialog._selectedData())
def testBadSubpath(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
self.qWaitForPendingActions(dialog)
@@ -794,8 +749,6 @@ class TestImageFileDialogApi(testutils.TestCaseQt, _UtilsMixin):
self.assertEqual(url.data_path(), "/group")
def testBadSlicingPath(self):
- if h5py is None:
- self.skipTest("h5py is missing")
dialog = self.createDialog()
self.qWaitForPendingActions(dialog)
dialog.selectUrl(_tmpDirectory + "/data.h5::/cube[a;45,-90]")
diff --git a/silx/gui/dialog/utils.py b/silx/gui/dialog/utils.py
index 1c16b44..e2334f9 100644
--- a/silx/gui/dialog/utils.py
+++ b/silx/gui/dialog/utils.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2016 European Synchrotron Radiation Facility
+# 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
@@ -33,8 +33,10 @@ __date__ = "25/10/2017"
import os
import sys
import types
+
+import six
+
from silx.gui import qt
-from silx.third_party import six
def samefile(path1, path2):