Esempio n. 1
0
    def __init__(self, node_block: NodeBlock):
        super().__init__(node_block.node.name, "")
        self.layout = QGridLayout()

        # Connect node
        self.node = node_block
        self.parameters = dict()
        self.edited_data = dict()
        self.has_edits = False

        # Build main_layout
        title_label = CustomLabel("Edit parameters")
        title_label.setStyleSheet(style.NODE_LABEL_STYLE)
        title_label.setAlignment(Qt.AlignCenter)
        self.layout.addWidget(title_label, 0, 0, 1, 2)

        # Input box
        in_dim_label = CustomLabel("Input")
        in_dim_label.setStyleSheet(style.IN_DIM_LABEL_STYLE)
        in_dim_label.setAlignment(Qt.AlignRight)
        self.layout.addWidget(in_dim_label, 1, 0)

        in_dim_box = CustomTextBox(','.join(map(str, node_block.in_dim)))
        in_dim_box.setValidator(ArithmeticValidator.TENSOR)

        self.layout.addWidget(in_dim_box, 1, 1)
        self.parameters["in_dim"] = in_dim_box

        if not node_block.is_head:
            in_dim_box.setReadOnly(True)

        # Display parameters if present
        counter = 2
        if node_block.node.param:
            counter = self.append_node_params(node_block.node, node_block.block_data)

        # "Apply" button which saves changes
        apply_button = CustomButton("Apply")
        apply_button.clicked.connect(self.save_data)
        self.layout.addWidget(apply_button, counter, 0)

        # "Cancel" button which closes the dialog without saving
        cancel_button = CustomButton("Cancel")
        cancel_button.clicked.connect(self.close)
        self.layout.addWidget(cancel_button, counter, 1)

        self.layout.setColumnStretch(0, 1)
        self.layout.setColumnStretch(1, 1)

        self.render_layout()
Esempio n. 2
0
    def __init__(self, node_block: NodeBlock):
        super().__init__(node_block.node.name, "")
        self.layout = QGridLayout()

        # Connect node
        self.node = node_block
        self.new_in_dim = ','.join(map(str, node_block.in_dim))
        self.in_dim_box = CustomTextBox()
        self.has_edits = False

        # Build main_layout
        title_label = CustomLabel("Edit network input")
        title_label.setStyleSheet(style.NODE_LABEL_STYLE)
        title_label.setAlignment(Qt.AlignCenter)
        self.layout.addWidget(title_label, 0, 0, 1, 2)

        # Input box
        in_dim_label = CustomLabel("Input shape")
        in_dim_label.setStyleSheet(style.IN_DIM_LABEL_STYLE)
        in_dim_label.setAlignment(Qt.AlignRight)
        self.layout.addWidget(in_dim_label, 1, 0)

        self.in_dim_box.setText(self.new_in_dim)
        self.in_dim_box.setValidator(ArithmeticValidator.TENSOR)

        self.layout.addWidget(self.in_dim_box, 1, 1)

        if not node_block.is_head:
            self.in_dim_box.setReadOnly(True)

        # "Apply" button which saves changes
        apply_button = CustomButton("Apply")
        apply_button.clicked.connect(self.save_data)
        self.layout.addWidget(apply_button, 2, 0)

        # "Cancel" button which closes the dialog without saving
        cancel_button = CustomButton("Cancel")
        cancel_button.clicked.connect(self.close)
        self.layout.addWidget(cancel_button, 2, 1)

        self.layout.setColumnStretch(0, 1)
        self.layout.setColumnStretch(1, 1)

        self.render_layout()
