예제 #1
0
    def create_widget_layout(self,
                             widget_dict: dict,
                             cb_f: Callable = None,
                             line_f: Callable = None) -> QHBoxLayout:
        """
        This method sets up the parameters layout by reading
        the JSON-based dict of params and building
        the corresponding graphic objects.

        Parameters
        ----------
        widget_dict : dict
            The dictionary of widgets to build.
        cb_f : Callable, optional
            The activation function for combo boxes.
        line_f : Callable, optional
            The activation function for text boxes.

        Returns
        ----------
        QHBoxLayout
            The layout with all the widgets loaded.

        """

        widget_layout = QHBoxLayout()
        left_layout = QGridLayout()
        left_layout.setAlignment(Qt.AlignTop)

        counter = 0
        for first_level in widget_dict.keys():

            sub_key = next(iter(widget_dict[first_level]))

            if type(widget_dict[first_level][sub_key]) == dict:

                self.widgets[first_level] = CustomComboBox()
                for second_level in widget_dict[first_level].keys():
                    self.widgets[first_level].addItem(second_level)
                self.widgets[first_level].setCurrentIndex(-1)

                if cb_f is not None:
                    self.widgets[first_level].activated.connect(
                        cb_f(first_level))
            else:

                if widget_dict[first_level]["type"] == "bool":

                    self.widgets[first_level] = CustomComboBox()
                    self.widgets[first_level].addItems([
                        str(widget_dict[first_level]["value"]),
                        str(not widget_dict[first_level]["value"])
                    ])
                else:

                    self.widgets[first_level] = CustomTextBox()
                    self.widgets[first_level].setText(
                        str(widget_dict[first_level].get("value", "")))

                    if line_f is not None:
                        self.widgets[first_level].textChanged.connect(
                            line_f(first_level))

                    if widget_dict[first_level]["type"] == "int":
                        self.widgets[first_level].setValidator(
                            ArithmeticValidator.INT)
                    elif widget_dict[first_level]["type"] == "float":
                        self.widgets[first_level].setValidator(
                            ArithmeticValidator.FLOAT)
                    elif widget_dict[first_level]["type"] == "tensor" or \
                            widget_dict[first_level]["type"] == "tuple":
                        self.widgets[first_level].setValidator(
                            ArithmeticValidator.TENSOR)

            w_label = CustomLabel(first_level)
            if 'optional' not in widget_dict[first_level].keys():
                w_label.setText(first_level + '*')
            w_label.setToolTip(widget_dict[first_level].get("description"))
            left_layout.addWidget(w_label, counter, 0)
            left_layout.addWidget(self.widgets[first_level], counter, 1)
            counter += 1

        widget_layout.addLayout(left_layout)
        return widget_layout
예제 #2
0
    def append_node_params(self, node: NetworkNode, current_data: dict) -> int:
        """

        This method adds to the dialog layer the editable parameters of
        the node, and returns the last row counter for the grid main_layout.

        Attributes
        ----------
        node: NetworkNode
            The node whose parameters are displayed.
        current_data: dict
            The node current data.
        Returns
        ----------
        int
            The last row counter.

        """

        # Init column counter
        counter = 2

        # Display parameter labels
        for param, value in node.param.items():
            param_label = CustomLabel(param)
            if node.param[param]["editable"] == "false":
                param_label.setStyleSheet(style.UNEDITABLE_PARAM_LABEL_STYLE)

            param_label.setAlignment(Qt.AlignRight)
            # Set the tooltip of the input with the description
            param_label.setToolTip("<" + value["type"] + ">: "
                                   + value["description"])
            self.layout.addWidget(param_label, counter, 0)

            # Display parameter values
            if value["type"] == "boolean":
                line = CustomComboBox()
                line.addItem("True")
                line.addItem("False")
                line.setPlaceholderText(str(current_data[param]))
            else:
                line = CustomTextBox()
                if node.param[param]["editable"] == "false":
                    line.setReadOnly(True)
                if isinstance(current_data[param], Tensor) or isinstance(current_data[param], np.ndarray):
                    line.setText("(" + ','.join(map(str, current_data[param].shape)) + ")")
                elif isinstance(current_data[param], tuple):
                    line.setText(','.join(map(str, current_data[param])))
                else:
                    line.setText(str(current_data[param]))

                # Set type validator
                validator = None
                if value["type"] == "int":
                    validator = ArithmeticValidator.INT
                elif value["type"] == "float":
                    validator = ArithmeticValidator.FLOAT
                elif value["type"] == "Tensor" or value["type"] == "list of ints":
                    validator = ArithmeticValidator.TENSOR
                elif value["type"] == "list of Tensors":
                    validator = ArithmeticValidator.TENSOR_LIST
                line.setValidator(validator)

            if node.param[param]["editable"] == "false":
                line.setStyleSheet(style.UNEDITABLE_VALUE_LABEL_STYLE)
            self.layout.addWidget(line, counter, 1)

            # Keep trace of CustomTextBox objects
            self.parameters[param] = line
            counter += 1

        return counter
