# Source code for taurus.qt.qtgui.container.qcontainer

    #!/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 basic pure Qt container widgets
    """

    import json

    from taurus.external.qt import Qt
    from taurus.qt.qtgui.icon import getStandardIcon

    __docformat__ = "restructuredtext"

    _TitleBarStyleExpanded = """.QFrame {{
    border-width: 0px;
    border-style: solid;
    border-color: {stop_color};
    border-top-left-radius: {border_radius};
    border-top-right-radius: {border_radius};
    border-bottom-left-radius: 0px;
    border-bottom-right-radius: 0px;
    background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                      stop: 0 {start_color}, stop: 1 {stop_color});
    }}"""

    _TitleBarStyleCollapsed = """.QFrame {{
    border-width: 0px;
    border-style: solid;
    border-color: {stop_color};
    border-top-left-radius: {border_radius};
    border-top-right-radius: {border_radius};
    border-bottom-left-radius: {border_radius};
    border-bottom-right-radius: {border_radius};
    background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                      stop: 0 {start_color}, stop: 1 {stop_color});
    }}"""

    _TitleLabelStyle = """.QLabel {{ color : {font_color}; }}"""

    _ContentBarStyleWithTitle = """ContentFrame {{
    border-top-width: 0px;
    border-left-width: 1px;
    border-right-width: 1px;
    border-bottom-width: 1px;
    border-style: solid;
    border-color: {border_color};
    border-top-left-radius: 0px;
    border-top-right-radius: 0px;
    border-bottom-left-radius: {border_radius};
    border-bottom-right-radius: {border_radius};
    background-color: qlineargradient(x1: 0, y1: 0, x2: 1.0, y2: 1.0,
                                      stop: 0 {start_color}, stop: 1 {stop_color});
    /*
      background-position: center center;
    */
    }}"""

    _ContentBarStyleWithoutTitle = """ContentFrame {{
    border-width: 1px;
    border-style: solid;
    border-color: {border_color};
    border-top-left-radius: {border_radius};
    border-top-right-radius: {border_radius};
    border-bottom-left-radius: {border_radius};
    border-bottom-right-radius: {border_radius};
    background-color: qlineargradient(x1: 0, y1: 0, x2: 1.0, y2: 1.0,
                                      stop: 0 {start_color}, stop: 1 {stop_color});
    /*
      background-position: center center;
    */
    }}"""

    # Empty content QFrame to avoid frame style to be propagated
    # to child QFrame widgets

    class ContentFrame(Qt.QFrame):
        pass

    class QGroupWidget(Qt.QWidget):
        """An expandable/collapsible composite widget"""

        DefaultTitleBarVisible = True
        DefaultTitleBarHeight = 16
        DefaultTitleBarStyle = {
            "start_color": "rgb(60, 150, 255)",
            "stop_color": "rgb(0, 65, 200)",
            "font_color": "white",
            "border_radius": "5px",
        }

        DefaultContentVisible = True
        DefaultContentStyle = {
            "start_color": "rgb(224, 224, 224)",
            "stop_color": "rgb(255, 255, 255)",
            "border_color": "rgb(0, 85, 227)",
            "border_radius": "5px",
        }

        def __init__(self, parent=None, designMode=False):
            Qt.QWidget.__init__(self, parent)
            self._titleVisible = self.DefaultTitleBarVisible
            self._contentVisible = self.DefaultContentVisible
            self._titleBarStyle = self.DefaultTitleBarStyle
            self._contentStyle = self.DefaultContentStyle
            self.__init()
            self._updateStyle()
            self.resetContentVisible()
            self.resetTitleHeight()
            self.resetTitleVisible()

        def __init(self):
            panelLayout = Qt.QVBoxLayout()
            panelLayout.setSpacing(0)
            panelLayout.setContentsMargins(0, 0, 0, 0)
            self.setLayout(panelLayout)

            self._titleBar = titleBar = Qt.QFrame()
            panelLayout.addWidget(titleBar, 0)

            lyt = Qt.QHBoxLayout()
            lyt.setContentsMargins(2, 2, 2, 2)
            lyt.setSpacing(2)
            self._titleBar.setLayout(lyt)

            self._titleButton = Qt.QToolButton()
            self._titleButton.setStyleSheet("border: 0px")
            styleOption = Qt.QStyleOption()
            styleOption.initFrom(self._titleButton)
            style = Qt.QApplication.style()
            icon = style.standardIcon(
                Qt.QStyle.SP_DesktopIcon, styleOption, self._titleButton
            )
            self._titleButton.setIcon(icon)
            self._titleLabel = Qt.QLabel()
            self._upDownButton = Qt.QToolButton()
            self._upDownButton.setStyleSheet("border: 0px")
            self._upDownButton.clicked.connect(self.switchContentVisible)
            lyt.addWidget(self._titleButton, 0)
            lyt.addWidget(self._titleLabel, 1)
            lyt.addWidget(self._upDownButton, 0)

            self._content = content = ContentFrame()
            lyt = Qt.QHBoxLayout()
            lyt.setContentsMargins(0, 0, 0, 0)
            content.setLayout(lyt)
            panelLayout.addWidget(content, 1)

        def _updateStyle(self):
            """Internal method that updates the style"""
            if self.contentVisible:
                ts = _TitleBarStyleExpanded
            else:
                ts = _TitleBarStyleCollapsed
            fullTitleBarStyle = ts.format(**self._titleBarStyle)
            fullTitleLabelStyle = _TitleLabelStyle.format(**self._titleBarStyle)
            if self.titleVisible:
                contentStyleTemplate = _ContentBarStyleWithTitle
            else:
                contentStyleTemplate = _ContentBarStyleWithoutTitle

            contentStyle = self._contentStyle.copy()
            contentStyle["border_color"] = self._titleBarStyle["stop_color"]
            fullContentStyle = contentStyleTemplate.format(**contentStyle)
            self._titleBar.setStyleSheet(fullTitleBarStyle)
            self._titleLabel.setStyleSheet(fullTitleLabelStyle)
            self._content.setStyleSheet(fullContentStyle)

        @classmethod
        def getQtDesignerPluginInfo(cls):
            return {
                "module": "taurus.qt.qtgui.container",
                "group": "Taurus Containers",
                "icon": "designer:groupwidget.png",
                "container": True,
            }

        def content(self):
            """Returns the contents widget

            :return: the content widget
            :rtype: Qt.QFrame
            """
            return self._content

        def titleBar(self):
            """Returns the title bar widget

            :return: the title bar widget
            :rtype: Qt.QFrame
            """
            return self._titleBar

        def titleButton(self):
            """Returns the title button widget

            :return: the title button widget
            :rtype: Qt.QToolButton
            """
            return self._titleButton

        def collapseButton(self):
            """Returns the collapse button widget

            :return: the collapse button widget
            :rtype: Qt.QToolButton
            """
            return self._upDownButton

        def setTitle(self, title):
            """Sets this widget's title

            :param title: the new widget title
            :type title: str
            """
            self._titleLabel.setText(title)

        def getTitle(self):
            """Returns this widget's title

            :return: this widget's title
            :rtype: str
            """
            return self._titleLabel.text()

        def setTitleIcon(self, icon):
            """Sets this widget's title icon

            :param icon: the new widget title icon
            :type icon: Qt.QIcon
            """
            self._titleButton.setIcon(icon)

        def getTitleIcon(self):
            """Returns this widget's title icon

            :return: this widget's title icon
            :rtype: Qt.QIcon
            """
            return self._titleButton.icon()

        def switchContentVisible(self):
            """Switches this widget's contents visibility"""
            self.setContentVisible(not self.isContentVisible())

        def isContentVisible(self):
            """Returns this widget's contents visibility

            :return: this widget's contents visibility
            :rtype: bool
            """
            return self._contentVisible

        def resetContentVisible(self):
            """Resets this widget's contents visibility"""
            self.setContentVisible(self.DefaultContentVisible)

        def setContentVisible(self, show):
            """Sets this widget's contents visibility

            :param show: the new widget contents visibility
            :type show: bool
            """
            self._contentVisible = show
            self._updateStyle()

            # if show: icon_name = "go-previous"
            # else: icon_name = "go-down"
            # icon = Qt.QIcon.fromTheme(icon_name)

            if show:
                icon_name = Qt.QStyle.SP_TitleBarShadeButton
            else:
                icon_name = Qt.QStyle.SP_TitleBarUnshadeButton
            icon = getStandardIcon(icon_name, self._upDownButton)

            self._upDownButton.setIcon(icon)
            self._content.setVisible(show)
            self.adjustSize()

        def isTitleVisible(self):
            """Returns this widget's title visibility

            :return: this widget's title visibility
            :rtype: bool
            """
            return self._titleVisible

        def resetTitleVisible(self):
            """Resets this widget's title visibility"""
            self.setTitleVisible(self.DefaultTitleBarVisible)

        def setTitleVisible(self, show):
            """Sets this widget's title visibility

            :param icon: the new widget title visibility
            :type icon: bool
            """
            self._titleVisible = show
            self._titleBar.setVisible(show)
            self._updateStyle()

        def getTitleHeight(self):
            """Returns this widget's title height

            :return: this widget's title height
            :rtype: bool
            """
            return self.titleButton().iconSize().height()

        def setTitleHeight(self, h):
            """Sets this widget's title height

            :param icon: the new widget title height
            :type icon: bool
            """
            s = Qt.QSize(h, h)
            self.titleButton().setIconSize(s)
            self.collapseButton().setIconSize(s)

        def resetTitleHeight(self):
            """Resets this widget's title height"""
            self.setTitleHeight(self.DefaultTitleBarHeight)

        def getTitleStyle(self):
            """Returns this widget's title style

            :return: this widget's title style
            :rtype: dict
            """
            return self._titleBarStyle

        def setTitleStyle(self, style_map):
            """Sets this widget's title style
            Used key/values for style_map:
            - 'start_color'  : brush (Ex.: '#E0E0E0', 'rgb(0,0,0)', 'white')
            - 'stop_color'   : brush (Ex.: '#E0E0E0', 'rgb(0,0,0)', 'white')
            - 'font_color'   : brush (Ex.: '#E0E0E0', 'rgb(0,0,0)', 'white')
            - 'border_radius': radius (Ex.: '5px', '5px,2px')

            :param style_map: the new widget title style
            :type style_map: dict
            """
            style = self.DefaultTitleBarStyle.copy()
            style.update(style_map)
            self._titleBarStyle = style
            self._updateStyle()

        def resetTitleStyle(self):
            """Resets this widget's title style"""
            self.setTitleStyle({})

        def getTitleStyleStr(self):
            """Returns this widget's title style

            :return: this widget's title style
            :rtype: dict
            """
            return json.dumps(self._titleBarStyle)

        def setTitleStyleStr(self, style_map):
            """Sets this widget's title style
            Used key/values for style_map:
            - 'start_color'  : brush (Ex.: '#E0E0E0', 'rgb(0,0,0)', 'white')
            - 'stop_color'   : brush (Ex.: '#E0E0E0', 'rgb(0,0,0)', 'white')
            - 'font_color'   : brush (Ex.: '#E0E0E0', 'rgb(0,0,0)', 'white')
            - 'border_radius': radius (Ex.: '5px', '5px,2px')

            :param style_map: the new widget title style
            :type style_map: dict
            """
            style_map = json.loads(str(style_map))
            self.setTitleStyle(style_map)

        def resetTitleStyleStr(self):
            """Resets this widget's title style"""
            self.resetTitleStyle()

        def getContentStyle(self):
            """Returns this widget's content style

            :return: this widget's content style
            :rtype: dict
            """
            return self._contentStyle

        def setContentStyle(self, style_map):
            """Sets this widget's content style
            Used key/values for style_map:
            - 'start_color'  : brush (Ex.: '#E0E0E0', 'rgb(0,0,0)', 'white')
            - 'stop_color'   : brush (Ex.: '#E0E0E0', 'rgb(0,0,0)', 'white')

            :param style_map: the new widget content style
            :type style_map: dict
            """
            style = self.DefaultContentStyle.copy()
            style.update(style_map)
            self._contentStyle = style
            self._updateStyle()

        def resetContentStyle(self):
            """Resets this widget's content style"""
            self.setContentStyle({})

        def getContentStyleStr(self):
            """Returns this widget's content style

            :return: this widget's content style
            :rtype: dict
            """
            return json.dumps(self._contentStyle)

        def setContentStyleStr(self, style_map):
            """Sets this widget's content style
            Used key/values for style_map:
            - 'start_color'  : brush (Ex.: '#E0E0E0', 'rgb(0,0,0)', 'white')
            - 'stop_color'   : brush (Ex.: '#E0E0E0', 'rgb(0,0,0)', 'white')

            :param style_map: the new widget content style
            :type style_map: dict
            """
            style_map = json.loads(str(style_map))
            self.setContentStyle(style_map)

        def resetContentStyleStr(self):
            """Resets this widget's content style"""
            self.resetContentStyle()

        #: This property contains the widget's title
        #:
        #: **Access functions:**
        #:
        #:     * :meth:`getTitle`
        #:     * :meth:`setTitle`
        title = Qt.pyqtProperty("QString", getTitle, setTitle)

        #: This property contains the widget's title icon
        #:
        #: **Access functions:**
        #:
        #:     * :meth:`getTitleIcon`
        #:     * :meth:`setTitleIcon`
        titleIcon = Qt.pyqtProperty("QIcon", getTitleIcon, setTitleIcon)

        #: This property contains the widget's title height
        #:
        #: **Access functions:**
        #:
        #:     * :meth:`getTitleHeight`
        #:     * :meth:`setTitleHeight`
        #:     * :meth:`resetTitleHeight`
        titleHeight = Qt.pyqtProperty(
            "int", getTitleHeight, setTitleHeight, resetTitleHeight
        )

        #: This property contains the widget's title visibility
        #:
        #: **Access functions:**
        #:
        #:     * :meth:`isTitleVisible`
        #:     * :meth:`setTitleVisible`
        titleVisible = Qt.pyqtProperty("bool", isTitleVisible, setTitleVisible)

        #: This property contains the widget's content's visibility
        #:
        #: **Access functions:**
        #:
        #:     * :meth:`isContentVisible`
        #:     * :meth:`setContentVisible`
        #:     * :meth:`resetContentVisible`
        contentVisible = Qt.pyqtProperty(
            "bool", isContentVisible, setContentVisible, resetContentVisible
        )

        # : This property contains the widget's content style
        # : The style must be a json dictionary
        # :
        # : **Access functions:**
        # :
        # :     * :meth:`getContentStyleStr`
        # :     * :meth:`setContentStyleStr`
        # :     * :meth:`resetContentStyleStr`
        contentStyle = Qt.pyqtProperty(
            "QString",
            getContentStyleStr,
            setContentStyleStr,
            resetContentStyleStr,
            doc="The style must be a json dictionary",
        )

        # : This property contains the widget's title style
        # : The style must be a json dictionary
        # :
        # : **Access functions:**
        # :
        # :     * :meth:`getTitleStyleStr`
        # :     * :meth:`setTitleStyleStr`
        # :     * :meth:`resetTitleStyleStr`
        titleStyle = Qt.pyqtProperty(
            "QString",
            getTitleStyleStr,
            setTitleStyleStr,
            resetTitleStyleStr,
            doc="The style must be a json dictionary",
        )

    def demo():
        "QGroup Widget"
        w = Qt.QWidget()
        lyt = Qt.QVBoxLayout()
        w.setLayout(lyt)

        panel = QGroupWidget()
        panel.title = "Database"
        contentLayout = Qt.QFormLayout()
        panel.content().setLayout(contentLayout)
        contentLayout.addRow("&Host", Qt.QLineEdit())
        contentLayout.addRow("&Port", Qt.QLineEdit())
        lyt.addWidget(panel, 0)

        panel = QGroupWidget()
        panel.title = "Hello world"
        panel.titleIcon = Qt.QIcon.fromTheme("video-x-generic")
        panel.setTitleStyle(
            {
                "start_color": "rgb(255, 60, 60)",
                "stop_color": "rgb(200, 0, 0)",
                "font_color": "rgb(140, 0, 0)",
                "border_radius": "10px",
            }
        )
        panel.setContentStyle(
            {
                "border_radius": "0px",
            }
        )
        contentLayout = Qt.QFormLayout()
        panel.content().setLayout(contentLayout)
        contentLayout.addRow("State", Qt.QPushButton("Press here"))
        contentLayout.addRow("Status", Qt.QLineEdit())
        contentLayout.addRow("Coment", Qt.QLineEdit())
        contentLayout.addRow("Build", Qt.QCheckBox())
        contentLayout.addRow("Upper limit", Qt.QSpinBox())
        contentLayout.addRow("Lower limit", Qt.QSpinBox())
        lyt.addWidget(panel, 0)

        panel = QGroupWidget()
        panel.title = "Hello world 2"
        panel.titleIcon = Qt.QIcon.fromTheme("network-server")
        panel.titleVisible = False
        contentLayout = Qt.QFormLayout()
        panel.content().setLayout(contentLayout)
        contentLayout.addRow("Something", Qt.QLineEdit())
        contentLayout.addRow("More", Qt.QLineEdit())
        lyt.addWidget(panel, 0)

        panel = QGroupWidget()
        panel.title = "5"
        panel.titleIcon = Qt.QIcon.fromTheme("folder")
        contentLayout = Qt.QVBoxLayout()
        panel.content().setLayout(contentLayout)
        panel2 = QGroupWidget()
        panel2.title = "5.1"
        panel2.titleIcon = Qt.QIcon.fromTheme("folder")
        panel2.titleHeight = 48
        contentLayout2 = Qt.QFormLayout()
        panel2.content().setLayout(contentLayout2)
        contentLayout2.addRow("Something", Qt.QLineEdit())
        contentLayout2.addRow("More", Qt.QLineEdit())
        contentLayout.addWidget(panel2, 0)
        lyt.addWidget(panel, 0)

        lyt.addStretch(1)

        w.show()
        w.adjustSize()
        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="Group widget 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()