Esempio n. 3
0
    def __init__(self, message):
        super().__init__("", message)

        # Set title label
        title_label = CustomLabel("Input required")
        title_label.setStyleSheet(style.NODE_LABEL_STYLE)
        title_label.setAlignment(Qt.AlignCenter)

        # Set message label
        mess_label = CustomLabel("\n" + self.content + "\n")
        mess_label.setAlignment(Qt.AlignCenter)

        # Set input reading
        self.input = None
        input_line = CustomTextBox()
        input_line.setValidator(QRegExpValidator(QRegExp(
            ArithmeticValidator.TENSOR.regExp().pattern() + "|" +
            ArithmeticValidator.TENSOR_LIST.regExp().pattern())))

        # Add buttons to close the dialog
        confirm_button = CustomButton("Ok")
        confirm_button.clicked.connect(self.save_input)

        cancel_button = CustomButton("Cancel")
        cancel_button.clicked.connect(self.cancel)

        buttons = QWidget()
        buttons_layout = QHBoxLayout()
        buttons_layout.addWidget(confirm_button)
        buttons_layout.addWidget(cancel_button)
        buttons.setLayout(buttons_layout)

        # Compose widgets
        self.layout.addWidget(title_label)
        self.layout.addWidget(mess_label)
        self.layout.addWidget(input_line)
        self.layout.addWidget(buttons)

        self.render_layout()
Esempio n. 4
0
    def __init__(self, property_block: PropertyBlock):
        super().__init__("Edit property", "")
        self.property_block = property_block
        self.new_property = self.property_block.smt_string
        self.has_edits = False
        self.layout = QGridLayout()

        # Build main_layout
        title_label = CustomLabel("SMT property")
        title_label.setStyleSheet(style.NODE_LABEL_STYLE)
        title_label.setAlignment(Qt.AlignCenter)
        self.layout.addWidget(title_label, 0, 0, 1, 2)

        # Input box
        smt_label = CustomLabel("SMT-LIB definition")
        smt_label.setStyleSheet(style.IN_DIM_LABEL_STYLE)
        smt_label.setAlignment(Qt.AlignRight)
        self.layout.addWidget(smt_label, 1, 0)

        self.smt_box = CustomTextArea()
        self.smt_box.insertPlainText(self.new_property)
        self.layout.addWidget(self.smt_box, 1, 1)

        # "Apply" button which saves changes
        apply_button = CustomButton("Apply")
        apply_button.clicked.connect(self.save_data)
        self.layout.addWidget(apply_button, 2, 0)

        # "Cancel" button which closes the dialog without saving
        cancel_button = CustomButton("Cancel")
        cancel_button.clicked.connect(self.close)
        self.layout.addWidget(cancel_button, 2, 1)

        self.layout.setColumnStretch(0, 1)
        self.layout.setColumnStretch(1, 1)

        self.render_layout()
Esempio n. 5
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
Esempio n. 6
0
    def __init__(self, nn: NeuralNetwork):
        super().__init__("Train Network")

        # Training elements
        self.nn = nn
        self.is_nn_trained = False
        self.dataset_path = ""
        self.dataset_params = dict()
        self.dataset_transform = tr.Compose([])
        self.params = utility.read_json(ROOT_DIR + '/res/json/training.json')
        self.gui_params = dict()
        self.loss_f = ''
        self.metric = ''
        self.grid_layout = QGridLayout()

        # Dataset
        dt_label = CustomLabel("Dataset")
        dt_label.setAlignment(Qt.AlignCenter)
        dt_label.setStyleSheet(style.NODE_LABEL_STYLE)
        self.layout.addWidget(dt_label)

        dataset_layout = QHBoxLayout()
        self.widgets["dataset"] = CustomComboBox()
        self.widgets["dataset"].addItems(
            ["MNIST", "Fashion MNIST", "Custom data source..."])
        self.widgets["dataset"].setCurrentIndex(-1)
        self.widgets["dataset"].activated \
            .connect(lambda: self.setup_dataset(self.widgets["dataset"].currentText()))
        dataset_layout.addWidget(CustomLabel("Dataset"))
        dataset_layout.addWidget(self.widgets["dataset"])
        self.layout.addLayout(dataset_layout)

        transform_layout = QHBoxLayout()
        self.widgets["transform"] = CustomComboBox()
        self.widgets["transform"].addItems([
            "No transform", "Convolutional MNIST", "Fully Connected MNIST",
            "Custom..."
        ])
        self.widgets["transform"].activated \
            .connect(lambda: self.setup_transform(self.widgets["transform"].currentText()))
        transform_layout.addWidget(CustomLabel("Dataset transform"))
        transform_layout.addWidget(self.widgets["transform"])
        self.layout.addLayout(transform_layout)

        # Separator
        sep_label = CustomLabel("Training parameters")
        sep_label.setAlignment(Qt.AlignCenter)
        sep_label.setStyleSheet(style.NODE_LABEL_STYLE)
        self.layout.addWidget(sep_label)

        # Main body
        # Activation functions for dynamic widgets
        def activation_combo(key: str):
            return lambda: self.update_grid_view(
                f"{key}:{self.widgets[key].currentText()}")

        def activation_line(key: str):
            return lambda: self.update_dict_value(key, "", self.widgets[key].
                                                  text())

        body_layout = self.create_widget_layout(self.params, activation_combo,
                                                activation_line)
        body_layout.addLayout(self.grid_layout)
        self.grid_layout.setAlignment(Qt.AlignTop)
        self.layout.addLayout(body_layout)

        # Buttons
        btn_layout = QHBoxLayout()
        self.train_btn = CustomButton("Train network")
        self.train_btn.clicked.connect(self.train_network)
        self.cancel_btn = CustomButton("Cancel")
        self.cancel_btn.clicked.connect(self.close)
        btn_layout.addWidget(self.train_btn)
        btn_layout.addWidget(self.cancel_btn)
        self.layout.addLayout(btn_layout)

        self.render_layout()