예제 #3
0
    def show_layout(self, name: str) -> None:
        """
        This method displays a grid layout initialized by the
        dictionary of parameters and default values.

        Parameters
        ----------
        name : str
            The name of the main parameter to which
            the dictionary is related.

        """

        title = CustomLabel(name.replace(':', ': '))
        title.setAlignment(Qt.AlignCenter)
        self.grid_layout.addWidget(title, 0, 0, 1, 2)
        widgets_2level = dict()

        count = 1
        for k, v in self.gui_params[name].items():
            # Activation functions for dynamic widgets
            def activation_combo(super_key: str, key: str):
                return lambda: self.update_dict_value(
                    name, key, widgets_2level[f"{super_key}:{key}"][1].
                    currentText())

            def activation_line(super_key: str, key: str):
                return lambda: self.update_dict_value(
                    name, key, widgets_2level[f"{super_key}:{key}"][1].text())

            w_label = CustomLabel(k)
            w_label.setToolTip(v.get("description"))
            if v["type"] == "bool":
                cb = CustomComboBox()
                cb.addItems([str(v["value"]), str(not v["value"])])
                widgets_2level[f"{name}:{k}"] = (w_label, cb)
                widgets_2level[f"{name}:{k}"][1].activated.connect(
                    activation_combo(name, k))
            elif "allowed" in v.keys():
                cb = CustomComboBox()
                cb.addItems(v["allowed"])
                widgets_2level[f"{name}:{k}"] = (w_label, cb)
                widgets_2level[f"{name}:{k}"][1].activated.connect(
                    activation_combo(name, k))
            else:
                widgets_2level[f"{name}:{k}"] = (w_label,
                                                 CustomTextBox(str(
                                                     v["value"])))
                widgets_2level[f"{name}:{k}"][1].textChanged.connect(
                    activation_line(name, k))
                if v["type"] == "int":
                    widgets_2level[f"{name}:{k}"][1].setValidator(
                        ArithmeticValidator.INT)
                elif v["type"] == "float":
                    widgets_2level[f"{name}:{k}"][1].setValidator(
                        ArithmeticValidator.FLOAT)
                elif v["type"] == "tensor" or \
                        v["type"] == "tuple":
                    widgets_2level[f"{name}:{k}"][1].setValidator(
                        ArithmeticValidator.TENSOR)

            self.grid_layout.addWidget(widgets_2level[f"{name}:{k}"][0], count,
                                       0)
            self.grid_layout.addWidget(widgets_2level[f"{name}:{k}"][1], count,
                                       1)
            count += 1
예제 #4
0
class DropDownLabel(QWidget):
    """
    This widget displays a generic parameter name and value.
    It features a drop-down arrow button that shows or hides
    the description.

    Attributes
    ----------
    layout : QVBoxLayout
        Vertical main_layout of the widget.
    top : QWidget
        First part of the widget with name, type and default value of the
        parameter.
    top_layout : QHBoxLayout
        Horizontal main_layout of the top of the widget.
    name_label : CustomLabel
        Id and type of the object.
    type_label : CustomLabel
        Object type.
    default_label : CustomLabel
        Eventual default value.
    down_button : CustomButton
        Arrow button to show/hide the description of the parameter.
    description : CustomLabel
        Description of the parameter.

    Methods
    ----------
    change_description_mode()
        This method shows or hides the description of the parameter.

    """
    def __init__(self, name: str, parameters: dict):
        super().__init__()
        self.layout = QVBoxLayout()
        self.setContentsMargins(0, 0, 0, 0)
        self.setLayout(self.layout)
        self.setStyleSheet(style.DROPDOWN_STYLE)
        self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding)

        # Top bar with short info
        self.top = QWidget()
        self.top.setContentsMargins(0, 0, 0, 0)
        self.top.setStyleSheet(style.DROPDOWN_TOP_STYLE)
        self.top_layout = QHBoxLayout()
        self.top_layout.setContentsMargins(0, 0, 0, 0)
        self.top.setLayout(self.top_layout)

        self.name_label = CustomLabel(name)
        self.name_label.setAlignment(Qt.AlignLeft)
        self.name_label.setStyleSheet(style.DROPDOWN_NAME_STYLE)
        self.top_layout.addWidget(self.name_label, Qt.AlignLeft)

        self.type_label = CustomLabel(parameters["type"])
        self.type_label.setAlignment(Qt.AlignLeft)
        self.type_label.setToolTip("Type")
        self.type_label.setStyleSheet(style.DROPDOWN_TYPE_STYLE)
        self.top_layout.addWidget(self.type_label, Qt.AlignLeft)

        if "default" in parameters:
            self.default_label = CustomLabel(parameters["default"])
            self.default_label.setStyleSheet(style.DROPDOWN_DEFAULT_STYLE)
            self.default_label.setToolTip("Default value")
            self.default_label.setAlignment(Qt.AlignCenter)
            self.top_layout.addWidget(self.default_label, Qt.AlignRight)

        self.down_button = CustomButton("\u25bc")
        self.down_button.setStyleSheet(style.DROPDOWN_ARROW_STYLE)
        self.down_button.clicked.connect(lambda: self.__toggle_visibility())
        self.top_layout.addWidget(self.down_button, Qt.AlignRight)

        self.layout.addWidget(self.top)

        self.description = CustomLabel(parameters["description"])
        self.description.setSizePolicy(QSizePolicy.Minimum,
                                       QSizePolicy.Maximum)
        self.description.setWordWrap(True)
        self.description.setStyleSheet(style.DESCRIPTION_STYLE)
        self.description.hide()
        self.layout.addWidget(self.description)

    def __toggle_visibility(self):
        """
        This method toggles the visibility of the parameter description
        changing the arrow icon of the button.

        """

        if self.description.isHidden():
            self.description.show()
            self.down_button.setText("\u25b2")
        else:
            self.description.hide()
            self.down_button.setText("\u25bc")