# Source code for taurus.qt.qtgui.extra_nexus.taurusnexuswidget

    #!/usr/bin/env python

    # ###########################################################################
    #
    # This file is part of Taurus
    #
    # http://taurus-scada.org
    #
    # Copyright 2011 CELLS / ALBA Synchrotron, Bellaterra, Spain
    #
    # Taurus is free software: you can redistribute it and/or modify
    # it under the terms of the GNU Lesser General Public License as published by
    # the Free Software Foundation, either version 3 of the License, or
    # (at your option) any later version.
    #
    # Taurus is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    # GNU Lesser General Public License for more details.
    #
    # You should have received a copy of the GNU Lesser General Public License
    # along with Taurus.  If not, see <http://www.gnu.org/licenses/>.
    #
    # ###########################################################################

    """
    nexusWidget.py:
    """

    import numpy
    import posixpath
    from functools import partial

    from taurus.external.qt import Qt, compat
    from PyMca5.PyMcaGui.io.hdf5 import HDF5Widget, HDF5Info, HDF5DatasetTable

    from taurus.qt.qtgui.container import TaurusWidget
    from taurus.core.util.log import deprecation_decorator

    @deprecation_decorator(rel="5.0.0")
    class NeXusInfoWidget(Qt.QTabWidget):
        """deprecated"""

        def setInfoDict(self, info):
            pass

    class TaurusNeXusBrowser(TaurusWidget):
        """A Browser for nexus files with optional preview. Based on PyMCA's
        HDF5Widget"""

        def __init__(self, *args, **kwargs):
            TaurusWidget.__init__(self, *args)

            fileModel = kwargs.get("fileModel", None)
            if fileModel is None:
                fileModel = HDF5Widget.FileModel()
            self.__fileModel = fileModel

            self.treeWidget = HDF5Widget.HDF5Widget(self.__fileModel)
            self.treeWidget.setSizePolicy(
                Qt.QSizePolicy(Qt.QSizePolicy.Expanding, Qt.QSizePolicy.Expanding)
            )
            #        self.infoWidget = HDF5Info.HDF5InfoWidget()
            self.__previewStack = Qt.QStackedWidget()
            self.__currentPreview = None

            # layout
            self.__splitter = Qt.QSplitter()
            self.__splitter.setOrientation(Qt.Qt.Vertical)
            self.__splitter.addWidget(self.treeWidget)
            #        self.__splitter.addWidget(self.infoWidget)
            self.__splitter.addWidget(self.__previewStack)
            self.setLayout(Qt.QVBoxLayout())
            self.layout().addWidget(self.__splitter)

            # Actions
            self.setContextMenuPolicy(Qt.Qt.ActionsContextMenu)
            self.openFileAction = Qt.QAction(
                Qt.QIcon.fromTheme("document-open"), "Open Data File...", self
            )
            self.togglePreviewAction = Qt.QAction(
                Qt.QIcon("actions:view.svg"), "Show/Hide preview", self
            )
            self.togglePreviewAction.setCheckable(True)
            self.togglePreviewAction.setChecked(True)
            self.addActions([self.openFileAction, self.togglePreviewAction])

            # Toolbar
            self._toolbar = Qt.QToolBar("NeXus browser toolbar")
            self._toolbar.setIconSize(Qt.QSize(16, 16))
            self._toolbar.setFloatable(False)
            self._toolbar.addActions(
                [self.openFileAction, self.togglePreviewAction]
            )
            self.layout().setMenuBar(self._toolbar)

            # connections
            self.__fileModel.sigFileAppended.connect(self.treeWidget.fileAppended)
            self.treeWidget.sigHDF5WidgetSignal.connect(self.onHDF5WidgetSignal)
            self.openFileAction.triggered.connect(
                partial(self.openFile, fname=None)
            )
            self.togglePreviewAction.toggled.connect(
                self.__previewStack.setVisible
            )

            # configuration
            self.registerConfigProperty(
                self.togglePreviewAction.isChecked,
                self.togglePreviewAction.setChecked,
                "showPreview",
            )

        @Qt.pyqtSlot()
        @Qt.pyqtSlot("QString")
        def openFile(self, fname=None):
            if fname is None:
                fname, _ = compat.getOpenFileName(self, "Choose NeXus File", "")
            if fname:
                self.__nexusFile = self.__fileModel.openFile(fname)

        def onHDF5WidgetSignal(self, ddict):
            self.__previewStack.removeWidget(self.__currentPreview)
            self.__currentPreview = self.neXusPreviewWidgetFactory(ddict)
            self.__previewStack.addWidget(self.__currentPreview)
            self.__previewStack.setCurrentWidget(self.__currentPreview)

        def neXusPreviewWidgetFactory(self, ddict):
            """returns a widget showing a preview of a node in a NeXus file"""
            # @todo: check if this is the root group and it has a valid nexus
            #        data directory, in which case the default plot should be
            #        returned
            node = ddict["name"]
            data = self.__nexusFile[node]
            if hasattr(data, "shape") and len(data.shape) == 1:
                if isinstance(
                    data[0], (numpy.floating, numpy.integer, int, float)
                ):
                    try:
                        import pyqtgraph as pg

                        w = pg.PlotWidget()
                        w.plot(data)
                    except ImportError:
                        w = HDF5DatasetTable.HDF5DatasetTable()
                        w.setDataset(data)
                else:
                    w = HDF5DatasetTable.HDF5DatasetTable()
                    w.setDataset(data)
            else:
                info = HDF5Info.getInfo(self.__nexusFile, ddict["name"])
                w = HDF5Info.HDF5InfoWidget()
                w.setInfoDict(info)
            return w

        def neXusWidget(self):
            return self.treeWidget

        def findNodeIndex(self, filename, nodename):
            nexus_widget = self.neXusWidget()
            file_model = nexus_widget.model()

            for node in file_model.rootItem.children:
                if node.file.filename == filename:
                    file_node = node
                    break
            else:
                raise Exception("Could not find file %s" % filename)

            index = file_model.index(file_node.row, 0, Qt.QModelIndex())

            node_parts = nodename.split(posixpath.sep)
            while node_parts:
                name = posixpath.basename(node_parts.pop(0))
                for child in node.children:
                    child_name = posixpath.basename(child.name)
                    if child_name == name:
                        node = child
                        index = file_model.index(node.row, 0, index)
                        break
                else:
                    raise Exception(
                        "Could not find node %s in %s" % (name, filename)
                    )
            return index

        def setCurrentNode(self, filename, nodename):
            index = self.findNodeIndex(filename, nodename)
            self.setCurrentIndex(index)

        @classmethod
        def getQtDesignerPluginInfo(cls):
            ret = TaurusWidget.getQtDesignerPluginInfo()
            ret["module"] = "taurus.qt.qtgui.extra_nexus"
            ret["icon"] = "designer:listview.png"
            ret["container"] = False
            ret["group"] = "Taurus Views"
            return ret

        def closeEvent(self, event):
            """Close HDF5 files"""
            try:
                self.neXusWidget().model().close()
            except Exception:
                self.warning("Exception received while trying to close HDF5 files")
                self.traceback()
            TaurusWidget.closeEvent(self, event)

    if __name__ == "__main__":
        import sys
        from taurus.qt.qtgui.application import TaurusApplication

        if len(sys.argv) > 1:
            fname = sys.argv[1]
        else:
            fname = None

        if len(sys.argv) > 2:
            path = sys.argv[2]
        else:
            path = None

        app = TaurusApplication(sys.argv, cmd_line_parser=None)
        w = TaurusNeXusBrowser()
        w.openFile(fname)
        w.show()
        if path is not None:
            index = w.findNodeIndex(fname, path)
            nexus_widget = w.neXusWidget()
            nexus_widget.setCurrentIndex(index)
            while index.row() != -1 and index.column() != -1:
                nexus_widget.expand(index)
                index = index.parent()
        sys.exit(app.exec_())