Esempio n. 7
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
Esempio n. 8
0
    def __init__(self, property_block: PropertyBlock):
        super().__init__("Edit property", "")
        self.property_block = property_block
        self.has_edits = False
        self.property_list = []
        self.viewer = CustomTextArea()
        self.viewer.setReadOnly(True)
        self.viewer.setFixedHeight(100)
        grid = QGridLayout()

        # Build main_layout
        title_label = CustomLabel("Polyhedral property")
        title_label.setStyleSheet(style.NODE_LABEL_STYLE)
        title_label.setAlignment(Qt.AlignCenter)
        grid.addWidget(title_label, 0, 0, 1, 3)

        # Labels
        var_label = CustomLabel("Variable")
        var_label.setStyleSheet(style.IN_DIM_LABEL_STYLE)
        var_label.setAlignment(Qt.AlignRight)
        grid.addWidget(var_label, 1, 0)

        relop_label = CustomLabel("Operator")
        relop_label.setStyleSheet(style.IN_DIM_LABEL_STYLE)
        relop_label.setAlignment(Qt.AlignCenter)
        grid.addWidget(relop_label, 1, 1)

        value_label = CustomLabel("Value")
        value_label.setStyleSheet(style.IN_DIM_LABEL_STYLE)
        value_label.setAlignment(Qt.AlignLeft)
        grid.addWidget(value_label, 1, 2)

        self.var_cb = CustomComboBox()
        for v in property_block.variables:
            self.var_cb.addItem(v)
        grid.addWidget(self.var_cb, 2, 0)

        self.op_cb = CustomComboBox()
        operators = ["<=", "<", ">", ">="]
        for o in operators:
            self.op_cb.addItem(o)
        grid.addWidget(self.op_cb, 2, 1)

        self.val = CustomTextBox()
        self.val.setValidator(ArithmeticValidator.FLOAT)
        grid.addWidget(self.val, 2, 2)

        # "Add" button which adds the constraint
        add_button = CustomButton("Add")
        add_button.clicked.connect(
            lambda: self.add_entry(str(self.var_cb.currentText()), str(self.op_cb.currentText()), self.val.text()))
        grid.addWidget(add_button, 3, 0)

        # "Save" button which saves the state
        save_button = CustomButton("Save")
        save_button.clicked.connect(self.save_property)
        grid.addWidget(save_button, 3, 1)

        # "Cancel" button which closes the dialog without saving
        cancel_button = CustomButton("Cancel")
        cancel_button.clicked.connect(self.close)
        grid.addWidget(cancel_button, 3, 2)

        grid.setColumnStretch(0, 1)
        grid.setColumnStretch(1, 1)
        grid.setColumnStretch(2, 1)

        self.layout.addLayout(grid)
        self.layout.addWidget(self.viewer, 3)
        self.render_layout()
