# Source code for taurus.qt.qtgui.table.taurusdevicepropertytable

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

    """
    taurusdevicepropertytable.py:
    """

    # todo: tango-centric

    from taurus.external.qt import Qt, QtCore, QtGui
    from taurus.qt.qtgui.base import TaurusBaseWidget
    from taurus.core.taurusdevice import TaurusDevice

    class TaurusPropTable(QtGui.QTableWidget, TaurusBaseWidget):
        """
        This widget will show a list of properties of device and the list of
        values.
        """

        # TODO add a frame for Add, Delete and Refresh buttons!

        # TODO This widget is Tango-centric

        def __init__(self, parent=None, designMode=False):
            try:
                name = "TaurusPropTable"
                self._useParentModel = True
                self._localModel = ""
                self.call__init__wo_kw(QtGui.QTableWidget, parent)
                self.call__init__(TaurusBaseWidget, name, designMode=designMode)
                self.setObjectName(name)
                self.defineStyle()
                self.db = None

            except Exception:
                self.traceback()

        # -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
        # TaurusBaseWidget over writing methods
        # -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~

        def setModel(self, model, **kwargs):
            TaurusBaseWidget.setModel(self, model)
            # Update the table
            modelObj = self.getModelObj()
            if modelObj is None:
                dev_name = None
                self.db = None
            else:
                validator = modelObj.getNameValidator()
                groups = validator.getUriGroups(modelObj.getFullName())
                dev_name = groups["devname"]
                # -----------------------------------------------------------------
                # Workaround for bug-256
                # (use next line instead of the other one when bug-256 is fixed)
                # self.db = modelObj.getParentObj() # use this instead
                self.db = modelObj.factory().getAuthority(groups["authority"])
                # -----------------------------------------------------------------
            self.setTable(dev_name)

        def sizeHint(self):
            return QtGui.QTableWidget.sizeHint(self)

        def minimumSizeHint(self):
            return QtGui.QTableWidget.minimumSizeHint(self)

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

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

        # -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
        # QT properties
        # -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~

        model = QtCore.pyqtProperty(
            "QString",
            TaurusBaseWidget.getModel,
            setModel,
            TaurusBaseWidget.resetModel,
        )

        #: (deprecated))
        useParentModel = QtCore.pyqtProperty(
            "bool",
            TaurusBaseWidget.getUseParentModel,
            TaurusBaseWidget.setUseParentModel,
            TaurusBaseWidget.resetUseParentModel,
        )

        # -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
        # My methods
        # -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~

        @QtCore.pyqtSlot("QString")
        def setTable(self, dev_name):
            """
            Fills the table with the names of properties and their values for the
            given device.
            """
            if dev_name is None:
                return  # TODO: the table should be cleaned

            elif self.db is None:
                self.warning("Model must be set before calling setTable")
                return
            try:
                self.cellChanged.disconnect(self.valueChanged)
            except Exception:
                pass

            dev_name = str(dev_name)
            self.list_prop = list(self.db.get_device_property_list(dev_name, "*"))
            self.setRowCount(len(self.list_prop))
            for i in range(0, len(self.list_prop)):
                elem = self.list_prop[i]
                self.setText(elem, i, 0)
                self.dictionary = self.db.get_device_property(
                    dev_name, self.list_prop
                )
                self.debug(
                    "Getting %s properties: %s -> %s",
                    dev_name,
                    self.list_prop,
                    self.dictionary,
                )
                value = self.dictionary[elem]
                self.debug(
                    "TaurusPropsTable: property %s is type %s", elem, type(value)
                )
                USE_TABLES = False
                if USE_TABLES:
                    self.setPropertyValue(value, i, 1)
                else:
                    if not isinstance(value, str):  # not something like an string
                        # adding new lines in between elements in the list
                        value = "\n".join(str(v) for v in value)
                    self.setText(str(value), i, 1)

            self.updateStyle()
            self.dev_name = dev_name
            self.setWindowTitle("%s Properties" % dev_name)
            self.resizeColumnsToContents()
            self.resizeRowsToContents()

        def defineStyle(self):
            """Defines the initial style for the widget"""
            self.setWindowTitle("Properties")
            self.setColumnCount(2)
            self.setRowCount(0)
            self.setGeometry(QtCore.QRect(0, 0, 400, 500))

            self.setColumnWidth(0, 124)
            self.setColumnWidth(1, 254)

            headerItem = QtGui.QTableWidgetItem()
            headerItem.setText(
                QtGui.QApplication.translate(
                    "PLCTabWidget",
                    "Property Name",
                    None,
                    QtGui.QApplication.UnicodeUTF8,
                )
            )
            self.setHorizontalHeaderItem(0, headerItem)

            headerItem1 = QtGui.QTableWidgetItem()
            headerItem1.setText(
                QtGui.QApplication.translate(
                    "PLCTabWidget", "Value", None, QtGui.QApplication.UnicodeUTF8
                )
            )
            self.setHorizontalHeaderItem(1, headerItem1)
            hh = self.horizontalHeader()
            if hh.length() > 0:
                hh.setSectionResizeMode(hh.ResizeToContents)

        def updateStyle(self):
            self.resizeRowsToContents()
            hh = self.horizontalHeader()
            if hh.length() > 0:
                hh.setSectionResizeMode(hh.ResizeToContents)

                # self.resizeColumnsToContents()

        def setText(self, value, i=None, j=None):
            item = QtGui.QTableWidgetItem()
            item.setFlags(Qt.Qt.ItemIsEnabled)
            item.setText(
                QtGui.QApplication.translate(
                    "PLCTabWidget", value, None, QtGui.QApplication.UnicodeUTF8
                )
            )
            if i is not None and j is not None:
                self.setItem(i, j, item)

            # TODO: the info does not change with the events.

        def valueDoubleClicked(self, x, y):
            self.info("TaurusPropTable.valueDoubleClicked(%s,%s)" % (x, y))
            # opens a dialog for multiline edition
            self.editProperty()

        # -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
        # @name Property Edition
        # @{
        # -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~

        def addProperty(self):
            text, ok = QtGui.QInputDialog.getText(
                self, "New Property", "Property name:"
            )
            if ok:
                text1 = str(text)
                new_prop_name = str(text1)
                new_prop_value = "0"
                dict1 = {new_prop_name: [new_prop_value]}
                self.db.put_device_property(self.dev_name, dict1)
                self.setTable(self.dev_name)

        def deleteProperty(self):
            row = self.currentRow()
            prop_name = self.item(row, 0).text()
            list = [str(prop_name)]
            yes = QtGui.QMessageBox.Ok
            no = QtGui.QMessageBox.Cancel
            result = QtGui.QMessageBox.question(
                self,
                "Removing property",
                "Would you like to delete property  '" + prop_name + "'  ?",
                yes,
                no,
            )
            if result == yes:
                self.db.delete_device_property(self.dev_name, list)
                self.setTable(self.dev_name)

        def editProperty(self):
            row = self.currentRow()
            col = self.currentColumn()

            item1 = QtGui.QTableWidgetItem()
            item1 = self.item(row, 0)
            prop_name = item1.text()
            prop_name = str(prop_name)
            self.prop_name2 = prop_name
            self.info("TaurusPropsTable.editProperty(%s)" % prop_name)

            item2 = QtGui.QTableWidgetItem()
            item2 = self.item(row, 1)
            prop_value = item2.text()
            prop_value = str(prop_value)

            if col == 0:
                new_text, ok = QtGui.QInputDialog.getText(
                    self, "Rename", "Write new name of property:"
                )
                if ok:
                    new_text = str(new_text)
                    new_text = str(new_text)
                    list = [prop_name]
                    dict = {new_text: [prop_value]}
                    # usuwanie musze umiescic gdzies wczesniej bo inaczej usuwam
                    # juz zmieniana nazwe z listy property
                    self.db.delete_device_property(self.dev_name, list)
                    self.db.put_device_property(self.dev_name, dict)
                    self.setTable(self.dev_name)
            elif col == 1:
                # Create the dilog to edit multiply text
                dialogx = EditTextDialog(self)
                dialogx.setText(prop_value)
                dialogx.exec_()
                ok = dialogx.getResult()  # OK or Cancel
                if ok:
                    new_text = (
                        dialogx.getNewText()
                    )  # method of dialog to get the changed text
                    self.setNewPropertyValue(new_text)

        def setNewPropertyValue(self, new_text):
            new_text = str(new_text)
            new_text = str(new_text)
            values = {self.prop_name2: new_text.replace("\r", "").split("\n")}
            self.db.put_device_property(self.dev_name, values)
            self.setTable(self.dev_name)
            self.updateStyle()

        # @}

        # -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
        # Methods  for database commands
        # -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~

        def get_device_property_names(self, dev_name, wildcard="*"):
            return self.db.get_device_property_list(dev_name, wildcard)

        def put_device_property(self, dev_name, dict):
            return self.db.put_device_property(dev_name, dict)

        # -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
        # @name DEPRECATED METHODS
        # @{
        # -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~

        def valueChanged(self):
            """@deprecated valueChanged THIS DOES NOTHING!"""
            row = self.currentRow()
            # item = QtGui.QTableWidgetItem()
            item = self.item(row, 0)
            prop_name = item.text()
            prop_name = str(prop_name)
            # item_2 = QtGui.QTableWidgetItem()
            item_2 = self.item(row, 1)
            prop_value = item_2.text()
            prop_value = str(prop_value)
            dict = {prop_name: [prop_value]}
            list = [self.prop_name]
            self.db.delete_device_property(self.dev_name, list)
            self.db.put_device_property(self.dev_name, dict)

        def setPropertyValue(self, value, i, j):
            """This method inserts a new table widget inside the cell
            @deprecated ... use setText() and editProperty() event call instead!!!
            """
            if len(value) == 1 and isinstance(value[0], str):
                value = value[0]
            if isinstance(value, str):  # and '\n' in value:
                value = value.split("\n")
            if False:  # isinstance(value,str):
                item = QtGui.QTableWidgetItem()
                item.setText(
                    QtGui.QApplication.translate(
                        "PLCTabWidget", value, None, QtGui.QApplication.UnicodeUTF8
                    )
                )
                self.setItem(i, j, item)
            else:
                item = QtGui.QTableWidget(len(value), 1)
                item.setItemDelegate(Delegate(item))
                item.horizontalHeader().hide()
                item.verticalHeader().hide()
                # item.setGridStyle(Qt.Qt.DashLine)
                for k, v in enumerate(value):
                    cell = QtGui.QTableWidgetItem()
                    cell.setText(
                        QtGui.QApplication.translate(
                            "PLCTabWidget", v, None, QtGui.QApplication.UnicodeUTF8
                        )
                    )
                    item.setItem(k, 0, cell)
                item.setSizePolicy(
                    QtGui.QSizePolicy.MinimumExpanding,
                    QtGui.QSizePolicy.MinimumExpanding,
                )
                self.setCellWidget(i, j, item)
                self.resizeColumnsToContents()
                self.resizeRowsToContents()
            return

        # @}

    class EditTextDialog(QtGui.QDialog):
        """This class create the dialog using to edit multiply text"""

        def __init__(self, parent=None):
            print("In EditTextDialog.__init__()")
            QtGui.QDialog.__init__(self, parent)
            self.setModal(1)
            self.initComponents()
            self.show()
            self.result = 0
            # Signals

            self.buttonBox.accepted.connect(self.pressOK)
            self.buttonBox.rejected.connect(self.close)

        def initComponents(self):
            widgetLayout = QtGui.QVBoxLayout(self)
            widgetLayout.setContentsMargins(10, 10, 10, 10)
            self.editText = QtGui.QTextEdit()
            self.buttonBox = QtGui.QDialogButtonBox()
            self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
            self.buttonBox.setStandardButtons(
                QtGui.QDialogButtonBox.Cancel
                | QtGui.QDialogButtonBox.NoButton
                | QtGui.QDialogButtonBox.Ok
            )
            widgetLayout.addWidget(self.editText)
            widgetLayout.addWidget(self.buttonBox)

        def pressOK(self):
            print("In EditTextDialog.pressOk()")
            self.new_text = self.editText.toPlainText()
            self.result = 1
            self.close()

        def setText(self, text):
            self.editText.setText(text)
            self.new_text = text

        def getNewText(self):
            return self.new_text

        def getResult(self):
            return self.result

    class Delegate(QtGui.QItemDelegate):
        """Usage:
            table = QtGui.QTableWidget()
        table.setItemDelegate(Delegate(table))
        """

        def __init__(self, parent=None):
            QtGui.QItemDelegate.__init__(self, parent)

        def sizeHint(self, option, index):
            table = self.parent()
            widget = table.cellWidget(index.row(), index.column())
            if not widget:
                widget = table.itemAt(index.row(), index.column())
            size = widget.sizeHint()
            return size

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

        app = TaurusApplication(
            app_name="TaurusDevice property table", cmd_line_parser=None
        )
        widget = TaurusPropTable()
        args = sys.argv
        if len(args) == 1:
            model = "sys/tg_test/1"
        else:
            model = str(args[1])
        widget.setModel(model)
        widget.show()
        app.exec_()