# Source code for taurus.qt.qtgui.tree.taurusdbtree

    #!/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/>.
    #
    # ###########################################################################

    """This module provides widgets that display the database in a tree format
    """

    # todo: tango-centric!!

    from taurus.external.qt import Qt
    from taurus.core.taurusbasetypes import TaurusElementType
    from taurus.core.taurusauthority import TaurusAuthority
    from taurus.qt.qtcore.model import (
        TaurusDbBaseModel,
        TaurusDbDeviceModel,
        TaurusDbDeviceClassProxyModel,
        TaurusDbDeviceClassModel,
        TaurusDbDeviceProxyModel,
        TaurusDbPlainDeviceModel,
        TaurusDbServerModel,
        TaurusDbServerProxyModel,
        TaurusDbSimpleDeviceModel,
    )
    from taurus.qt.qtgui.base import TaurusBaseWidget
    from taurus.qt.qtgui.icon import getElementTypeIcon, getElementTypeIconName
    from .taurustree import TaurusBaseTreeWidget

    __docformat__ = "restructuredtext"

    class TaurusDbTreeWidget(TaurusBaseTreeWidget):
        """A class:`taurus.qt.qtgui.tree.TaurusBaseTreeWidget` that connects to a
        :class:`taurus.core.taurusauthority.TaurusAuthority` model. It can show the
        list of database elements in four different perspectives:

        - device : a three level hierarchy of devices (domain/family/name)
        - server : a server based perspective
        - class : a class based perspective

        Filters can be inserted into this widget to restrict the tree nodes that
        are seen.
        """

        KnownPerspectives = {
            TaurusElementType.Device: {
                "label": "By device",
                "icon": getElementTypeIconName(TaurusElementType.Device),
                "tooltip": "View by device tree",
                "model": [
                    TaurusDbDeviceProxyModel,
                    TaurusDbDeviceModel,
                ],
            },
            "PlainDevice": {
                "label": "By plain device",
                "icon": getElementTypeIconName(TaurusElementType.Device),
                "tooltip": (
                    "View by plain device tree (it may take a long time "
                    + "if there are problems with the exported devices)"
                ),
                "model": [
                    TaurusDbDeviceProxyModel,
                    TaurusDbPlainDeviceModel,
                ],
            },
            TaurusElementType.Server: {
                "label": "By server",
                "icon": getElementTypeIconName(TaurusElementType.Server),
                "tooltip": "View by server tree",
                "model": [
                    TaurusDbServerProxyModel,
                    TaurusDbServerModel,
                ],
            },
            TaurusElementType.DeviceClass: {
                "label": "By class",
                "icon": getElementTypeIconName(TaurusElementType.DeviceClass),
                "tooltip": "View by class tree",
                "model": [
                    TaurusDbDeviceClassProxyModel,
                    TaurusDbDeviceClassModel,
                ],
            },
        }

        DftPerspective = TaurusElementType.Device

        def getModelClass(self, **kwargs):
            return TaurusAuthority

        def sizeHint(self):
            return Qt.QSize(1024, 512)

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

    class _TaurusTreePanel(Qt.QWidget, TaurusBaseWidget):
        """A demonstration panel to show how
        :class:`taurus.qt.qtcore.TaurusDbBaseModel` models can interact with
        several model view widgets like QTreeView, QTableView, QListView and
        QComboBox"""

        def __init__(self, parent=None, designMode=False):
            """doc please!"""
            name = self.__class__.__name__
            self.call__init__wo_kw(Qt.QWidget, parent)
            self.call__init__(TaurusBaseWidget, name, designMode=designMode)
            self.init(designMode)

        def init(self, designMode):
            lyt = Qt.QGridLayout()
            lyt.setContentsMargins(0, 0, 0, 0)
            self.setLayout(lyt)

            main_panel = Qt.QTabWidget()
            self._device_tree_view = TaurusDbTreeWidget(
                perspective=TaurusElementType.Device
            )
            self._device_table_view = Qt.QTableView()
            self._device_table_view.setModel(TaurusDbBaseModel())
            self._device_list_view = Qt.QListView()
            self._device_list_view.setModel(TaurusDbSimpleDeviceModel())
            self._server_tree_view = TaurusDbTreeWidget(
                perspective=TaurusElementType.Server
            )
            self._class_tree_view = TaurusDbTreeWidget(
                perspective=TaurusElementType.DeviceClass
            )

            self._device_combo_view = Qt.QWidget()
            combo_form = Qt.QFormLayout()
            self._device_combo_view.setLayout(combo_form)

            self._combo_dev_tree_widget = TaurusDbTreeWidget(
                perspective=TaurusElementType.Device
            )
            qmodel = self._combo_dev_tree_widget.getQModel()
            qmodel.setSelectables([TaurusElementType.Member])
            device_combo = Qt.QComboBox()
            device_combo.setModel(qmodel)
            device_combo.setMaxVisibleItems(20)
            device_combo.setView(self._combo_dev_tree_widget.treeView())
            combo_form.addRow(
                "Device selector (by device hierarchy):", device_combo
            )

            self._combo_attr_tree_widget = TaurusDbTreeWidget(
                perspective=TaurusElementType.Device
            )
            qmodel = self._combo_attr_tree_widget.getQModel()
            device_combo = Qt.QComboBox()
            device_combo.setModel(qmodel)
            device_combo.setMaxVisibleItems(20)
            device_combo.setView(self._combo_attr_tree_widget.treeView())
            combo_form.addRow(
                "Attribute selector (by device hierarchy):", device_combo
            )

            self._combo_dev_table_view = Qt.QTableView()
            self._combo_dev_table_view.setModel(TaurusDbBaseModel())
            qmodel = self._combo_dev_table_view.model()
            qmodel.setSelectables([TaurusElementType.Device])
            device_combo = Qt.QComboBox()
            device_combo.setModel(qmodel)
            device_combo.setMaxVisibleItems(20)
            device_combo.setView(self._combo_dev_table_view)
            combo_form.addRow("Device selector (by plain device):", device_combo)

            main_panel.addTab(self._device_tree_view, "Device (Tree View)")
            main_panel.addTab(self._device_table_view, "Device (Table View)")
            main_panel.addTab(self._device_list_view, "Device (List View)")
            main_panel.addTab(self._server_tree_view, "Server (Tree View)")
            main_panel.addTab(self._class_tree_view, "Class (Tree View)")
            main_panel.addTab(self._device_combo_view, "ComboBox Views")

            lyt.addWidget(main_panel, 1, 0)

            self._main_panel = main_panel

        def deviceTreeWidget(self):
            return self._device_tree_view

        def deviceTableWidget(self):
            return self._device_table_view

        def deviceListWidget(self):
            return self._device_list_view

        def serverTreeWidget(self):
            return self._server_tree_view

        def classTreeWidget(self):
            return self._class_tree_view

        def sizeHint(self):
            return Qt.QSize(1024, 512)

        def _updateTreeModels(self):
            db_name, db = self.getModel(), self.getModelObj()

            self._device_tree_view.setModel(db_name)

            model = self._device_table_view.model()
            if model is not None:
                model.setDataSource(db)

            model = self._device_list_view.model()
            if model is not None:
                model.setDataSource(db)

            self._server_tree_view.setModel(db_name)
            self._class_tree_view.setModel(db_name)
            self._combo_dev_tree_widget.setModel(db_name)
            self._combo_attr_tree_widget.setModel(db_name)

            model = self._combo_dev_table_view.model()
            if model is not None:
                model.setDataSource(db)

        def refresh(self):
            db = self.getModelObj()
            if db is None:
                return
            db.refreshCache()
            self._device_tree_view.refresh()
            self._device_table_view.model().refresh()
            self._device_list_view.model().refresh()
            self._server_tree_view.refresh()
            self._class_tree_view.refresh()

        def goIntoTree(self):
            index = self._device_tree_view.currentIndex()
            if index is None:
                return
            # index_parent = index.parent()
            # if index_parent is None:
            #    return
            self._device_tree_view.setRootIndex(index)

        def goUpTree(self):
            index = self._device_tree_view.rootIndex()
            if index is None:
                return
            index_parent = index.parent()
            if index_parent is None:
                return
            self._device_tree_view.setRootIndex(index_parent)

        # -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
        # TaurusBaseWidget overwriting
        # -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~

        def getModelClass(self, **kwargs):
            return TaurusAuthority

        @Qt.pyqtSlot("QString")
        def setModel(self, model, **kwargs):
            """Sets/unsets the model name for this component

            :param model: the new model name
            :type model: str
            """
            super(_TaurusTreePanel, self).setModel(model)
            self._updateTreeModels()

        # -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
        # QT property definition
        # -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~

        #: This property holds the unique URI string representing the model name
        #: with which this widget will get its data from. The convention used for
        #: the string can be found :ref:`here <model-concept>`.
        #:
        #: **Access functions:**
        #:
        #:     * :meth:`TaurusBaseWidget.getModel`
        #:     * :meth:`TaurusBaseWidget.setModel`
        #:     * :meth:`TaurusBaseWidget.resetModel`
        #:
        #: .. seealso:: :ref:`model-concept`
        model = Qt.pyqtProperty(
            "QString",
            TaurusBaseWidget.getModel,
            TaurusBaseWidget.setModel,
            TaurusBaseWidget.resetModel,
        )

    def main_TaurusTreePanel(host):
        w = _TaurusTreePanel()
        w.setWindowIcon(getElementTypeIcon(TaurusElementType.Device))
        w.setWindowTitle("A Taurus Tree Example")
        w.setModel(host)
        w.show()
        return w

    def main_TaurusDbTreeWidget(host, perspective=TaurusElementType.Device):
        w = TaurusDbTreeWidget(perspective=perspective)
        w.setWindowIcon(getElementTypeIcon(perspective))
        w.setWindowTitle("A Taurus Tree Example")
        w.setModel(host)
        w.show()
        return w

    def demo():
        """DB panels"""
        import taurus

        db = taurus.Authority()
        host = db.getNormalName()
        w = main_TaurusTreePanel(host)
        # w = main_TaurusDbTreeWidget(host, TaurusElementType.Device)

        return w

    def main():
        import sys
        import taurus.qt.qtgui.application

        Application = taurus.qt.qtgui.application.TaurusApplication

        app = Application.instance()
        owns_app = app is None

        if owns_app:
            app = Application(
                app_name="DB model demo",
                app_version="1.0",
                org_domain="Taurus",
                org_name="Tango community",
            )
        w = demo()
        w.show()

        if owns_app:
            sys.exit(app.exec_())
        else:
            return w

    if __name__ == "__main__":
        main()