Esempio n. 9
0
class BlockInspector(QWidget):
    """
    This class contains the widget for displaying the description of a network
    block in the ParamToolbar. Each block attribute is labeled and wrapped
    in a drop-down box.

    Attributes
    ----------
    layout : QVBoxLayout
        Vertical main_layout of the widget.
    title_label : CustomLabel
        Title of the widget.
    description_label : CustomLabel
        Description of the block.
    parameters : QWidget
        Container of parameters.
    parameters_label : CustomLabel
        Label of parameters.
    parameters_layout : QVBoxLayout
        Vertical main_layout of parameters.
    inputs : QWidget
        Container of inputs.
    inputs_label : CustomLabel
        Label of inputs.
    inputs_layout : QVBoxLayout
        Vertical main_layout of inputs.
    outputs : QWidget
        Container of outputs.
    outputs_label : CustomLabel
        Label of outputs.
    outputs_layout : QVBoxLayout
        Vertical main_layout of outputs.

    """
    def __init__(self, block: NodeBlock):
        super().__init__()
        self.setStyleSheet(style.BLOCK_BOX_STYLE)
        self.layout = QVBoxLayout()
        self.layout.setSpacing(0)
        self.layout.setContentsMargins(0, 0, 10, 0)
        self.setLayout(self.layout)
        self.adjustSize()
        self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Maximum)

        # Widget title
        self.title_label = CustomLabel()
        self.title_label.setStyleSheet(style.TITLE_LABEL_STYLE)
        self.title_label.setText(block.block_id + ":" + block.node.name)

        # NodeBlock description
        self.description_label = CustomLabel()
        self.description_label.setStyleSheet(style.DESCRIPTION_STYLE)
        self.description_label.setWordWrap(True)
        self.description_label.setAlignment(Qt.AlignLeft)
        self.description_label.setText(block.node.descr)
        self.description_label.setSizePolicy(QSizePolicy.Preferred,
                                             QSizePolicy.Minimum)

        # Parameters section
        if block.node.param:
            self.parameters_label = CustomLabel("Parameters")
            self.parameters_label.setStyleSheet(style.NODE_LABEL_STYLE)
            self.parameters = QWidget()
            self.parameters_layout = QVBoxLayout()
            self.parameters_layout.setSpacing(0)
            self.parameters.setLayout(self.parameters_layout)
            self.parameters.setStyleSheet("padding: 0px")

            for par, values in block.node.param.items():
                self.parameters_layout.addWidget(DropDownLabel(par, values))

        # Inputs section
        if block.node.input:
            self.inputs_label = CustomLabel("Input")
            self.inputs_label.setStyleSheet(style.NODE_LABEL_STYLE)
            self.inputs = QWidget()
            self.inputs_layout = QVBoxLayout()
            self.inputs_layout.setSpacing(0)
            self.inputs.setLayout(self.inputs_layout)
            self.inputs.setStyleSheet("padding: 0px")

            for par, values in block.node.input.items():
                self.inputs_layout.addWidget(DropDownLabel(par, values))

        # Outputs section
        if block.node.output:
            self.outputs_label = CustomLabel("Output")
            self.outputs_label.setStyleSheet(style.NODE_LABEL_STYLE)
            self.outputs = QWidget()
            self.outputs_layout = QVBoxLayout()
            self.outputs_layout.setSpacing(0)
            self.outputs.setLayout(self.outputs_layout)
            self.outputs.setStyleSheet("padding: 0px")

            for par, values in block.node.output.items():
                self.outputs_layout.addWidget(DropDownLabel(par, values))

        # Compose widget
        self.layout.addWidget(self.title_label)
        self.layout.addWidget(self.description_label)

        if block.node.param:
            self.layout.addWidget(self.parameters_label)
            self.layout.addWidget(self.parameters)

        if block.node.input:
            self.layout.addWidget(self.inputs_label)
            self.layout.addWidget(self.inputs)

        if block.node.output:
            self.layout.addWidget(self.outputs_label)
            self.layout.addWidget(self.outputs)
Esempio n. 10
0
class BlocksToolbar(QToolBar):
    """
    This class defines a toolbar containing all the blocks available to draw a
    neural network: each type of block is read from a file in order to build a list
    of NetworkNode objects to be displayed.

    Attributes
    ----------
    NODE_FILE_PATH : str
        Path of the JSON file containing all information about the implemented
        nodes available to displaying.
    blocks : dict
        Dictionary of blocks connecting each block name with a NetworkNode.
    properties : dict
        Dictionary of properties connecting each property name with a NetworkProperty.
    f_buttons : dict
        Dictionary of buttons connecting a function name to a CustomButton.
    b_buttons : dict
        Dictionary connecting each block name to a CustomButton, which
        makes the corresponding node appear.
    p_buttons : dict
        Dictionary connecting each property name to a CustomButton, which
        makes the corresponding property appear.
    toolbar_tools_label : CustomLabel
        Label of the toolbar introducing tools.
    toolbar_blocks_label : CustomLabel
        Label of the toolbar introducing blocks types.
    toolbar_properties_label : CustomLabel
        Label of the toolbar introducing property names.
    isToolbar_tools_label_visible : bool
        Tells if the tools button are visible in the toolbar.
    isToolbar_blocks_label_visible : bool
        Tells if the blocks button are visible in the toolbar.
    isToolbar_properties_label_visible : bool
        Tells if the properties button are visible in the toolbar.

    Methods
    ----------
    __display_tools()
        This method displays on the toolbar the CustomButtons related to
        available tools.
    __init_blocks()
        This method reads from file all types of blocks storing them.
    __display_blocks()
        This method displays on the toolbar all buttons related to types of
        blocks.
    change_tools_mode()
        This method changes the visibility of the tools section of the toolbar.
    change_blocks_mode()
        This method changes the visibility of the blocks section of the toolbar.
    show_section(CustomLabel, dict)
        This method shows the given objects.
    hide_section(CustomLabel, dict)
        This method hides the given objects.

    """
    def __init__(self, node_file_path: str):
        super().__init__()
        self.NODE_FILE_PATH = node_file_path
        self.setContextMenuPolicy(Qt.PreventContextMenu)
        self.blocks = dict()
        self.properties = dict()

        # Graphic buttons
        self.f_buttons = dict()
        self.b_buttons = dict()
        self.p_buttons = dict()

        # Labels
        self.toolbar_tools_label = CustomLabel("Tools")
        self.toolbar_blocks_label = CustomLabel("Nodes")
        self.toolbar_properties_label = CustomLabel("Properties")
        self.isToolbar_tools_label_visible = True
        self.isToolbar_blocks_label_visible = True
        self.isToolbar_properties_label_visible = True

        # Setup view
        self.__display_tools()
        self.__init_blocks()
        self.__display_blocks()
        self.__init_properties()
        self.__display_properties()

        # Toolbar style
        for item in self.children():
            if type(item) is QToolButton:
                item.setStyleSheet("background-color: " + style.GREEN_2)
        self.setStyleSheet(style.TOOLBAR_STYLE)

        self.setOrientation(Qt.Vertical)
        self.setMovable(False)
        self.setFloatable(False)

    def __init_blocks(self):
        """
        Uploading blocks from a JSON file storing them in a dictionary of
        NetworkNode objects.

        """

        with open(self.NODE_FILE_PATH) as json_file:
            blocks_dict = json.loads(json_file.read())

        for k, b in blocks_dict.items():
            self.blocks[k] = NetworkNode(k, b["name"], b["input"],
                                         b["parameters"], b["output"],
                                         b["description"])
            button = NodeButton(k, self.blocks[k])
            button.setToolTip(b["description"])
            self.b_buttons[k] = button

    def __init_properties(self):
        props = ("Generic SMT", "Polyhedral")

        for k in props:
            button = PropertyButton(k)
            button.setToolTip(k)
            self.p_buttons[k] = button

    def __display_tools(self):
        """
        This method adds to the toolbar all buttons related to available tools,
        displaying them in rows in order to have a flexible main_layout in every
        position of the toolbar.

        """

        # Setting the label of the toolbar
        self.addWidget(self.toolbar_tools_label)
        self.toolbar_tools_label.setAlignment(Qt.AlignCenter)
        self.toolbar_tools_label.setStyleSheet(style.NODE_LABEL_STYLE)

        # Setting the first row with horizontal main_layout
        row_1 = QWidget()
        row_1_layout = QHBoxLayout()
        row_1_layout.setSpacing(0)
        row_1_layout.setContentsMargins(0, 0, 0, 0)
        row_1_layout.setAlignment(Qt.AlignCenter)
        row_1.setLayout(row_1_layout)

        # DrawLine mode button
        draw_line_button = CustomButton()
        draw_line_button.setIcon(QIcon(ROOT_DIR + "/res/icons/line.png"))
        draw_line_button.setFixedSize(40, 40)
        draw_line_button.setToolTip("Draw line")

        # Insert block button
        insert_block_button = CustomButton()
        insert_block_button.setIcon(QIcon(ROOT_DIR + "/res/icons/insert.png"))
        insert_block_button.setFixedSize(40, 40)
        insert_block_button.setToolTip("Insert block in edge")

        # Save in a dictionary button references and add the rows to the
        # toolbar
        row_1_layout.addWidget(draw_line_button)
        row_1_layout.addWidget(insert_block_button)
        self.f_buttons["draw_line"] = draw_line_button
        self.f_buttons["insert_block"] = insert_block_button
        self.addWidget(row_1)
        self.addSeparator()

    def __display_blocks(self):
        """
        Graphical blocks are displayed in a vertical main_layout, which is put in
        a movable toolbar of fixed size.

        """

        # Labels
        self.toolbar_blocks_label.setAlignment(Qt.AlignCenter)
        self.toolbar_blocks_label.setStyleSheet(style.NODE_LABEL_STYLE)

        # Buttons
        self.addWidget(self.toolbar_blocks_label)
        for b in self.b_buttons.values():
            self.addWidget(b)

    def __display_properties(self):
        """
        Graphical properties are displayed in a vertical main_layout, which is put in
        a movable toolbar of fixed size.

        """

        # Labels
        self.toolbar_properties_label.setAlignment(Qt.AlignCenter)
        self.toolbar_properties_label.setStyleSheet(style.NODE_LABEL_STYLE)

        # Buttons
        self.addWidget(self.toolbar_properties_label)
        for p in self.p_buttons.values():
            self.addWidget(p)

    def change_tools_mode(self):
        """
        This method handles the visibility of the tool section of the toolbar.
        If all sections are not visible, then the toolbar itself is hidden,
        while if the toolbar was hidden, it is shown with the tools section.

        """

        if not self.isToolbar_tools_label_visible:
            self.show_section(self.toolbar_tools_label, self.f_buttons)
            self.isToolbar_tools_label_visible = True

            if not self.isToolbar_blocks_label_visible:
                self.show()
        else:
            self.hide_section(self.toolbar_tools_label, self.f_buttons)
            self.isToolbar_tools_label_visible = False

            if not self.isToolbar_blocks_label_visible:
                self.hide()

    def change_blocks_mode(self):
        """
        This method handles the visibility of the blocks section of the toolbar.
        If all sections are not visible, then the toolbar itself is hidden,
        while if the toolbar was hidden, it is shown with the blocks section.

        """

        if not self.isToolbar_blocks_label_visible:
            self.show_section(self.toolbar_blocks_label, self.b_buttons)
            self.isToolbar_blocks_label_visible = True

            if not self.isToolbar_tools_label_visible:
                self.show()
        else:
            self.hide_section(self.toolbar_blocks_label, self.b_buttons)
            self.isToolbar_blocks_label_visible = False

            if not self.isToolbar_tools_label_visible:
                self.hide()

    @staticmethod
    def show_section(label: CustomLabel, buttons: dict):
        """
        This method shows the given dictionary of buttons with its label.

        Parameters
        ----------
        label: CustomLabel
        buttons: dict

        """

        label.show()
        label.setStyleSheet(style.NODE_LABEL_STYLE)
        for tool in buttons.values():
            tool.show()

    @staticmethod
    def hide_section(label: CustomLabel, buttons: dict):
        """
        This method hides the given dictionary of buttons with its label.

        Parameters
        ----------
        label: CustomLabel
        buttons: dict

        """

        label.hide()
        label.setStyleSheet(style.HIDDEN_LABEL_STYLE)
        for tool in buttons.values():
            tool.hide()
            if type(tool) is NodeButton:
                tool.setStyleSheet(style.HIDDEN_LABEL_STYLE)
Esempio n. 11
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")